Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/CITATION.cff b/CITATION.cff
index fefe4fccba..e8016a7d89 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -1,37 +1,37 @@
cff-version: 1.2.0
title: MITK
message: >-
If you use this software, please cite it using the
metadata from this file.
type: software
authors:
- given-names: MITK Team
affiliation: German Cancer Research Center (DKFZ)
repository-code: 'https://github.com/MITK/MITK'
url: 'https://www.mitk.org/'
abstract: >-
The Medical Imaging Interaction Toolkit (MITK) is a free
open-source software for the development of interactive
medical image processing software. Based on MITK, we
provide the MITK Workbench, a powerful and free
application to view, process, and segment medical images,
as well as a set of useful commandline applications for
typical image processing tasks like image registration,
conversion, stitching.
keywords:
- dicom
- medical-imaging
- dicom-browser
- medical-image-computing
- cpp-library
- dicom-rt
- mitk
- image-segmentation
- annotation
- image-registration
- perfusion
- visualization
- application-framework
license: BSD-3-Clause
-version: v2022.10
-date-released: '2022-10-29'
+version: v2023.04
+date-released: '2023-05-17'
diff --git a/CMake/BuildConfigurations/All.cmake b/CMake/BuildConfigurations/All.cmake
index 6a3b24125e..2e65fd8460 100644
--- a/CMake/BuildConfigurations/All.cmake
+++ b/CMake/BuildConfigurations/All.cmake
@@ -1,45 +1,44 @@
set(MITK_CONFIG_PACKAGES )
set(_apple_package_excludes)
set(_package_excludes
${_apple_package_excludes}
OpenCL
OpenMP
SYSTEM_Boost
Boost_LIBRARIES
SYSTEM_PYTHON
SUPERBUILD
POLHEMUS_TRACKER
MICROBIRD_TRACKER
MICROBIRD_TRACKER_INCLUDE_DIR
MICROBIRD_TRACKER_LIB
MICRON_TRACKER
OPTITRACK_TRACKER
SPACENAVIGATOR
TOF_KINECT
TOF_KINECTV2
TOF_MESASR4000
TOF_PMDCAMBOARD
TOF_PMDCAMCUBE
TOF_PMDO3
US_TELEMED_SDK
videoInput
- WIIMOTE
)
get_cmake_property(_cache_vars CACHE_VARIABLES)
foreach(_cache_var ${_cache_vars})
string(REGEX REPLACE "MITK_USE_(.+)" "\\1" _package "${_cache_var}")
if(_package AND NOT _package STREQUAL _cache_var)
list(FIND _package_excludes ${_package} _index)
if(_index EQUAL -1)
list(APPEND MITK_CONFIG_PACKAGES ${_package})
endif()
endif()
endforeach()
set(MITK_BUILD_ALL_APPS ON CACHE BOOL "Build all MITK applications" FORCE)
set(MITK_BUILD_ALL_PLUGINS ON CACHE BOOL "Build all MITK plugins" FORCE)
set(MITK_BUILD_EXAMPLES ON CACHE BOOL "Build the MITK examples" FORCE)
set(BLUEBERRY_BUILD_ALL_PLUGINS ON CACHE BOOL "Build all BlueBerry plugins" FORCE)
diff --git a/CMake/BuildConfigurations/ClassificationCmdApps.cmake b/CMake/BuildConfigurations/ClassificationCmdApps.cmake
deleted file mode 100644
index 5b6b3f5cee..0000000000
--- a/CMake/BuildConfigurations/ClassificationCmdApps.cmake
+++ /dev/null
@@ -1,26 +0,0 @@
-#Configuration for a minimal setup to build all cmd apps provided by the core and classification module
-include(${CMAKE_CURRENT_LIST_DIR}/CoreCmdApps.cmake)
-
-set(MITK_WHITELIST "ClassificationCmdApps" CACHE STRING "" FORCE)
-set(MITK_USE_Vigra ON CACHE BOOL "" FORCE)
-
-#Following packages are needed due to the current dependency
-#of some classification cmd apps to QtWidgetExt (see also
-#disucssion in T27702)
-set(MITK_USE_Qt5 ON CACHE BOOL "" FORCE)
-set(MITK_USE_CTK ON CACHE BOOL "" FORCE)
-set(MITK_USE_Qwt ON CACHE BOOL "" FORCE)
-
-#Following packages are needed due to the current dependency
-#of some classification cmd apps to QtWidgetExt (see also
-#disucssion in T27702)
-set(MITK_CONFIG_PACKAGES
- Qt5
- CTK
- Qwt
- Vigra
-)
-
-if(NOT MITK_USE_SUPERBUILD)
- set(BUILD_ClassificationMiniApps ON CACHE BOOL "" FORCE)
-endif()
diff --git a/CMake/BuildConfigurations/Default.cmake b/CMake/BuildConfigurations/Default.cmake
index 700e7efd48..08e48e4bfd 100644
--- a/CMake/BuildConfigurations/Default.cmake
+++ b/CMake/BuildConfigurations/Default.cmake
@@ -1,24 +1,25 @@
set(MITK_CONFIG_PACKAGES
ACVD
Qt5
BLUEBERRY
)
set(MITK_CONFIG_PLUGINS
org.mitk.gui.qt.mitkworkbench.intro
org.mitk.gui.qt.datamanager
org.mitk.gui.qt.stdmultiwidgeteditor
+ org.mitk.gui.qt.mxnmultiwidgeteditor
org.mitk.gui.qt.dicombrowser
org.mitk.gui.qt.imagenavigator
org.mitk.gui.qt.measurementtoolbox
org.mitk.gui.qt.properties
org.mitk.gui.qt.segmentation
org.mitk.gui.qt.volumevisualization
org.mitk.planarfigure
org.mitk.gui.qt.moviemaker
org.mitk.gui.qt.pointsetinteraction
org.mitk.gui.qt.remeshing
org.mitk.gui.qt.viewnavigator
org.mitk.gui.qt.imagecropper
org.mitk.gui.qt.pixelvalue
)
diff --git a/CMake/BuildConfigurations/PhenotypingRelease.cmake b/CMake/BuildConfigurations/PhenotypingRelease.cmake
deleted file mode 100644
index 15c1467ec2..0000000000
--- a/CMake/BuildConfigurations/PhenotypingRelease.cmake
+++ /dev/null
@@ -1,15 +0,0 @@
-include(${CMAKE_CURRENT_LIST_DIR}/WorkbenchRelease.cmake)
-
-list(APPEND MITK_CONFIG_PACKAGES
- Vigra
-)
-
-list(APPEND MITK_CONFIG_PLUGINS
- org.mitk.gui.qt.basicimageprocessing
- org.mitk.gui.qt.radiomics
-)
-
-if(NOT MITK_USE_SUPERBUILD)
- set(BUILD_BasicImageProcessingMiniApps ON CACHE BOOL "" FORCE)
- set(BUILD_ClassificationMiniApps ON CACHE BOOL "" FORCE)
-endif()
diff --git a/CMake/BuildConfigurations/WorkbenchRelease.cmake b/CMake/BuildConfigurations/WorkbenchRelease.cmake
index db7bf09cd6..0163c6a085 100644
--- a/CMake/BuildConfigurations/WorkbenchRelease.cmake
+++ b/CMake/BuildConfigurations/WorkbenchRelease.cmake
@@ -1,28 +1,29 @@
include(${CMAKE_CURRENT_LIST_DIR}/Default.cmake)
set(MITK_CONFIG_PACKAGES ${MITK_CONFIG_PACKAGES}
MatchPoint
)
set(MITK_CONFIG_PLUGINS ${MITK_CONFIG_PLUGINS}
org.mitk.matchpoint.core.helper
org.mitk.gui.qt.matchpoint.algorithm.browser
org.mitk.gui.qt.matchpoint.algorithm.control
org.mitk.gui.qt.matchpoint.mapper
org.mitk.gui.qt.matchpoint.framereg
org.mitk.gui.qt.matchpoint.visualizer
org.mitk.gui.qt.matchpoint.evaluator
org.mitk.gui.qt.matchpoint.manipulator
)
if(NOT MITK_USE_SUPERBUILD)
set(BUILD_CoreCmdApps ON CACHE BOOL "" FORCE)
set(BUILD_MatchPointCmdApps ON CACHE BOOL "" FORCE)
+ set(BUILD_SegmentationCmdApps ON CACHE BOOL "" FORCE)
endif()
set(MITK_VTK_DEBUG_LEAKS OFF CACHE BOOL "Enable VTK Debug Leaks" FORCE)
find_package(Doxygen REQUIRED)
# Ensure that the in-application help can be build
set(BLUEBERRY_QT_HELP_REQUIRED ON CACHE BOOL "Required Qt help documentation in plug-ins" FORCE)
diff --git a/CMake/Findlz4.cmake b/CMake/Findlz4.cmake
deleted file mode 100644
index e9c68dccc4..0000000000
--- a/CMake/Findlz4.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-find_path(lz4_INCLUDE_DIR lz4.h
- PATHS ${MITK_EXTERNAL_PROJECT_PREFIX}
- PATH_SUFFIXES include
- NO_DEFAULT_PATH
-)
-mark_as_advanced(lz4_INCLUDE_DIR)
-
-
-find_library(lz4_LIBRARY_RELEASE lz4
- PATHS ${MITK_EXTERNAL_PROJECT_PREFIX}
- PATH_SUFFIXES lib lib64
- NO_DEFAULT_PATH)
-mark_as_advanced(lz4_LIBRARY_RELEASE)
-
-
-find_library(lz4_LIBRARY_DEBUG lz4d
- PATHS ${MITK_EXTERNAL_PROJECT_PREFIX}
- PATH_SUFFIXES lib lib64
- NO_DEFAULT_PATH)
-mark_as_advanced(lz4_LIBRARY_DEBUG)
-
-set(lz4_LIBRARIES)
-
-if(lz4_LIBRARY_RELEASE)
- list(APPEND lz4_LIBRARIES optimized ${lz4_LIBRARY_RELEASE})
-endif()
-
-if(lz4_LIBRARY_DEBUG)
- list(APPEND lz4_LIBRARIES debug ${lz4_LIBRARY_DEBUG})
-endif()
-
-find_package_handle_standard_args(lz4
- FOUND_VAR lz4_FOUND
- REQUIRED_VARS lz4_INCLUDE_DIR lz4_LIBRARIES
-)
diff --git a/CMake/PackageDepends/MITK_Boost_Config.cmake b/CMake/PackageDepends/MITK_Boost_Config.cmake
index 7275754c8a..1413f203ea 100644
--- a/CMake/PackageDepends/MITK_Boost_Config.cmake
+++ b/CMake/PackageDepends/MITK_Boost_Config.cmake
@@ -1,15 +1,15 @@
-set(Boost_ADDITIONAL_VERSIONS "1.80.0" "1.80")
+set(Boost_ADDITIONAL_VERSIONS "1.82.0" "1.82")
find_package(Boost REQUIRED COMPONENTS ${Boost_REQUIRED_COMPONENTS_BY_MODULE})
if(Boost_REQUIRED_COMPONENTS_BY_MODULE)
foreach(boost_component ${Boost_REQUIRED_COMPONENTS_BY_MODULE})
list(APPEND ALL_LIBRARIES "Boost::${boost_component}")
endforeach()
endif()
list(APPEND ALL_LIBRARIES "Boost::boost")
if(MSVC)
list(APPEND ALL_LIBRARIES "Boost::dynamic_linking" "bcrypt")
endif()
diff --git a/CMake/PackageDepends/MITK_Vigra_Config.cmake b/CMake/PackageDepends/MITK_Vigra_Config.cmake
deleted file mode 100644
index 87f8c25534..0000000000
--- a/CMake/PackageDepends/MITK_Vigra_Config.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-list(APPEND ALL_INCLUDE_DIRECTORIES ${Vigra_INCLUDE_DIRS})
-list(APPEND ALL_LIBRARIES vigraimpex)
-
diff --git a/CMake/PackageDepends/MITK_lz4_Config.cmake b/CMake/PackageDepends/MITK_lz4_Config.cmake
deleted file mode 100644
index b9b2b8ff86..0000000000
--- a/CMake/PackageDepends/MITK_lz4_Config.cmake
+++ /dev/null
@@ -1,2 +0,0 @@
-list(APPEND ALL_INCLUDE_DIRECTORIES ${lz4_INCLUDE_DIR})
-list(APPEND ALL_LIBRARIES ${lz4_LIBRARIES})
diff --git a/CMake/Whitelists/ClassificationCmdApps.cmake b/CMake/Whitelists/ClassificationCmdApps.cmake
deleted file mode 100644
index 19011af613..0000000000
--- a/CMake/Whitelists/ClassificationCmdApps.cmake
+++ /dev/null
@@ -1,20 +0,0 @@
-include(${CMAKE_CURRENT_LIST_DIR}/CoreCmdApps.cmake)
-
-list(APPEND enabled_modules
- Classification
- CLCore
- CLVigraRandomForest
- CLUtilities
- CLMRUtilities
- CLImportanceWeighting
- Segmentation
- DataCollection
- SurfaceInterpolation
- GraphAlgorithms
- ImageStatistics
- ImageExtraction
- PlanarFigure
- QtWidgets
- QtWidgetsExt
-)
-
diff --git a/CMake/Whitelists/FlowBenchSegmentation.cmake b/CMake/Whitelists/FlowBenchSegmentation.cmake
index 60c1587601..c0eedb2dfb 100644
--- a/CMake/Whitelists/FlowBenchSegmentation.cmake
+++ b/CMake/Whitelists/FlowBenchSegmentation.cmake
@@ -1,55 +1,54 @@
set(enabled_modules
Core
CppMicroServices
DICOM
DICOMPM
DataTypesExt
AlgorithmsExt
DICOMQI
Multilabel
SceneSerializationBase
DICOMPMIO
DICOMImageIO
ContourModel
DICOMSegIO
LegacyGL
MapperExt
SceneSerialization
LegacyIO
IOExt
MultilabelIO
AppUtil
QtWidgets
QtWidgetsExt
Segmentation
SegmentationUI
PlanarFigure
Annotation
SurfaceInterpolation
GraphAlgorithms
ImageExtraction
ImageStatistics
)
set(enabled_plugins
org.blueberry.core.commands
org.blueberry.core.expressions
org.blueberry.core.runtime
org.blueberry.ui.qt
org.blueberry.ui.qt.help
org.blueberry.ui.qt.log
-org.mitk.core.ext
org.mitk.core.services
org.mitk.gui.common
org.mitk.gui.qt.application
org.mitk.gui.qt.common
org.mitk.gui.qt.datamanager
org.mitk.gui.qt.ext
org.mitk.gui.qt.flow.segmentation
org.mitk.gui.qt.flowapplication
org.mitk.gui.qt.imagenavigator
org.mitk.gui.qt.properties
org.mitk.gui.qt.segmentation
org.mitk.gui.qt.stdmultiwidgeteditor
org.mitk.planarfigure
)
diff --git a/CMake/manifest.xml.in b/CMake/manifest.xml.in
index 0e42726234..09d3679994 100644
--- a/CMake/manifest.xml.in
+++ b/CMake/manifest.xml.in
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="${TARGET}" version="6.0.0.0"/>
<application>
<windowsSettings>
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
+ <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>
diff --git a/CMake/mitkFunctionCreateBlueBerryApplication.cmake b/CMake/mitkFunctionCreateBlueBerryApplication.cmake
index ebbcaaade2..f56c9fc100 100644
--- a/CMake/mitkFunctionCreateBlueBerryApplication.cmake
+++ b/CMake/mitkFunctionCreateBlueBerryApplication.cmake
@@ -1,235 +1,235 @@
#!
#! Create a BlueBerry application.
#!
#! \brief This function will create a BlueBerry application together with all
#! necessary provisioning and configuration data and install support.
#!
#! \param NAME (required) The name of the executable.
#! \param DESCRIPTION (optional) A human-readable description of your application.
#! The usage depends on the CPack generator (on Windows, this is a descriptive
#! text for the created shortcuts).
#! \param SOURCES (optional) A list of source files to compile into your executable. Defaults
#! to <name>.cpp.
#! \param PLUGINS (optional) A list of required plug-ins. Defaults to all known plug-ins.
#! \param EXCLUDE_PLUGINS (optional) A list of plug-ins which should not be used. Mainly
#! useful if PLUGINS was not used.
#! \param LINK_LIBRARIES A list of libraries to be linked with the executable.
#! \param LIBRARY_DIRS A list of directories to pass through to MITK_INSTALL_TARGETS
#! \param NO_PROVISIONING (option) Do not create provisioning files.
#! \param NO_INSTALL (option) Do not install this executable
#!
#! Assuming that there exists a file called <code>MyApp.cpp</code>, an example call looks like:
#! \code
#! mitkFunctionCreateBlueBerryApplication(
#! NAME MyApp
#! DESCRIPTION "MyApp - New ways to explore medical data"
#! EXCLUDE_PLUGINS org.mitk.gui.qt.extapplication
#! )
#! \endcode
#!
function(mitkFunctionCreateBlueBerryApplication)
cmake_parse_arguments(_APP "NO_PROVISIONING;NO_INSTALL" "NAME;DESCRIPTION" "SOURCES;PLUGINS;EXCLUDE_PLUGINS;LINK_LIBRARIES;LIBRARY_DIRS" ${ARGN})
if(NOT _APP_NAME)
message(FATAL_ERROR "NAME argument cannot be empty.")
endif()
if(NOT _APP_SOURCES)
set(_APP_SOURCES ${_APP_NAME}.cpp)
endif()
if(NOT _APP_PLUGINS)
ctkFunctionGetAllPluginTargets(_APP_PLUGINS)
else()
set(_plugins ${_APP_PLUGINS})
set(_APP_PLUGINS)
foreach(_plugin ${_plugins})
string(REPLACE "." "_" _plugin_target ${_plugin})
list(APPEND _APP_PLUGINS ${_plugin_target})
endforeach()
# get all plug-in dependencies
ctkFunctionGetPluginDependencies(_plugin_deps PLUGINS ${_APP_PLUGINS} ALL)
# add the dependencies to the list of application plug-ins
list(APPEND _APP_PLUGINS ${_plugin_deps})
endif()
# -----------------------------------------------------------------------
# Set up include and link dirs for the executable
# -----------------------------------------------------------------------
include_directories(
${org_blueberry_core_runtime_INCLUDE_DIRS}
)
# -----------------------------------------------------------------------
# Add executable icon (Windows)
# -----------------------------------------------------------------------
set(WINDOWS_ICON_RESOURCE_FILE "")
if(WIN32)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/icons/${_APP_NAME}.rc")
set(WINDOWS_ICON_RESOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/icons/${_APP_NAME}.rc")
endif()
endif()
# -----------------------------------------------------------------------
# Create the executable and link libraries
# -----------------------------------------------------------------------
set(_app_compile_flags )
if(WIN32)
set(_app_compile_flags "${_app_compile_flags} -DWIN32_LEAN_AND_MEAN")
endif()
if(MITK_SHOW_CONSOLE_WINDOW)
add_executable(${_APP_NAME} MACOSX_BUNDLE ${_APP_SOURCES} ${WINDOWS_ICON_RESOURCE_FILE})
else()
add_executable(${_APP_NAME} MACOSX_BUNDLE WIN32 ${_APP_SOURCES} ${WINDOWS_ICON_RESOURCE_FILE})
endif()
if(NOT CMAKE_CURRENT_SOURCE_DIR MATCHES "^${CMAKE_SOURCE_DIR}/.*")
foreach(MITK_EXTENSION_DIR ${MITK_ABSOLUTE_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 ${_APP_NAME} PROPERTY FOLDER "${MITK_EXTENSION_ROOT_FOLDER}/Applications")
break()
endif()
endforeach()
else()
set_property(TARGET ${_APP_NAME} PROPERTY FOLDER "${MITK_ROOT_FOLDER}/Applications")
endif()
mitk_use_modules(TARGET ${_APP_NAME} MODULES MitkAppUtil)
set_target_properties(${_APP_NAME} PROPERTIES
COMPILE_FLAGS "${_app_compile_flags}")
target_link_libraries(${_APP_NAME} PRIVATE org_blueberry_core_runtime ${_APP_LINK_LIBRARIES})
if(WIN32)
target_link_libraries(${_APP_NAME} PRIVATE ${QT_QTMAIN_LIBRARY})
endif()
-if(WIN32 AND MITK_UTF8)
+if(WIN32)
mitk_add_manifest(${_APP_NAME})
endif()
# -----------------------------------------------------------------------
# Add executable icon and bundle name (Mac)
# -----------------------------------------------------------------------
if(APPLE)
if( _APP_DESCRIPTION)
set_target_properties(${_APP_NAME} PROPERTIES MACOSX_BUNDLE_NAME "${_APP_DESCRIPTION}")
else()
set_target_properties(${_APP_NAME} PROPERTIES MACOSX_BUNDLE_NAME "${_APP_NAME}")
endif()
set(icon_name "icon.icns")
set(icon_full_path "${CMAKE_CURRENT_SOURCE_DIR}/icons/${icon_name}")
if(EXISTS "${icon_full_path}")
set_target_properties(${_APP_NAME} PROPERTIES MACOSX_BUNDLE_ICON_FILE "${icon_name}")
file(COPY ${icon_full_path} DESTINATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_APP_NAME}.app/Contents/Resources/")
INSTALL (FILES ${icon_full_path} DESTINATION "${_APP_NAME}.app/Contents/Resources/")
endif()
endif()
# -----------------------------------------------------------------------
# Set build time dependencies
# -----------------------------------------------------------------------
# This ensures that all enabled plug-ins are up-to-date when the
# executable is build.
if(_APP_PLUGINS)
ctkMacroGetAllProjectTargetLibraries("${_APP_PLUGINS}" _project_plugins)
if(_APP_EXCLUDE_PLUGINS AND _project_plugins)
set(_exclude_targets)
foreach(_exclude_plugin ${_APP_EXCLUDE_PLUGINS})
string(REPLACE "." "_" _exclude_target ${_exclude_plugin})
list(APPEND _exclude_targets ${_exclude_target})
endforeach()
list(REMOVE_ITEM _project_plugins ${_exclude_targets})
endif()
if(_project_plugins)
add_dependencies(${_APP_NAME} ${_project_plugins})
endif()
endif()
# -----------------------------------------------------------------------
# Additional files needed for the executable
# -----------------------------------------------------------------------
if(NOT _APP_NO_PROVISIONING)
# Create a provisioning file, listing all plug-ins
set(_prov_file "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_APP_NAME}.provisioning")
mitkFunctionCreateProvisioningFile(FILE ${_prov_file}
PLUGINS ${_APP_PLUGINS}
EXCLUDE_PLUGINS ${_APP_EXCLUDE_PLUGINS}
)
endif()
# Create a .ini file for initial parameters
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_APP_NAME}.ini")
configure_file(${_APP_NAME}.ini
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_APP_NAME}.ini)
endif()
# Create batch and VS user files for Windows platforms
include(mitkFunctionCreateWindowsBatchScript)
if(WIN32)
set(template_name "start${_APP_NAME}.bat.in")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${template_name}")
foreach(BUILD_TYPE debug release)
mitkFunctionCreateWindowsBatchScript(${template_name}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/start${_APP_NAME}_${BUILD_TYPE}.bat
${BUILD_TYPE})
endforeach()
endif()
mitkFunctionConfigureVisualStudioUserProjectFile(
NAME ${_APP_NAME}
)
endif(WIN32)
# -----------------------------------------------------------------------
# Install support
# -----------------------------------------------------------------------
if(NOT _APP_NO_INSTALL)
# This installs all third-party CTK plug-ins
mitkFunctionInstallThirdPartyCTKPlugins(${_APP_PLUGINS} EXCLUDE ${_APP_EXCLUDE_PLUGINS})
if(COMMAND BlueBerryApplicationInstallHook)
set(_real_app_plugins ${_APP_PLUGINS})
if(_APP_EXCLUDE_PLUGINS)
list(REMOVE_ITEM _real_app_plugins ${_APP_EXCLUDE_PLUGINS})
endif()
BlueBerryApplicationInstallHook(APP_NAME ${_APP_NAME} PLUGINS ${_real_app_plugins})
endif()
# Install the executable
MITK_INSTALL_TARGETS(EXECUTABLES ${_APP_NAME} LIBRARY_DIRS ${_APP_LIBRARY_DIRS} GLOB_PLUGINS )
if(NOT _APP_NO_PROVISIONING)
# Install the provisioning file
mitkFunctionInstallProvisioningFiles(${_prov_file})
endif()
# On Linux, create a shell script to start a relocatable application
if(UNIX AND NOT APPLE)
install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME "${_APP_NAME}.sh")
elseif(WIN32)
install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledWin32App.bat" DESTINATION "." RENAME "${_APP_NAME}.bat")
endif()
# Tell cpack the executables that you want in the start menu as links
set(MITK_CPACK_PACKAGE_EXECUTABLES ${MITK_CPACK_PACKAGE_EXECUTABLES} "${_APP_NAME};${_APP_DESCRIPTION}" CACHE INTERNAL "Collecting windows shortcuts to executables")
endif()
endfunction()
function(FunctionCreateBlueBerryApplication)
message(SEND_ERROR "The function FunctionCreateBlueBerryApplication was renamed to mitkFunctionCreateBlueBerryApplication in MITK 2015.05")
endfunction()
diff --git a/CMake/mitkFunctionCreateModule.cmake b/CMake/mitkFunctionCreateModule.cmake
index b0a777b921..df45e5d1bc 100644
--- a/CMake/mitkFunctionCreateModule.cmake
+++ b/CMake/mitkFunctionCreateModule.cmake
@@ -1,647 +1,647 @@
##################################################################
#
# 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|Watersheds
#! \endcode
#!
#! The <moduleName> 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
#!
#! \sa mitk_create_executable
#!
#! Parameters (all optional):
#!
#! \param <moduleName> 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 <arg>
#! \param DESCRIPTION A description for this module
#!
#! Multi-value Parameters (all optional):
#!
#! \param INCLUDE_DIRS Include directories for this module:
#! \verbatim
#! [[PUBLIC|PRIVATE|INTERFACE] <dir1>...]...
#! \endverbatim
#! The default scope for include directories is PUBLIC.
#! \param DEPENDS List of module dependencies:
#! \verbatim
#! [[PUBLIC|PRIVATE|INTERFACE] <module1>...]...
#! \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 (deprecated)
INCLUDE_DIRS # include directories: [PUBLIC|PRIVATE|INTERFACE] <list>
INTERNAL_INCLUDE_DIRS # include dirs internal to this module (DEPRECATED)
DEPENDS # list of modules this module depends on: [PUBLIC|PRIVATE|INTERFACE] <list>
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] <package-list>
TARGET_DEPENDS # list of CMake targets this module should depend on: [PUBLIC|PRIVATE|INTERFACE] <list>
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] <list>
)
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 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()
# -----------------------------------------------------------------
# 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.
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"
#
# 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})
# ---------------------------------------------------------------
# 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)
if(MITK_SHOW_CONSOLE_WINDOW)
set(_SHOW_CONSOLE_OPTION "")
else()
set(_SHOW_CONSOLE_OPTION WIN32)
endif()
add_executable(${MODULE_TARGET} ${_SHOW_CONSOLE_OPTION}
${MODULE_CPP_FILES} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP}
${DOX_FILES} ${UI_FILES} ${QRC_FILES} ${WINDOWS_ICON_RESOURCE_FILE})
- if(WIN32 AND MITK_UTF8)
+ if(WIN32)
mitk_add_manifest(${MODULE_TARGET})
endif()
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 $<$<CONFIG:Debug>:${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 $<$<CONFIG:Release>:${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 $<$<CONFIG:Debug>:${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 $<$<CONFIG:Release>:${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)
target_link_libraries(${MODULE_TARGET} ${MODULE_TARGET_DEPENDS})
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()
# 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)
endfunction()
diff --git a/CMake/mitkFunctionCreatePlugin.cmake b/CMake/mitkFunctionCreatePlugin.cmake
index b2d27259d5..8edd95a256 100644
--- a/CMake/mitkFunctionCreatePlugin.cmake
+++ b/CMake/mitkFunctionCreatePlugin.cmake
@@ -1,357 +1,357 @@
#! \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
#! <plugin_target>_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 TARGET_DEPENDS (optional) A list of CMake targets 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
TARGET_DEPENDS
DOXYGEN_TAGFILES
MOC_OPTIONS
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}
)
if(_PLUGIN_TARGET_DEPENDS)
target_link_libraries(${PLUGIN_TARGET} ${_PLUGIN_TARGET_DEPENDS})
endif()
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_ABSOLUTE_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)
mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated-declarations" 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(_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)
+ if(TARGET MitkLog)
+ target_link_libraries(${PLUGIN_TARGET} PRIVATE MitkLog)
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/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake
index 86725d7193..a1fe3a86bc 100644
--- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake
+++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake
@@ -1,213 +1,201 @@
#! Helper function that gets all library search paths.
#!
#! Usage:
#!
#! mitkFunctionGetLibrarySearchPaths(search_path intermediate_dir [DEBUG|MINSIZEREL|RELWITHDEBINFO])
#!
#!
#! The function creates the variable ${search_path}. The variable intermediate_dir contains
#! paths that should be added to the search_path but should not be checked for existance,
#! because the are not yet created. The option DEBUG, MINSIZEREL or RELWITHDEBINFO can be used to indicate that
#! not the paths for release configuration are requested but the debug, min size release or "release with debug info"
#! paths.
#!
function(mitkFunctionGetLibrarySearchPaths search_path intermediate_dir)
cmake_parse_arguments(PARSE_ARGV 2 GLS "RELEASE;DEBUG;MINSIZEREL;RELWITHDEBINFO" "" "")
set(_dir_candidates
"${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
"${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins"
"${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
"${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins"
)
if(MITK_EXTERNAL_PROJECT_PREFIX)
list(APPEND _dir_candidates
"${MITK_EXTERNAL_PROJECT_PREFIX}/bin"
"${MITK_EXTERNAL_PROJECT_PREFIX}/lib"
)
endif()
# Determine the Qt5 library installation prefix
set(_qmake_location )
if(MITK_USE_Qt5 AND TARGET ${Qt5Core_QMAKE_EXECUTABLE})
get_property(_qmake_location TARGET ${Qt5Core_QMAKE_EXECUTABLE}
PROPERTY IMPORT_LOCATION)
endif()
if(_qmake_location)
if(NOT _qt_install_libs)
if(WIN32)
execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_BINS
OUTPUT_VARIABLE _qt_install_libs
OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_LIBS
OUTPUT_VARIABLE _qt_install_libs
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
file(TO_CMAKE_PATH "${_qt_install_libs}" _qt_install_libs)
set(_qt_install_libs ${_qt_install_libs} CACHE INTERNAL "Qt library installation prefix" FORCE)
endif()
if(_qt_install_libs)
list(APPEND _dir_candidates ${_qt_install_libs})
endif()
elseif(MITK_USE_Qt5)
message(WARNING "The qmake executable could not be found.")
endif()
get_property(_additional_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS)
if(TARGET OpenSSL::SSL)
if(GLS_DEBUG)
get_target_property(_openssl_location OpenSSL::SSL IMPORTED_LOCATION_DEBUG)
else()
get_target_property(_openssl_location OpenSSL::SSL IMPORTED_LOCATION_RELEASE)
endif()
if(_openssl_location)
get_filename_component(_openssl_location ${_openssl_location} DIRECTORY)
set(_openssl_location "${_openssl_location}/../../bin")
if(EXISTS ${_openssl_location})
get_filename_component(_openssl_location ${_openssl_location} ABSOLUTE)
list(APPEND _dir_candidates ${_openssl_location})
endif()
endif()
endif()
if(MITK_USE_HDF5)
FIND_PACKAGE(HDF5 COMPONENTS C HL NO_MODULE REQUIRED shared)
get_target_property(_location hdf5-shared LOCATION)
get_filename_component(_location ${_location} PATH)
list(APPEND _additional_paths ${_location})
# This is a work-around. The hdf5-config.cmake file is not robust enough
# to be included several times via find_pakcage calls.
set(HDF5_LIBRARIES ${HDF5_LIBRARIES} PARENT_SCOPE)
endif()
- if(MITK_USE_Vigra)
- # we cannot use _find_package(Vigra) here because the vigra-config.cmake file
- # always includes the target-exports files without using an include guard. This
- # would lead to errors when another find_package(Vigra) call is processed. The
- # (bad) assumption here is that for the time being, only the Classification module
- # is using Vigra.
- if(UNIX)
- list(APPEND _additional_paths ${Vigra_DIR}/lib)
- else()
- list(APPEND _additional_paths ${Vigra_DIR}/bin)
- endif()
- endif()
if(_additional_paths)
list(APPEND _dir_candidates ${_additional_paths})
endif()
# The code below is sub-optimal. It makes assumptions about
# the structure of the build directories, pointed to by
# the *_DIR variables. Instead, we should rely on package
# specific "LIBRARY_DIRS" variables, if they exist.
if(WIN32)
list(APPEND _dir_candidates "${ITK_DIR}/bin")
endif()
if(MITK_USE_MatchPoint)
if(WIN32)
list(APPEND _dir_candidates "${MatchPoint_DIR}/bin")
else()
list(APPEND _dir_candidates "${MatchPoint_DIR}/lib")
endif()
endif()
# If OpenCV is built within the MITK superbuild set the binary directory
# according to the lib path provided by OpenCV.
# In the case where an external OpenCV is provided use the binary directory
# of this OpenCV directory
if(MITK_USE_OpenCV)
if(WIN32)
if (EXISTS ${OpenCV_LIB_PATH})
list(APPEND _dir_candidates "${OpenCV_LIB_PATH}/../bin") # OpenCV is built in superbuild
else()
list(APPEND _dir_candidates "${OpenCV_DIR}/bin") # External OpenCV build is used
endif()
endif()
endif()
if(MITK_USE_Python3)
list(APPEND _dir_candidates "${CTK_DIR}/CMakeExternals/Install/bin")
get_filename_component(_python_dir "${Python3_EXECUTABLE}" DIRECTORY)
list(APPEND _dir_candidates "${_python_dir}")
endif()
if(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD)
list(APPEND _dir_candidates "${MITK_PMD_SDK_DIR}/plugins" "${MITK_PMD_SDK_DIR}/bin")
endif()
if(MITK_USE_CTK)
list(APPEND _dir_candidates "${CTK_LIBRARY_DIRS}")
foreach(_ctk_library ${CTK_LIBRARIES})
if(${_ctk_library}_LIBRARY_DIRS)
list(APPEND _dir_candidates "${${_ctk_library}_LIBRARY_DIRS}")
endif()
endforeach()
endif()
if(MITK_USE_BLUEBERRY)
if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY)
if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}")
list(APPEND _dir_candidates "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}")
else()
list(APPEND _dir_candidates "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}")
endif()
endif()
endif()
if(MITK_LIBRARY_DIRS)
list(APPEND _dir_candidates ${MITK_LIBRARY_DIRS})
endif()
###################################################################
#get the search paths added by the mitkFunctionAddLibrarySearchPath
file(GLOB _additional_path_info_files "${MITK_SUPERBUILD_BINARY_DIR}/MITK-AdditionalLibPaths/*.cmake")
foreach(_additional_path_info_file ${_additional_path_info_files})
get_filename_component(_additional_info_name ${_additional_path_info_file} NAME_WE)
include(${_additional_path_info_file})
if(GLS_DEBUG)
list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_DEBUG_LIBRARY_SEARCH_PATHS})
elseif(GLS_MINSIZEREL)
list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_MINSIZEREL_LIBRARY_SEARCH_PATHS})
elseif(GLS_RELWITHDEBINFO)
list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_RELWITHDEBINFO_LIBRARY_SEARCH_PATHS})
else() #Release
list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_RELEASE_LIBRARY_SEARCH_PATHS})
endif()
endforeach(_additional_path_info_file ${_additional_path_info_files})
###############################################
#sanitize all candidates and compile final list
list(REMOVE_DUPLICATES _dir_candidates)
set(_search_dirs )
foreach(_dir ${_dir_candidates})
if(EXISTS "${_dir}/${intermediate_dir}")
list(APPEND _search_dirs "${_dir}/${intermediate_dir}")
else()
list(APPEND _search_dirs "${_dir}")
endif()
endforeach()
# Special handling for "internal" search dirs. The intermediate directory
# might not have been created yet, so we can't check for its existence.
# Hence we just add it for Windows without checking.
set(_internal_search_dirs "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins")
if(WIN32)
foreach(_dir ${_internal_search_dirs})
set(_search_dirs "${_dir}/${intermediate_dir}" ${_search_dirs})
endforeach()
else()
set(_search_dirs ${_internal_search_dirs} ${_search_dirs})
endif()
list(REMOVE_DUPLICATES _search_dirs)
set(${search_path} ${_search_dirs} PARENT_SCOPE)
endfunction()
diff --git a/CMake/mitkSwigAddLibraryDependencies.cmake b/CMake/mitkSwigAddLibraryDependencies.cmake
index bdcf1bffa9..5b46f0fc8f 100644
--- a/CMake/mitkSwigAddLibraryDependencies.cmake
+++ b/CMake/mitkSwigAddLibraryDependencies.cmake
@@ -1,30 +1,30 @@
#! This CMake macro adds the necessary library and incllude
#! directories to a swig-project.
#!
#! params:
#! swig_module : Name of the SWIG module, for example pyMITK
-#! library_names : Semicolon separated list of the libraries that are included, for example "MitkCore;mbilog"
+#! library_names : Semicolon separated list of the libraries that are included, for example "MitkCore;MitkLog"
#!
# function inspired by
# https://stackoverflow.com/questions/37205274/swig-and-cmake-make-use-of-information-provided-by-target-include-directories
# This function tells cmake which additional dependencies are existing
# especially with respect to the linker dependencies.
function(mitkSwigAddLibraryDependencies swig_module library_names)
foreach(library_name ${library_names})
# Adding each library as a linker dependency:
swig_link_libraries(${swig_module} ${library_name})
# Extracting all include directories from each given project and
# then including these directories to the newly created swig project.
get_property(LIBRARY_INCLUDES
TARGET ${library_name}
PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
# Checking each given librarie to include all includes from this library.
endforeach()
# In addition include python dependencies:
include_directories( ${PYTHON_INCLUDE_DIR})
endfunction()
diff --git a/CMake/mitkTestDriverFiles.cmake.in b/CMake/mitkTestDriverFiles.cmake.in
index 78583f9b24..c7538a7495 100644
--- a/CMake/mitkTestDriverFiles.cmake.in
+++ b/CMake/mitkTestDriverFiles.cmake.in
@@ -1,47 +1,47 @@
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/files.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/files.cmake)
endif()
# Write a header file containing include directives and custom code
# for the test driver.
set(TESTDRIVER_EXTRA_INCLUDES )
-list(APPEND MODULE_TEST_EXTRA_DRIVER_INCLUDE "mitkLog.h")
+list(APPEND MODULE_TEST_EXTRA_DRIVER_INCLUDE "mitkLogBackend.h")
list(REMOVE_DUPLICATES MODULE_TEST_EXTRA_DRIVER_INCLUDE)
foreach(_include ${MODULE_TEST_EXTRA_DRIVER_INCLUDE})
set(TESTDRIVER_EXTRA_INCLUDES "${TESTDRIVER_EXTRA_INCLUDES}
#include <${_include}>")
endforeach()
set(TESTDRIVER_EXTRA_INCLUDES "${TESTDRIVER_EXTRA_INCLUDES}
#include <vector>
std::vector<std::string> globalCmdLineArgs;")
set(_extra_include_file ${CMAKE_CURRENT_BINARY_DIR}/${TESTDRIVER}_extras.h)
configure_file(${MITK_CMAKE_DIR}/mitkTestDriverExtraIncludes.h.in ${_extra_include_file})
set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "
for (int avIndex = 1; avIndex < ac; ++avIndex) globalCmdLineArgs.push_back(av[avIndex]);
-mitk::LoggingBackend::Register();
+mitk::LogBackend::Register();
${MODULE_TEST_EXTRA_DRIVER_INIT};"
)
-set(CMAKE_TESTDRIVER_AFTER_TESTMAIN "mitk::LoggingBackend::Unregister();")
+set(CMAKE_TESTDRIVER_AFTER_TESTMAIN "mitk::LogBackend::Unregister();")
create_test_sourcelist(_test_cpp_files ${MODULE_NAME}_main.cpp
${MODULE_TESTS} ${MODULE_RENDERING_TESTS} ${MODULE_IMAGE_TESTS} ${MODULE_SURFACE_TESTS} ${MODULE_CUSTOM_TESTS}
EXTRA_INCLUDE ${_extra_include_file}
)
list(APPEND CPP_FILES ${_test_cpp_files})
# Some old CMake scripts use TEST_CPP_FILES in their files.cmake
# file of the test driver to add source fiels to the executable
# (they should just use CPP_FILES like in any other files.cmake
# file instead).
if(TEST_CPP_FILES)
list(APPEND CPP_FILES ${TEST_CPP_FILES})
endif()
if(MODULE_RESOURCE_FILES)
list(APPEND RESOURCE_FILES ${MODULE_RESOURCE_FILES})
endif()
diff --git a/CMakeExternals/ACVD.cmake b/CMakeExternals/ACVD.cmake
index 5409265ccd..db0876ebc3 100644
--- a/CMakeExternals/ACVD.cmake
+++ b/CMakeExternals/ACVD.cmake
@@ -1,50 +1,50 @@
#-----------------------------------------------------------------------------
# ACVD
#-----------------------------------------------------------------------------
if(MITK_USE_ACVD)
# Sanity checks
if(DEFINED ACVD_DIR AND NOT EXISTS ${ACVD_DIR})
message(FATAL_ERROR "ACVD_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj ACVD)
set(proj_DEPENDENCIES VTK)
set(ACVD_DEPENDS ${proj})
if(NOT DEFINED ACVD_DIR)
set(additional_args )
if(CTEST_USE_LAUNCHERS)
list(APPEND additional_args
"-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
)
endif()
ExternalProject_Add(${proj}
LIST_SEPARATOR ${sep}
GIT_REPOSITORY https://github.com/valette/ACVD.git
- GIT_TAG e583e278
+ GIT_TAG 18209c90
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${ep_common_args}
${additional_args}
-DUSE_MULTITHREADING:BOOL=ON
-DBUILD_EXAMPLES:BOOL=OFF
-DQt5_DIR:PATH=${Qt5_DIR}
-DVTK_DIR:PATH=${VTK_DIR}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
DEPENDS ${proj_DEPENDENCIES}
)
set(ACVD_DIR ${ep_prefix})
mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeExternals/Boost.cmake b/CMakeExternals/Boost.cmake
index dcebc7c38b..bf50d36881 100644
--- a/CMakeExternals/Boost.cmake
+++ b/CMakeExternals/Boost.cmake
@@ -1,343 +1,343 @@
#-----------------------------------------------------------------------------
# Boost
#-----------------------------------------------------------------------------
include(mitkFunctionGetMSVCVersion)
#[[ Sanity checks ]]
if(DEFINED BOOST_ROOT AND NOT EXISTS ${BOOST_ROOT})
message(FATAL_ERROR "BOOST_ROOT variable is defined but corresponds to non-existing directory")
endif()
string(REPLACE "^^" ";" MITK_USE_Boost_LIBRARIES "${MITK_USE_Boost_LIBRARIES}")
set(proj Boost)
set(proj_DEPENDENCIES )
set(Boost_DEPENDS ${proj})
if(NOT DEFINED BOOST_ROOT AND NOT MITK_USE_SYSTEM_Boost)
#[[ Reset variables. ]]
set(patch_cmd "")
set(configure_cmd "")
set(install_cmd "")
set(BOOST_ROOT ${ep_prefix})
- set(Boost_DIR "${BOOST_ROOT}/lib/cmake/Boost-1.80.0")
+ set(Boost_DIR "${BOOST_ROOT}/lib/cmake/Boost-1.82.0")
if(WIN32)
set(BOOST_LIBRARYDIR "${BOOST_ROOT}/lib")
endif()
#[[ If you update Boost, make sure that the FindBoost module of the minimum
required version of CMake supports the new version of Boost.
In case you are using a higher version of CMake, download at least the
source code of the minimum required version of CMake to look into the
right version of the FindBoost module:
<CMAKE_INSTALL_DIR>/share/cmake-<VERSION>/Modules/FindBoost.cmake
Search for a list called _Boost_KNOWN_VERSIONS. If the new version is
not included in this list, you have three options:
* Update the minimum required version of CMake. This may require
adaptions of other parts of our CMake scripts and has the most
impact on other MITK developers. Yet this is the safest and
cleanest option.
* Set Boost_ADDITIONAL_VERSIONS (see the documentation of the
FindBoost module). As Boost libraries and dependencies between
them are hard-coded in the FindBoost module only for known versions,
this may cause trouble for other MITK developers relying on new
components of Boost or components with changed dependencies.
* Copy a newer version of the FindBoost module into our CMake
directory. Our CMake directory has a higher precedence than the
default CMake module directory. Doublecheck if the minimum required
version of CMake is able to process the newer version of the
FindBoost module. Also, DO NOT FORGET to mention this option right
above the call of cmake_minimum_required() in the top-level
CMakeLists.txt file AND in this file right above the set(url)
command below so if we update the minimum required version of CMake
or use another option in the future, we do not forget to remove our
copy of the FindBoost module again. ]]
- set(url "${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/boost_1_80_0.tar.gz")
- set(md5 077f074743ea7b0cb49c6ed43953ae95)
+ set(url "${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/boost_1_82_0.tar.gz")
+ set(md5 f7050f554a65f6a42ece221eaeec1660)
if(MITK_USE_Boost_LIBRARIES)
#[[ Boost has a two-step build process. In the first step, a bootstrap
script is called to build b2, an executable that is used to actually
build Boost in the second step.
The bootstrap script expects a toolset (compiler) argument that is
used to build the b2 executable. The scripts and their expected
argument format differ between Windows and Unix. ]]
if(WIN32)
mitkFunctionGetMSVCVersion()
if(VISUAL_STUDIO_VERSION_MINOR EQUAL 0)
#[[ Use just the major version in the toolset name. ]]
set(bootstrap_args vc${VISUAL_STUDIO_VERSION_MAJOR})
elseif(VISUAL_STUDIO_VERSION_MAJOR EQUAL 14 AND VISUAL_STUDIO_VERSION_MINOR LESS 20)
#[[ Assume Visual Studio 2017. ]]
set(bootstrap_args vc${VISUAL_STUDIO_VERSION_MAJOR}1)
elseif(VISUAL_STUDIO_VERSION_MAJOR EQUAL 14 AND VISUAL_STUDIO_VERSION_MINOR LESS 30)
#[[ Assume Visual Studio 2019. ]]
set(bootstrap_args vc${VISUAL_STUDIO_VERSION_MAJOR}2)
elseif(VISUAL_STUDIO_VERSION_MAJOR EQUAL 14 AND VISUAL_STUDIO_VERSION_MINOR LESS 40)
#[[ Assume Visual Studio 2022. ]]
set(bootstrap_args vc${VISUAL_STUDIO_VERSION_MAJOR}3)
else()
#[[ Fallback to the generic case. Be prepared to add another elseif
branch above for future versions of Visual Studio. ]]
set(bootstrap_args vc${VISUAL_STUDIO_VERSION_MAJOR})
endif()
else()
#[[ We support GCC and Clang on Unix. On macOS, the toolset must be set
to clang. The actual compiler for all of these toolkits is set
further below, after the bootstrap script but before b2. ]]
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)
set(toolset gcc)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang OR APPLE)
set(toolset clang)
endif()
if(toolset)
set(bootstrap_args --with-toolset=${toolset})
endif()
#[[ At least give it a shot if the toolset is something else and let
the bootstrap script decide on the toolset by not passing any
argument. ]]
endif()
#[[ The call of b2 is more complex. b2 arguments are grouped into options
and properties. Options follow the standard format for arguments while
properties are plain key-value pairs. ]]
set(b2_options
--build-dir=<BINARY_DIR>
--stagedir=<INSTALL_DIR>
--ignore-site-config #[[ Build independent of any site.config file ]]
-q #[[ Stop at first error ]]
)
if(APPLE AND CMAKE_OSX_SYSROOT)
#[[ Specify the macOS platform SDK to be used. ]]
list(APPEND b2_options --sysroot=${CMAKE_OSX_SYSROOT})
endif()
foreach(lib ${MITK_USE_Boost_LIBRARIES})
list(APPEND b2_options --with-${lib})
endforeach()
set(b2_properties
threading=multi
runtime-link=shared
"cxxflags=${MITK_CXX${MITK_CXX_STANDARD}_FLAG} ${CMAKE_CXX_FLAGS}"
)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
list(APPEND b2_properties address-model=64)
else()
list(APPEND b2_properties address-model=32)
endif()
if(BUILD_SHARED_LIBS)
list(APPEND b2_properties link=shared)
else()
list(APPEND b2_properties link=static)
endif()
list(APPEND b2_properties "\
$<$<CONFIG:Debug>:variant=debug>\
$<$<CONFIG:Release>:variant=release>\
$<$<CONFIG:MinSizeRel>:variant=release>\
$<$<CONFIG:RelWithDebInfo>:variant=release>")
if(WIN32)
set(bootstrap_cmd if not exist b2.exe \( call bootstrap.bat ${bootstrap_args} \))
set(b2_cmd b2 ${b2_options} ${b2_properties} stage)
else()
set(bootstrap_cmd #[[ test -e ./b2 || ]] ./bootstrap.sh ${bootstrap_args})
set(b2_cmd ./b2 ${b2_options} ${b2_properties} stage)
#[[ We already told Boost if we want to use GCC or Clang but so far we
were not able to specify the exact same compiler we set in CMake
when configuring the MITK superbuild for the first time.
For example, this can be different from the system default
when multiple versions of the same compiler are installed
at the same time.
The bootstrap script creates a configuration file for b2 that should
be modified if necessary before b2 is called.
We look for a line like
using gcc ;
and replace it with something more specific like
using gcc : : /usr/bin/gcc-7.3 ;
We use the stream editor sed for the replacement but since macOS is
based on BSD Unix, we use the limited but portable BSD syntax
instead of the more powerful GNU syntax. We also use | instead of
the more commonly used / separator for sed because the replacement
contains slashes.
2021/06/15: The custom project-config.jam does not work well with
SDK paths on macOS anymore, so we use a custom project-config.jam
only on Linux for now. ]]
if(toolset AND NOT APPLE)
set(configure_cmd sed -i.backup "\
s|\
using[[:space:]][[:space:]]*${toolset}[[:space:]]*$<SEMICOLON>|\
using ${toolset} : : ${CMAKE_CXX_COMPILER} $<SEMICOLON>|\
g"
<SOURCE_DIR>/project-config.jam
)
endif()
endif()
endif()
if(WIN32)
set(dummy_cmd cd .)
else()
set(dummy_cmd true) #[[ "cd ." does not work reliably ]]
endif()
if(NOT patch_cmd)
set(patch_cmd ${dummy_cmd}) #[[ Do nothing ]]
endif()
if(NOT configure_cmd)
set(configure_cmd ${dummy_cmd}) #[[ Do nothing ]]
endif()
if(WIN32)
set(install_cmd
if not exist $<SHELL_PATH:${ep_prefix}/include/boost/config.hpp>
\( ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/boost <INSTALL_DIR>/include/boost \)
)
else()
set(install_cmd
# test -e <INSTALL_DIR>/include/boost/config.hpp ||
${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/boost <INSTALL_DIR>/include/boost
)
endif()
ExternalProject_Add(${proj}
URL ${url}
URL_MD5 ${md5}
PATCH_COMMAND ${patch_cmd}
CONFIGURE_COMMAND ${configure_cmd}
BUILD_COMMAND ""
INSTALL_COMMAND ${install_cmd}
)
ExternalProject_Add_Step(${proj} bootstrap
COMMAND ${bootstrap_cmd}
DEPENDEES patch
DEPENDERS configure
WORKING_DIRECTORY <SOURCE_DIR>
)
ExternalProject_Add_Step(${proj} b2
COMMAND ${b2_cmd}
DEPENDEES bootstrap
DEPENDERS build
WORKING_DIRECTORY <SOURCE_DIR>
)
if(WIN32)
#[[ Reuse already extracted files. ]]
set(stamp_dir ${ep_prefix}/src/Boost-stamp)
configure_file(
${CMAKE_CURRENT_LIST_DIR}/extract-Boost.replacement.cmake
${stamp_dir}/extract-Boost.replacement.cmake
COPYONLY)
ExternalProject_Add_Step(${proj} pre_download
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/Boost-pre_download.cmake
DEPENDEES mkdir
DEPENDERS download
WORKING_DIRECTORY ${stamp_dir}
)
endif()
set(install_manifest_dependees install)
if(MITK_USE_Boost_LIBRARIES)
if(WIN32)
#[[ Move DLLs from lib to bin directory. ]]
ExternalProject_Add_Step(${proj} post_install
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/Boost-post_install-WIN32.cmake
DEPENDEES install
WORKING_DIRECTORY <INSTALL_DIR>/lib
)
set(install_manifest_dependees post_install)
elseif(APPLE)
#[[ Boost does not follow the common practice of either using rpath or
absolute paths for referencing dependencies. We have to use the
install_name_tool to fix this. ]]
ExternalProject_Add_Step(${proj} post_install
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/Boost-post_install-APPLE.cmake
DEPENDEES install
WORKING_DIRECTORY <INSTALL_DIR>/lib
)
set(install_manifest_dependees post_install)
endif()
endif()
ExternalProject_Add_Step(${proj} install_manifest
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/Boost-install_manifest.cmake
DEPENDEES ${install_manifest_dependees}
WORKING_DIRECTORY ${ep_prefix}
)
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
diff --git a/CMakeExternals/DCMQI.cmake b/CMakeExternals/DCMQI.cmake
index 3ab55c42e1..b3e26f60e7 100644
--- a/CMakeExternals/DCMQI.cmake
+++ b/CMakeExternals/DCMQI.cmake
@@ -1,69 +1,69 @@
#-----------------------------------------------------------------------------
# DCMQI
#-----------------------------------------------------------------------------
if(MITK_USE_DCMQI)
# Sanity checks
if(DEFINED DCMQI_DIR AND NOT EXISTS ${DCMQI_DIR})
message(FATAL_ERROR "DCMQI_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj DCMQI)
set(proj_DEPENDENCIES DCMTK ITK)
set(DCMQI_DEPENDS ${proj})
if(NOT DEFINED DCMQI_DIR)
set(additional_cmake_args)
if(CTEST_USE_LAUNCHERS)
list(APPEND additional_cmake_args
"-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
)
endif()
if(MITK_USE_OpenCV)
list(APPEND additional_cmake_args "-DCMAKE_CONFIGURATION_TYPES:STRING=Debug$<SEMICOLON>Release")
endif()
mitk_query_custom_ep_vars()
ExternalProject_Add(${proj}
LIST_SEPARATOR ${sep}
GIT_REPOSITORY https://github.com/QIICR/dcmqi.git
- GIT_TAG v1.2.4
+ GIT_TAG v1.2.5
UPDATE_COMMAND ""
INSTALL_COMMAND ""
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${ep_common_args}
${additional_cmake_args}
#-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DBUILD_SHARED_LIBS:BOOL=ON
-DDCMQI_BUILD_APPS:BOOL=OFF
-DDCMTK_DIR:PATH=${DCMTK_DIR}
-DITK_DIR:PATH=${ITK_DIR}
-DITK_NO_IO_FACTORY_REGISTER_MANAGER:BOOL=ON
-DDCMQI_SUPERBUILD:BOOL=OFF
-DDCMQI_CMAKE_CXX_STANDARD:STRING=${MITK_CXX_STANDARD}
${${proj}_CUSTOM_CMAKE_ARGS}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
${${proj}_CUSTOM_CMAKE_CACHE_ARGS}
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
${${proj}_CUSTOM_CMAKE_CACHE_DEFAULT_ARGS}
DEPENDS ${proj_DEPENDENCIES}
)
ExternalProject_Get_Property(${proj} binary_dir)
set(DCMQI_DIR ${binary_dir})
#set(${proj}_DIR ${ep_prefix})
#message(${proj}_DIR: ${${proj}_DIR})
#mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeExternals/ExternalProjectList.cmake b/CMakeExternals/ExternalProjectList.cmake
index 4567614685..87e25a67e0 100644
--- a/CMakeExternals/ExternalProjectList.cmake
+++ b/CMakeExternals/ExternalProjectList.cmake
@@ -1,34 +1,33 @@
mitkFunctionAddExternalProject(NAME Poco ON COMPONENTS Foundation Net Util XML Zip)
mitkFunctionAddExternalProject(NAME DCMTK ON DOC "EXPERIMENTAL, superbuild only: Use DCMTK in MITK")
mitkFunctionAddExternalProject(NAME OpenIGTLink OFF)
mitkFunctionAddExternalProject(NAME tinyxml2 ON ADVANCED)
mitkFunctionAddExternalProject(NAME GDCM ON ADVANCED)
mitkFunctionAddExternalProject(NAME Eigen ON ADVANCED DOC "Use the Eigen library")
mitkFunctionAddExternalProject(NAME ANN ON ADVANCED DOC "Use Approximate Nearest Neighbor Library")
mitkFunctionAddExternalProject(NAME CppUnit ON ADVANCED DOC "Use CppUnit for unit tests")
mitkFunctionAddExternalProject(NAME HDF5 ON ADVANCED)
mitkFunctionAddExternalProject(NAME OpenCV OFF)
-mitkFunctionAddExternalProject(NAME Vigra OFF DEPENDS HDF5)
mitkFunctionAddExternalProject(NAME ITK ON NO_CACHE DEPENDS HDF5)
mitkFunctionAddExternalProject(NAME VTK ON NO_CACHE)
mitkFunctionAddExternalProject(NAME Boost ON NO_CACHE)
mitkFunctionAddExternalProject(NAME ZLIB OFF ADVANCED)
mitkFunctionAddExternalProject(NAME lz4 ON ADVANCED)
mitkFunctionAddExternalProject(NAME cpprestsdk OFF DEPENDS Boost ZLIB ADVANCED)
mitkFunctionAddExternalProject(NAME ACVD OFF DOC "Use Approximated Centroidal Voronoi Diagrams")
mitkFunctionAddExternalProject(NAME CTK ON DEPENDS Qt5 DCMTK DOC "Use CTK in MITK")
mitkFunctionAddExternalProject(NAME DCMQI ON DEPENDS DCMTK ITK DOC "Use dcmqi in MITK")
mitkFunctionAddExternalProject(NAME MatchPoint OFF ADVANCED DEPENDS Boost ITK DOC "Use the MatchPoint translation image registration library")
mitkFunctionAddExternalProject(NAME nlohmann_json ON ADVANCED)
mitkFunctionAddExternalProject(NAME httplib OFF DEPENDS ZLIB)
if(MITK_USE_Qt5)
mitkFunctionAddExternalProject(NAME Qwt ON ADVANCED DEPENDS Qt5)
endif()
if(UNIX AND NOT APPLE)
mitkFunctionAddExternalProject(NAME PCRE OFF ADVANCED NO_PACKAGE)
mitkFunctionAddExternalProject(NAME SWIG OFF ADVANCED NO_PACKAGE DEPENDS PCRE)
elseif(WIN32)
mitkFunctionAddExternalProject(NAME SWIG OFF ADVANCED NO_PACKAGE)
endif()
diff --git a/CMakeExternals/ITK.cmake b/CMakeExternals/ITK.cmake
index b6ab2759cd..59b448cc79 100644
--- a/CMakeExternals/ITK.cmake
+++ b/CMakeExternals/ITK.cmake
@@ -1,89 +1,90 @@
#-----------------------------------------------------------------------------
# ITK
#-----------------------------------------------------------------------------
# Sanity checks
if(DEFINED ITK_DIR AND NOT EXISTS ${ITK_DIR})
message(FATAL_ERROR "ITK_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj ITK)
set(proj_DEPENDENCIES GDCM)
if(MITK_USE_OpenCV)
list(APPEND proj_DEPENDENCIES OpenCV)
endif()
if(MITK_USE_HDF5)
list(APPEND proj_DEPENDENCIES HDF5)
endif()
set(ITK_DEPENDS ${proj})
if(NOT DEFINED ITK_DIR)
set(additional_cmake_args -DUSE_WRAP_ITK:BOOL=OFF)
list(APPEND additional_cmake_args
-DITKV4_COMPATIBILITY:BOOL=OFF
-DITK_LEGACY_REMOVE:BOOL=ON
)
if(MITK_USE_OpenCV)
list(APPEND additional_cmake_args
-DModule_ITKVideoBridgeOpenCV:BOOL=ON
-DOpenCV_DIR:PATH=${OpenCV_DIR}
"-DCMAKE_CONFIGURATION_TYPES:STRING=Debug$<SEMICOLON>Release"
)
endif()
# Keep the behaviour of ITK 4.3 which by default turned on ITK Review
# see MITK bug #17338
list(APPEND additional_cmake_args
-DModule_ITKReview:BOOL=ON
-DModule_ITKOpenJPEG:BOOL=ON # for 4.7, the OpenJPEG is needed by review but the variable must be set
-DModule_IsotropicWavelets:BOOL=ON
)
if(CTEST_USE_LAUNCHERS)
list(APPEND additional_cmake_args
"-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
)
endif()
mitk_query_custom_ep_vars()
ExternalProject_Add(${proj}
LIST_SEPARATOR ${sep}
UPDATE_COMMAND ""
GIT_REPOSITORY https://github.com/MITK/ITK.git
- GIT_TAG v5.2.1-patched
+ GIT_TAG v5.3.0-patched
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${ep_common_args}
${additional_cmake_args}
+ -DITK_SKIP_PATH_LENGTH_CHECKS:BOOL=ON
-DBUILD_EXAMPLES:BOOL=OFF
-DITK_USE_SYSTEM_GDCM:BOOL=ON
-DGDCM_DIR:PATH=${GDCM_DIR}
-DITK_USE_SYSTEM_HDF5:BOOL=ON
-DHDF5_DIR:PATH=${HDF5_DIR}
-DModule_GrowCut:BOOL=ON
${${proj}_CUSTOM_CMAKE_ARGS}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
${${proj}_CUSTOM_CMAKE_CACHE_ARGS}
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
${${proj}_CUSTOM_CMAKE_CACHE_DEFAULT_ARGS}
DEPENDS ${proj_DEPENDENCIES}
)
set(ITK_DIR ${ep_prefix})
mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
diff --git a/CMakeExternals/MatchPoint.cmake b/CMakeExternals/MatchPoint.cmake
index cc551e875d..6d988f1658 100644
--- a/CMakeExternals/MatchPoint.cmake
+++ b/CMakeExternals/MatchPoint.cmake
@@ -1,76 +1,76 @@
#-----------------------------------------------------------------------------
# MatchPoint
#-----------------------------------------------------------------------------
if(MITK_USE_MatchPoint)
set(MatchPoint_SOURCE_DIR "" CACHE PATH "Location of the MatchPoint source directory")
mark_as_advanced(MatchPoint_SOURCE_DIR)
# Sanity checks
if(DEFINED MatchPoint_DIR AND NOT EXISTS ${MatchPoint_DIR})
message(FATAL_ERROR "MatchPoint_DIR variable is defined but corresponds to non-existing directory")
endif()
if(NOT MatchPoint_DIR AND MatchPoint_SOURCE_DIR AND NOT EXISTS ${MatchPoint_SOURCE_DIR})
message(FATAL_ERROR "MatchPoint_SOURCE_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj MatchPoint)
set(proj_DEPENDENCIES Boost ITK)
set(MatchPoint_DEPENDS ${proj})
if(NOT MatchPoint_DIR)
set(additional_cmake_args)
if(MITK_USE_OpenCV)
list(APPEND additional_cmake_args "-DCMAKE_CONFIGURATION_TYPES:STRING=Debug$<SEMICOLON>Release")
endif()
if(MatchPoint_SOURCE_DIR)
set(download_step SOURCE_DIR ${MatchPoint_SOURCE_DIR})
else()
set(download_step
GIT_REPOSITORY https://github.com/MIC-DKFZ/MatchPoint.git
- GIT_TAG e63dfdbb
+ GIT_TAG a45efdf9
)
endif()
string(REPLACE "-DBOOST_ALL_DYN_LINK" "" modified_ep_common_args "${ep_common_args}")
ExternalProject_Add(${proj}
${download_step}
# INSTALL_COMMAND "${CMAKE_COMMAND} -P cmake_install.cmake"
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${modified_ep_common_args}
${additional_cmake_args}
-DBUILD_TESTING:BOOL=OFF
-DITK_DIR:PATH=${ITK_DIR} #/src/ITK-build
"-DBoost_DIR:PATH=${Boost_DIR}"
-DMAP_USE_SYSTEM_GDCM:BOOL=ON
-DMAP_USE_SYSTEM_HDF5:BOOL=ON
-DMAP_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER:BOOL=ON
-DMAP_WRAP_Plastimatch:BOOL=ON
-DMAP_BUILD_Ontology:BOOL=ON
-DMAP_BUILD_Ontology_simple:BOOL=ON
-DGDCM_DIR:PATH=${GDCM_DIR}
-DHDF5_DIR:PATH=${HDF5_DIR}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
DEPENDS ${proj_DEPENDENCIES}
)
ExternalProject_Get_Property(${proj} binary_dir)
set(${proj}_DIR ${binary_dir})
mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif(MITK_USE_MatchPoint)
diff --git a/CMakeExternals/Poco.cmake b/CMakeExternals/Poco.cmake
index 22b544244f..9a3ccd0794 100644
--- a/CMakeExternals/Poco.cmake
+++ b/CMakeExternals/Poco.cmake
@@ -1,103 +1,103 @@
#-----------------------------------------------------------------------------
# Poco
#-----------------------------------------------------------------------------
if(MITK_USE_Poco)
# Sanity checks
if(DEFINED Poco_DIR AND NOT EXISTS ${Poco_DIR})
message(FATAL_ERROR "Poco_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj Poco)
set(proj_DEPENDENCIES )
set(${proj}_DEPENDS ${proj})
if(NOT DEFINED ${proj}_DIR)
set(additional_cmake_args )
if(CTEST_USE_LAUNCHERS)
list(APPEND additional_cmake_args
"-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
)
endif()
mitk_query_custom_ep_vars()
set(ssl_args
-DENABLE_CRYPTO:BOOL=OFF
-DENABLE_NETSSL:BOOL=OFF
-DENABLE_NETSSL_WIN:BOOL=OFF
)
if(OpenSSL_FOUND)
set(ssl_args
-DENABLE_CRYPTO:BOOL=ON
-DENABLE_NETSSL:BOOL=ON
-DFORCE_OPENSSL:BOOL=ON
)
if(OPENSSL_ROOT_DIR)
list(APPEND ssl_args
"-DOPENSSL_ROOT_DIR:PATH=${OPENSSL_ROOT_DIR}"
)
endif()
endif()
ExternalProject_Add(${proj}
LIST_SEPARATOR ${sep}
GIT_REPOSITORY https://github.com/pocoproject/poco.git
- GIT_TAG poco-1.12.2-release
+ GIT_TAG poco-1.12.4-release
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${ep_common_args}
${additional_cmake_args}
${ssl_args}
-DENABLE_ACTIVERECORD:BOOL=OFF
-DENABLE_ACTIVERECORD_COMPILER:BOOL=OFF
-DENABLE_APACHECONNECTOR:BOOL=OFF
-DENABLE_CPPPARSER:BOOL=OFF
-DENABLE_DATA:BOOL=OFF
-DENABLE_DATA_MYSQL:BOOL=OFF
-DENABLE_DATA_ODBC:BOOL=OFF
-DENABLE_DATA_POSTGRESQL:BOOL=OFF
-DENABLE_DATA_SQLITE:BOOL=OFF
-DENABLE_ENCODINGS:BOOL=OFF
-DENABLE_ENCODINGS_COMPILER:BOOL=OFF
-DENABLE_FOUNDATION:BOOL=ON
-DENABLE_JSON:BOOL=ON
-DENABLE_JWT:BOOL=OFF
-DENABLE_MONGODB:BOOL=OFF
-DENABLE_NET:BOOL=ON
-DENABLE_PAGECOMPILER:BOOL=OFF
-DENABLE_PAGECOMPILER_FILE2PAGE:BOOL=OFF
-DENABLE_PDF:BOOL=OFF
-DENABLE_POCODOC:BOOL=OFF
-DENABLE_PROMETHEUS:BOOL=OFF
-DENABLE_REDIS:BOOL=OFF
-DENABLE_SEVENZIP:BOOL=OFF
-DENABLE_TESTS:BOOL=OFF
-DENABLE_UTIL:BOOL=ON
-DENABLE_XML:BOOL=ON
-DENABLE_ZIP:BOOL=ON
${${proj}_CUSTOM_CMAKE_ARGS}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
${${proj}_CUSTOM_CMAKE_CACHE_ARGS}
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
${${proj}_CUSTOM_CMAKE_CACHE_DEFAULT_ARGS}
DEPENDS ${proj_DEPENDENCIES}
)
set(${proj}_DIR ${ep_prefix})
mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake
index 69fa6d4da1..b68a539504 100644
--- a/CMakeExternals/VTK.cmake
+++ b/CMakeExternals/VTK.cmake
@@ -1,85 +1,88 @@
#-----------------------------------------------------------------------------
# VTK
#-----------------------------------------------------------------------------
# Sanity checks
if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR})
message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj VTK)
set(proj_DEPENDENCIES )
set(VTK_DEPENDS ${proj})
if(NOT DEFINED VTK_DIR)
set(additional_cmake_args )
if(WIN32)
list(APPEND additional_cmake_args
-DCMAKE_CXX_MP_FLAG:BOOL=ON
)
else()
list(APPEND additional_cmake_args
-DVTK_MODULE_USE_EXTERNAL_VTK_freetype:BOOL=ON
)
endif()
# Optionally enable memory leak checks for any objects derived from vtkObject. This
# will force unit tests to fail if they have any of these memory leaks.
option(MITK_VTK_DEBUG_LEAKS OFF)
mark_as_advanced(MITK_VTK_DEBUG_LEAKS)
list(APPEND additional_cmake_args
-DVTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS}
)
if(MITK_USE_Qt5)
list(APPEND additional_cmake_args
-DVTK_GROUP_ENABLE_Qt:STRING=YES
-DQt5_DIR:PATH=${Qt5_DIR}
)
endif()
if(CTEST_USE_LAUNCHERS)
list(APPEND additional_cmake_args
"-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
)
endif()
mitk_query_custom_ep_vars()
ExternalProject_Add(${proj}
LIST_SEPARATOR ${sep}
GIT_REPOSITORY https://github.com/Kitware/VTK.git
- GIT_TAG v9.1.0
+ GIT_TAG v9.2.6
GIT_SUBMODULES ""
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${ep_common_args}
-DOpenGL_GL_PREFERENCE:STRING=LEGACY
-DVTK_ENABLE_WRAPPING:BOOL=OFF
-DVTK_LEGACY_REMOVE:BOOL=ON
-DVTK_MODULE_ENABLE_VTK_TestingRendering:STRING=YES
-DVTK_MODULE_ENABLE_VTK_RenderingContextOpenGL2:STRING=YES
-DVTK_MODULE_ENABLE_VTK_RenderingVolumeOpenGL2:STRING=YES
-DVTK_MODULE_ENABLE_VTK_GUISupportQtQuick:STRING=NO
+ -DVTK_MODULE_ENABLE_VTK_IOIOSS:STRING=NO # See T29633
+ -DVTK_MODULE_ENABLE_VTK_ioss:STRING=NO # See T29633
+ -DVTK_QT_VERSION:STRING=5
${additional_cmake_args}
${${proj}_CUSTOM_CMAKE_ARGS}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
${${proj}_CUSTOM_CMAKE_CACHE_ARGS}
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
${${proj}_CUSTOM_CMAKE_CACHE_DEFAULT_ARGS}
DEPENDS ${proj_DEPENDENCIES}
)
set(VTK_DIR ${ep_prefix})
mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
diff --git a/CMakeExternals/Vigra.cmake b/CMakeExternals/Vigra.cmake
deleted file mode 100644
index 5b2c4ddd22..0000000000
--- a/CMakeExternals/Vigra.cmake
+++ /dev/null
@@ -1,71 +0,0 @@
-#-----------------------------------------------------------------------------
-# VIGRA
-#-----------------------------------------------------------------------------
-
-if(MITK_USE_Vigra)
-
- # Sanity checks
- if(DEFINED Vigra_DIR AND NOT EXISTS ${Vigra_DIR})
- message(FATAL_ERROR "Vigra_DIR variable is defined but corresponds to non-existing directory")
- endif()
-
- if(NOT ${MITK_USE_HDF5})
- message(FATAL_ERROR "HDF5 is required for Vigra. Please enable it.")
- endif()
-
- set(proj Vigra)
- set(proj_DEPENDENCIES HDF5)
- set(Vigra_DEPENDS ${proj})
-
- # If a mac ports installation is present some imaging-io-libraries may interfere with the vigra build.
- # Hence, we exclude them here.
- set(mac_additional_cmake_args)
- if(APPLE)
- set(mac_additional_cmake_args
- -DJPEG_INCLUDE_DIR=
- -DJPEG_LIBRARY=
- -DTIFF_INCLUDE_DIR=
- -DTIFF_LIBRARY=
- -DPNG_LIBRARY_RELEASE=
- -DPNG_PNG_INCLUDE_DIR=
- )
- endif()
-
- if(NOT DEFINED Vigra_DIR)
-
- set(additional_cmake_args )
- if(CTEST_USE_LAUNCHERS)
- list(APPEND additional_cmake_args
- "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
- )
- endif()
-
- ExternalProject_Add(${proj}
- GIT_REPOSITORY https://github.com/MITK/vigra.git
- GIT_TAG Version-1-10-0-patched
- CMAKE_GENERATOR ${gen}
- CMAKE_GENERATOR_PLATFORM ${gen_platform}
- CMAKE_ARGS
- ${ep_common_args}
- ${additional_cmake_args}
- ${mac_additional_cmake_args}
- -DAUTOEXEC_TESTS:BOOL=OFF
- -DWITH_VIGRANUMPY:BOOL=OFF
- -DHDF5_DIR:PATH=${HDF5_DIR}
- -DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=TRUE
- -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
- CMAKE_CACHE_ARGS
- ${ep_common_cache_args}
- CMAKE_CACHE_DEFAULT_ARGS
- ${ep_common_cache_default_args}
- DEPENDS ${proj_DEPENDENCIES}
- )
-
- set(Vigra_DIR ${ep_prefix})
-
- else()
-
- mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
-
- endif()
-endif(MITK_USE_Vigra)
diff --git a/CMakeExternals/Vigra.patch b/CMakeExternals/Vigra.patch
deleted file mode 100644
index 8002ed96bb..0000000000
--- a/CMakeExternals/Vigra.patch
+++ /dev/null
@@ -1,519 +0,0 @@
-diff -urNb vigra-Version-1-10-0/CMakeLists.txt Vigra/CMakeLists.txt
---- vigra-Version-1-10-0/CMakeLists.txt 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/CMakeLists.txt 2015-03-03 10:13:57.693725000 +0100
-@@ -70,7 +70,12 @@ IF(WITH_OPENEXR)
- ENDIF()
-
- IF(WITH_HDF5)
-+ FIND_PACKAGE(HDF5 PATHS ${HDF5_DIR} PATH_SUFFIXES hdf5 NO_DEFAULT_PATH NO_MODULE)
-+ IF(NOT HDF5_FOUND)
- VIGRA_FIND_PACKAGE(HDF5)
-+ ENDIF()
-+ # HDF5 changed their config, this ports the new style to the old style
-+ set(HDF5_LIBRARIES ${HDF5_EXPORT_LIBRARIES})
- ENDIF()
-
- IF(WITH_BOOST_GRAPH)
-@@ -395,3 +398,4 @@
- ENDIF()
-
- MESSAGE( STATUS "---------------------------------------------------------" )
-+
-diff -urNb vigra-Version-1-10-0/config/VigraConfig.cmake.in Vigra/config/VigraConfig.cmake.in
---- vigra-Version-1-10-0/config/VigraConfig.cmake.in 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/config/VigraConfig.cmake.in 2015-03-03 10:13:57.693725000 +0100
-@@ -1,7 +1,9 @@
- get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
- get_filename_component(Vigra_TOP_DIR "${SELF_DIR}/../../" ABSOLUTE)
-
--include(${SELF_DIR}/vigra-targets.cmake)
-+if(NOT TARGET vigraimpex)
-+ include(${SELF_DIR}/vigra-targets.cmake)
-+endif()
- get_target_property(VIGRA_TYPE vigraimpex TYPE)
- if(${VIGRA_TYPE} STREQUAL "STATIC_LIBRARY")
- SET(VIGRA_STATIC_LIB True)
-@@ -12,3 +14,4 @@
- IF(EXISTS ${SELF_DIR}/../vigranumpy/VigranumpyConfig.cmake)
- INCLUDE(${SELF_DIR}/../vigranumpy/VigranumpyConfig.cmake)
- ENDIF()
-+
-diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_common.hxx Vigra/include/vigra/random_forest/rf_common.hxx
---- vigra-Version-1-10-0/include/vigra/random_forest/rf_common.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/random_forest/rf_common.hxx 2015-07-08 18:55:16.000000000 +0200
-@@ -558,6 +558,7 @@
- int is_weighted_; // class_weights_ are used
- double precision_; // termination criterion for regression loss
- int response_size_;
-+ int max_tree_depth;
-
- template<class T>
- void to_classlabel(int index, T & out) const
-@@ -583,7 +584,8 @@
- EQUALS(class_weights_),
- EQUALS(is_weighted_),
- EQUALS(precision_),
-- EQUALS(response_size_)
-+ EQUALS(response_size_),
-+ EQUALS(max_tree_depth)
- {
- std::back_insert_iterator<ArrayVector<Label_t> >
- iter(classes);
-@@ -604,7 +606,8 @@
- EQUALS(class_weights_),
- EQUALS(is_weighted_),
- EQUALS(precision_),
-- EQUALS(response_size_)
-+ EQUALS(response_size_),
-+ EQUALS(max_tree_depth)
- {
- std::back_insert_iterator<ArrayVector<Label_t> >
- iter(classes);
-@@ -624,7 +627,8 @@
- EQUALS(used_);
- EQUALS(is_weighted_);
- EQUALS(precision_);
-- EQUALS(response_size_)
-+ EQUALS(response_size_);
-+ EQUALS(max_tree_depth)
- class_weights_.clear();
- std::back_insert_iterator<ArrayVector<double> >
- iter2(class_weights_);
-@@ -648,7 +652,8 @@
- EQUALS(used_);
- EQUALS(is_weighted_);
- EQUALS(precision_);
-- EQUALS(response_size_)
-+ EQUALS(response_size_);
-+ EQUALS(max_tree_depth)
- class_weights_.clear();
- std::back_insert_iterator<ArrayVector<double> >
- iter2(class_weights_);
-@@ -677,7 +682,8 @@
- COMPARE(used_);
- COMPARE(class_weights_);
- COMPARE(classes);
-- COMPARE(response_size_)
-+ COMPARE(response_size_);
-+ COMPARE(max_tree_depth)
- #undef COMPARE
- return result;
- }
-@@ -715,6 +721,7 @@
- PULL(used_, int);
- PULL(precision_, double);
- PULL(response_size_, int);
-+ PULL(max_tree_depth, int);
- if(is_weighted_)
- {
- vigra_precondition(end - begin == 10 + 2*class_count_,
-@@ -747,6 +754,7 @@
- PUSH(used_);
- PUSH(precision_);
- PUSH(response_size_);
-+ PUSH(max_tree_depth);
- if(is_weighted_)
- {
- std::copy(class_weights_.begin(),
-@@ -773,6 +781,7 @@
- PULL(used_, int);
- PULL(precision_, double);
- PULL(response_size_, int);
-+ PULL(max_tree_depth, int);
- class_weights_ = in["class_weights_"];
- #undef PUSH
- }
-@@ -789,6 +798,7 @@
- PUSH(used_);
- PUSH(precision_);
- PUSH(response_size_);
-+ PUSH(max_tree_depth);
- in["class_weights_"] = class_weights_;
- #undef PUSH
- }
-@@ -805,7 +815,8 @@
- used_(false),
- is_weighted_(false),
- precision_(0.0),
-- response_size_(1)
-+ response_size_(1),
-+ max_tree_depth(50)
- {}
-
-
-@@ -857,7 +868,7 @@
- is_weighted_ = false;
- precision_ = 0.0;
- response_size_ = 0;
--
-+ max_tree_depth = 50;
- }
-
- bool used() const
-diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_decisionTree.hxx Vigra/include/vigra/random_forest/rf_decisionTree.hxx
---- vigra-Version-1-10-0/include/vigra/random_forest/rf_decisionTree.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/random_forest/rf_decisionTree.hxx 2015-07-08 18:55:16.000000000 +0200
-@@ -90,6 +90,8 @@
- ProblemSpec<> ext_param_;
- unsigned int classCount_;
-
-+ std::map<int, int> m_Parents;
-+
-
- public:
- /* \brief Create tree with parameters */
-@@ -350,6 +352,22 @@
- continueLearn(features,labels,stack_entry,split,stop,visitor,randint);
- }
-
-+template < class TRandomForest>
-+int GetTreeDepthForNode(int nodeIndex, TRandomForest* rf)
-+{
-+ int depth = 0;
-+ while (true)
-+ {
-+ if (nodeIndex < 1)
-+ {
-+ break;
-+ }
-+ ++depth;
-+ nodeIndex = rf->m_Parents[nodeIndex];
-+ }
-+ return depth;
-+}
-+
- template < class U, class C,
- class U2, class C2,
- class StackEntry_t,
-@@ -374,6 +392,11 @@
- size_t last_node_pos = 0;
- StackEntry_t top=stack.back();
-
-+ Split_t* splitPointer = &split;
-+ bool isDepthSplitter = true;
-+
-+ int maximumTreeDepth = splitPointer->GetMaximumTreeDepth();
-+
- while(!stack.empty())
- {
-
-@@ -392,7 +415,20 @@
- //kind of node to make
- TreeInt NodeID;
-
-- if(stop(top))
-+ bool depthStop = false;
-+ if (isDepthSplitter)
-+ {
-+ int currentDepthLevel;
-+ if (top.leftParent != StackEntry_t::DecisionTreeNoParent)
-+ currentDepthLevel = GetTreeDepthForNode(top.leftParent, this);
-+ else
-+ currentDepthLevel = GetTreeDepthForNode(top.rightParent, this);
-+
-+ depthStop = (currentDepthLevel >= maximumTreeDepth);
-+ }
-+ if(stop(top) || (depthStop))
-+
-+ //if (stop(top) || currentDepthLevel >= MaximumSplitDepth(split))
- NodeID = split.makeTerminalNode(features,
- labels,
- top,
-@@ -421,17 +457,20 @@
- // Using InteriorNodeBase because exact parameter form not needed.
- // look at the Node base before getting scared.
- last_node_pos = topology_.size();
-+ m_Parents[last_node_pos] = StackEntry_t::DecisionTreeNoParent;
- if(top.leftParent != StackEntry_t::DecisionTreeNoParent)
- {
- NodeBase(topology_,
- parameters_,
- top.leftParent).child(0) = last_node_pos;
-+ m_Parents[last_node_pos] = top.leftParent;
- }
- else if(top.rightParent != StackEntry_t::DecisionTreeNoParent)
- {
- NodeBase(topology_,
- parameters_,
- top.rightParent).child(1) = last_node_pos;
-+ m_Parents[last_node_pos] = top.rightParent;
- }
-
-
-diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_nodeproxy.hxx Vigra/include/vigra/random_forest/rf_nodeproxy.hxx
---- vigra-Version-1-10-0/include/vigra/random_forest/rf_nodeproxy.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/random_forest/rf_nodeproxy.hxx 2015-07-08 18:55:16.000000000 +0200
-@@ -50,7 +50,11 @@
- namespace vigra
- {
-
--
-+class DepthSplitterBase
-+{
-+public:
-+ virtual int GetMaximumTreeDepth() const = 0;
-+};
-
- enum NodeTags
- {
-diff -urNb vigra-Version-1-10-0/include/vigra/random_forest/rf_split.hxx Vigra/include/vigra/random_forest/rf_split.hxx
---- vigra-Version-1-10-0/include/vigra/random_forest/rf_split.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/random_forest/rf_split.hxx 2015-07-08 18:55:16.000000000 +0200
-@@ -108,6 +108,11 @@
- \ref SplitBase::findBestSplit() or \ref SplitBase::makeTerminalNode().
- **/
-
-+ virtual int GetMaximumTreeDepth() const
-+ {
-+ return ext_param_.max_tree_depth;
-+ }
-+
- template<class T>
- void set_external_parameters(ProblemSpec<T> const & in)
- {
-diff -urNb vigra-Version-1-10-0/include/vigra/random_forest.hxx Vigra/include/vigra/random_forest.hxx
---- vigra-Version-1-10-0/include/vigra/random_forest.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/random_forest.hxx 2015-07-15 14:08:18.548277915 +0200
-@@ -165,6 +165,7 @@
- ProblemSpec_t ext_param_;
- /*mutable ArrayVector<int> tree_indices_;*/
- rf::visitors::OnlineLearnVisitor online_visitor_;
-+ bool multithreadPrediction; // enable/disable multithreaded predictProbabilities and predictLabels
-
-
- void reset()
-@@ -584,6 +585,18 @@
- {
- vigra_precondition(features.shape(0) == labels.shape(0),
- "RandomForest::predictLabels(): Label array has wrong size.");
-+ if (multithreadPrediction)
-+ {
-+#pragma omp parallel for
-+ for(int k=0; k<features.shape(0); ++k)
-+ {
-+ vigra_precondition(!detail::contains_nan(rowVector(features, k)),
-+ "RandomForest::predictLabels(): NaN in feature matrix.");
-+ labels(k,0) = detail::RequiresExplicitCast<T>::cast(predictLabel(rowVector(features, k), rf_default()));
-+ }
-+ }
-+ else
-+ {
- for(int k=0; k<features.shape(0); ++k)
- {
- vigra_precondition(!detail::contains_nan(rowVector(features, k)),
-@@ -591,6 +604,7 @@
- labels(k,0) = detail::RequiresExplicitCast<T>::cast(predictLabel(rowVector(features, k), rf_default()));
- }
- }
-+ }
-
- /** \brief predict multiple labels with given features
- *
-@@ -1261,6 +1275,60 @@
- }
- */
- //Classify for each row.
-+ if (multithreadPrediction)
-+ {
-+#pragma omp parallel for
-+ for(int row=0; row < rowCount(features); ++row)
-+ {
-+ MultiArrayView<2, U, StridedArrayTag> currentRow(rowVector(features, row));
-+
-+ // when the features contain an NaN, the instance doesn't belong to any class
-+ // => indicate this by returning a zero probability array.
-+ if(detail::contains_nan(currentRow))
-+ {
-+ rowVector(prob, row).init(0.0);
-+ continue;
-+ }
-+
-+ ArrayVector<double>::const_iterator weights;
-+
-+ //totalWeight == totalVoteCount!
-+ double totalWeight = 0.0;
-+
-+ //Let each tree classify...
-+ for(int k=0; k<options_.tree_count_; ++k)
-+ {
-+ //get weights predicted by single tree
-+ weights = trees_[k /*tree_indices_[k]*/].predict(currentRow);
-+
-+ //update votecount.
-+ int weighted = options_.predict_weighted_;
-+ for(int l=0; l<ext_param_.class_count_; ++l)
-+ {
-+ double cur_w = weights[l] * (weighted * (*(weights-1))
-+ + (1-weighted));
-+ prob(row, l) += (T)cur_w;
-+ //every weight in totalWeight.
-+ totalWeight += cur_w;
-+ }
-+ if(stop.after_prediction(weights,
-+ k,
-+ rowVector(prob, row),
-+ totalWeight))
-+ {
-+ break;
-+ }
-+ }
-+
-+ //Normalise votes in each row by total VoteCount (totalWeight
-+ for(int l=0; l< ext_param_.class_count_; ++l)
-+ {
-+ prob(row, l) /= detail::RequiresExplicitCast<T>::cast(totalWeight);
-+ }
-+ }
-+ }
-+ else
-+ {
- for(int row=0; row < rowCount(features); ++row)
- {
- MultiArrayView<2, U, StridedArrayTag> currentRow(rowVector(features, row));
-@@ -1309,6 +1377,7 @@
- prob(row, l) /= detail::RequiresExplicitCast<T>::cast(totalWeight);
- }
- }
-+ }
-
- }
-
-diff -u -r Vigra.orig/include/vigra/imagecontainer.hxx Vigra/include/vigra/imagecontainer.hxx
---- Vigra.orig/include/vigra/imagecontainer.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/imagecontainer.hxx 2017-08-26 11:02:40.079669325 +0200
-@@ -760,7 +760,7 @@
- /** swap contents of this array with the contents of other
- (STL-Container interface)
- */
-- void swap(const ImagePyramid<ImageType, Alloc> &other)
-+ void swap(ImagePyramid<ImageType, Alloc> &other)
- {
- images_.swap(other.images_);
- std::swap(lowestLevel_, other.lowestLevel_);
-diff -urNb vigra-Version-1-10-0/include/vigra/functortraits.hxx Vigra/include/vigra/functortraits.hxx
---- vigra-Version-1-10-0/include/vigra/functortraits.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/functortraits.hxx 2022-03-17 15:15:01.637026200 +0100
-@@ -195,8 +195,6 @@
- VIGRA_DEFINE_STL_FUNCTOR(std::negate, VigraTrueType, VigraFalseType)
- VIGRA_DEFINE_STL_FUNCTOR(std::logical_not, VigraTrueType, VigraFalseType)
- VIGRA_DEFINE_STL_FUNCTOR(std::unary_negate, VigraTrueType, VigraFalseType)
--VIGRA_DEFINE_STL_FUNCTOR(std::binder1st, VigraTrueType, VigraFalseType)
--VIGRA_DEFINE_STL_FUNCTOR(std::binder2nd, VigraTrueType, VigraFalseType)
- #undef VIGRA_DEFINE_STL_FUNCTOR
-
- template <class R>
-diff -urNb vigra-Version-1-10-0/src/impex/imageinfo.cxx Vigra/src/impex/imageinfo.cxx
---- vigra-Version-1-10-0/src/impex/imageinfo.cxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/src/impex/imageinfo.cxx 2022-03-17 15:22:20.975223000 +0100
-@@ -1016,7 +1016,7 @@
- do
- {
- numEndIt = std::find_if(numBeginIt, filename.rend(),(int (*)(int)) &isdigit);
-- numBeginIt = std::find_if(numEndIt, filename.rend(), not1(std::ptr_fun((int (*)(int))&isdigit)));
-+ numBeginIt = std::find_if(numEndIt, filename.rend(), std::not_fn((int (*)(int))&isdigit));
-
- if(numEndIt != filename.rend())
- {
-diff -urNb vigra-1.10.0-src/include/vigra/separableconvolution.hxx Vigra/include/vigra/separableconvolution.hxx
---- vigra-1.10.0-src/include/vigra/separableconvolution.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/separableconvolution.hxx 2022-03-17 23:08:05.690694437 +0100
-@@ -1409,9 +1409,6 @@
- {}
-
- ~InitProxy()
--#ifndef _MSC_VER
-- throw(PreconditionViolation)
--#endif
- {
- vigra_precondition(count_ == 1 || count_ == sum_,
- "Kernel1D::initExplicitly(): "
-diff -urNb vigra-1.10.0-src/src/impex/gif.cxx Vigra/src/impex/gif.cxx
---- vigra-1.10.0-src/src/impex/gif.cxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/src/impex/gif.cxx 2022-03-17 23:17:05.896364451 +0100
-@@ -482,12 +482,12 @@
- in_code,
- old_code;
-
-- register int
-+ int
- bits,
- code,
- count;
-
-- register unsigned long
-+ unsigned long
- datum;
-
- void_vector<Int16> prefix(MaxStackSize);
-@@ -496,8 +496,8 @@
- void_vector<UInt8> packet(256);
- void_vector<UInt16> indices(header.width*header.height);
-
-- register UInt8 *c;
-- register UInt16 *p = indices.begin();
-+ UInt8 *c;
-+ UInt16 *p = indices.begin();
-
- UInt8
- data_size,
-@@ -624,7 +624,7 @@
-
- int pass, x, y;
-
-- register UInt16 *q;
-+ UInt16 *q;
-
- static int
- interlace_rate[4] = { 8, 8, 4, 2 },
-@@ -891,9 +891,9 @@
- long
- datum;
-
-- register int k;
-+ int k;
-
-- register UInt8 *p;
-+ UInt8 *p;
-
- void_vector<Int16> hash_code(MaxHashTable);
- void_vector<Int16> hash_prefix(MaxHashTable);
-diff -urNb vigra-1.10.0-src/include/vigra/random_forest/rf_algorithm.hxx Vigra/include/vigra/random_forest/rf_algorithm.hxx
---- vigra-1.10.0-src/include/vigra/random_forest/rf_algorithm.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/random_forest/rf_algorithm.hxx 2022-03-18 08:52:17.519102162 +0100
-@@ -34,6 +34,7 @@
- /************************************************************************/
- #define VIGRA_RF_ALGORITHM_HXX
-
-+#include <random>
- #include <vector>
- #include "splices.hxx"
- #include <queue>
-@@ -1151,7 +1152,7 @@
- ArrayVector<Int32> indices(pr.features().shape(0));
- for(int ii = 0; ii < pr.features().shape(0); ++ii)
- indices.push_back(ii);
-- std::random_shuffle(indices.begin(), indices.end());
-+ std::shuffle(indices.begin(), indices.end(), std::mt19937(std::random_device()()));
- for(int ii = 0; ii < rf.ext_param_.row_count_; ++ii)
- {
- if(!sm.is_used()[indices[ii]] && cts[pr.response()(indices[ii], 0)] < 3000)
-diff -urNb vigra-1.10.0-src/include/vigra/random_forest/rf_visitors.hxx Vigra/include/vigra/random_forest/rf_visitors.hxx
---- vigra-1.10.0-src/include/vigra/random_forest/rf_visitors.hxx 2013-11-18 17:48:16.000000000 +0100
-+++ Vigra/include/vigra/random_forest/rf_visitors.hxx 2022-03-18 08:54:14.449776895 +0100
-@@ -41,6 +41,7 @@
- #include <vigra/windows.h>
- #include <iostream>
- #include <iomanip>
-+#include <random>
-
- #include <vigra/multi_pointoperators.hxx>
- #include <vigra/timing.hxx>
-@@ -909,7 +910,7 @@
- {
- ArrayVector<int> oob_indices;
- ArrayVector<int> cts(class_count, 0);
-- std::random_shuffle(indices.begin(), indices.end());
-+ std::shuffle(indices.begin(), indices.end(), std::mt19937(std::random_device()()));
- for(int ii = 0; ii < rf.ext_param_.row_count_; ++ii)
- {
- if(!sm.is_used()[indices[ii]] && cts[pr.response()(indices[ii], 0)] < 40000)
diff --git a/CMakeExternals/ZLIB.cmake b/CMakeExternals/ZLIB.cmake
index 80eb9a03ec..c5359a0331 100644
--- a/CMakeExternals/ZLIB.cmake
+++ b/CMakeExternals/ZLIB.cmake
@@ -1,29 +1,29 @@
set(proj ZLIB)
set(proj_DEPENDENCIES "")
if(MITK_USE_${proj})
set(${proj}_DEPENDS ${proj})
if(DEFINED ${proj}_DIR AND NOT EXISTS ${${proj}_DIR})
message(FATAL_ERROR "${proj}_DIR variable is defined but corresponds to non-existing directory!")
endif()
find_package(ZLIB QUIET)
if(NOT DEFINED ${proj}_DIR AND NOT ZLIB_FOUND)
ExternalProject_Add(${proj}
GIT_REPOSITORY https://github.com/madler/zlib.git
- GIT_TAG v1.2.11
+ GIT_TAG v1.2.13
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS ${ep_common_args}
CMAKE_CACHE_ARGS ${ep_common_cache_args}
CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args}
DEPENDS ${proj_DEPENDENCIES}
)
set(${proj}_DIR ${ep_prefix})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeExternals/lz4.cmake b/CMakeExternals/lz4.cmake
index 5f63e12c42..28a1315826 100644
--- a/CMakeExternals/lz4.cmake
+++ b/CMakeExternals/lz4.cmake
@@ -1,54 +1,54 @@
#-----------------------------------------------------------------------------
# lz4
#-----------------------------------------------------------------------------
if(MITK_USE_lz4)
# Sanity checks
if(DEFINED lz4_DIR AND NOT EXISTS "${lz4_DIR}")
message(FATAL_ERROR "lz4_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj lz4)
set(proj_DEPENDENCIES )
set(lz4_DEPENDS ${proj})
if(NOT DEFINED lz4_DIR)
set(additional_args )
if(NOT CMAKE_DEBUG_POSTFIX)
list(APPEND additional_args "-DCMAKE_DEBUG_POSTFIX:STRING=d")
endif()
if(CTEST_USE_LAUNCHERS)
list(APPEND additional_args
"-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
)
endif()
ExternalProject_Add(${proj}
LIST_SEPARATOR ${sep}
GIT_REPOSITORY https://github.com/lz4/lz4.git
- GIT_TAG v1.9.3
+ GIT_TAG v1.9.4
SOURCE_SUBDIR build/cmake
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${ep_common_args}
${additional_args}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
-DLZ4_BUILD_CLI:BOOL=OFF
-DLZ4_BUILD_LEGACY_LZ4C:BOOL=OFF
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
DEPENDS ${proj_DEPENDENCIES}
)
set(lz4_DIR "${ep_prefix}")
mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeExternals/nlohmann_json.cmake b/CMakeExternals/nlohmann_json.cmake
index fbca098b3c..78a1cd68ad 100644
--- a/CMakeExternals/nlohmann_json.cmake
+++ b/CMakeExternals/nlohmann_json.cmake
@@ -1,48 +1,48 @@
#-----------------------------------------------------------------------------
# nlohmann_json
#-----------------------------------------------------------------------------
if(MITK_USE_nlohmann_json)
# Sanity checks
if(DEFINED nlohmann_json_DIR AND NOT EXISTS "${nlohmann_json_DIR}")
message(FATAL_ERROR "nlohmann_json_DIR variable is defined but corresponds to non-existing directory")
endif()
set(proj nlohmann_json)
set(proj_DEPENDENCIES )
set(nlohmann_json_DEPENDS ${proj})
if(NOT DEFINED nlohmann_json_DIR)
set(additional_args )
if(CTEST_USE_LAUNCHERS)
list(APPEND additional_args
"-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake"
)
endif()
ExternalProject_Add(${proj}
LIST_SEPARATOR ${sep}
GIT_REPOSITORY https://github.com/nlohmann/json.git
- GIT_TAG v3.10.5
+ GIT_TAG v3.11.2
CMAKE_GENERATOR ${gen}
CMAKE_GENERATOR_PLATFORM ${gen_platform}
CMAKE_ARGS
${ep_common_args}
${additional_args}
CMAKE_CACHE_ARGS
${ep_common_cache_args}
-DJSON_BuildTests:BOOL=OFF
CMAKE_CACHE_DEFAULT_ARGS
${ep_common_cache_default_args}
DEPENDS ${proj_DEPENDENCIES}
)
set(nlohmann_json_DIR "${ep_prefix}")
mitkFunctionInstallExternalCMakeProject(${proj})
else()
mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}")
endif()
endif()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbfcfa1fb5..dd5ce7718a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,1377 +1,1418 @@
#[[ When increasing the minimum required version, check if Boost_ADDITIONAL_VERSIONS
in CMake/PackageDepends/MITK_Boost_Config.cmake can be removed. See the first
long comment in CMakeExternals/Boost.cmake for details. ]]
set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.18)
cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION})
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19 AND CMAKE_VERSION VERSION_LESS 3.19.2)
message(FATAL_ERROR "\
CMake v${CMAKE_VERSION} is defective [1]. \
Please either downgrade to v3.18 or upgrade to at least v3.19.2.\n\
[1] https://gitlab.kitware.com/cmake/cmake/-/issues/21529")
endif()
#-----------------------------------------------------------------------------
# Policies
#-----------------------------------------------------------------------------
#[[ T28060
https://cmake.org/cmake/help/v3.18/policy/CMP0091.html
https://cmake.org/cmake/help/v3.18/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
We pass CMP0091 to all external projects as command-line argument:
-DCMAKE_POLICY_DEFAULT_CMP0091:STRING=OLD
]]
cmake_policy(SET CMP0091 OLD)
#-----------------------------------------------------------------------------
# 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 2022.10.99)
+ project(MITK VERSION 2023.04.99)
include_directories(SYSTEM ${MITK_SUPERBUILD_BINARY_DIR})
endif()
#-----------------------------------------------------------------------------
# MITK Extension Feature
#-----------------------------------------------------------------------------
set(MITK_EXTENSION_DIRS "" CACHE STRING "")
unset(MITK_ABSOLUTE_EXTENSION_DIRS)
foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS})
get_filename_component(MITK_ABSOLUTE_EXTENSION_DIR "${MITK_EXTENSION_DIR}" ABSOLUTE)
list(APPEND MITK_ABSOLUTE_EXTENSION_DIRS "${MITK_ABSOLUTE_EXTENSION_DIR}")
endforeach()
set(MITK_DIR_PLUS_EXTENSION_DIRS "${MITK_SOURCE_DIR}" ${MITK_ABSOLUTE_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_ABSOLUTE_EXTENSION_DIRS})
set(MITK_CMAKE_EXTENSION_DIR "${MITK_EXTENSION_DIR}/CMake")
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(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()
if(CMAKE_COMPILER_IS_GNUCXX)
mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION)
else()
set(GCC_VERSION 0)
endif()
set(MITK_CXX_STANDARD 17)
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++<std> flag for targets.
# However, compile flag checks also need to be done with -std=c++<std>.
# The MITK_CXX<std>_FLAG variable is also used for external projects
# build during the MITK super-build.
mitkFunctionCheckCompilerFlags("-std=c++${MITK_CXX_STANDARD}" MITK_CXX${MITK_CXX_STANDARD}_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)
mark_as_advanced(
MITK_XVFB_TESTING
MITK_FAST_TESTING
MITK_BUILD_ALL_APPS
)
#-----------------------------------------------------------------------------
# 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_ABSOLUTE_EXTENSION_DIRS})
set(MITK_CMAKE_EXTERNALS_EXTENSION_DIR "${MITK_EXTENSION_DIR}/CMakeExternals")
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_ABSOLUTE_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)
if(WIN32)
set(MITK_QT5_MINIMUM_VERSION 5.12.9)
else()
set(MITK_QT5_MINIMUM_VERSION 5.12)
endif()
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 2022)
list(APPEND _compilers "msvc2019" "msvc2017") # Binary compatible
elseif (CMAKE_MATCH_0 EQUAL 2019)
list(APPEND _compilers "msvc2017") # Binary compatible
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})
endif()
# -----------------------------------------
# Custom dependency logic
if(WIN32 AND Qt5_DIR)
set(_dir_candidate "${Qt5_DIR}/../../../../../Tools/OpenSSL/Win_x64")
get_filename_component(_dir_candidate ${_dir_candidate} ABSOLUTE)
if(EXISTS "${_dir_candidate}")
set(OPENSSL_ROOT_DIR "${_dir_candidate}")
endif()
endif()
find_package(OpenSSL)
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 OR MITK_USE_httplib)
if(NOT OpenSSL_FOUND)
set(openssl_message "Could not find OpenSSL (dependency of C++ REST SDK and cpp-httplib).\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 either install Win32 OpenSSL:\n"
" https://slproweb.com/products/Win32OpenSSL.html\n"
"Or use the Qt Maintenance tool to install (recommended):\n"
" Developer and Designer Tools > OpenSSL Toolkit > OpenSSL 64-bit binaries\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<unsigned char>, itk::RGBAPixel<unsigned char>"
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<unsigned char>, itk::RGBAPixel<unsigned char>"
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()
find_package(Git REQUIRED)
#-----------------------------------------------------------------------------
# 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(mitkFunctionAddManifest)
include(mitkFunctionAddCustomModuleTest)
include(mitkFunctionCheckModuleDependencies)
include(mitkFunctionCompileSnippets)
include(mitkFunctionConfigureVisualStudioUserProjectFile)
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
#-----------------------------------------------------------------------------
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)
#-----------------------------------------------------------------------------
if(OpenSSL_FOUND AND WIN32)
- set(MITK_OPENSSL_SSL_DLL "" CACHE FILEPATH "")
- set(MITK_OPENSSL_CRYPTO_DLL "" CACHE FILEPATH "")
+ #[[ On Windows, CMake is able to locate the link libraries for OpenSSL but it
+ does not look for the corresponding DLLs that we need to copy to our
+ binary directories and include in packaging.
+
+ Setting these paths manually is cumbersome so we try to use a simple
+ heuristic to automatically set them:
+
+ - Based on the link libraries (usually located in a lib folder),
+ try to find the "../bin" binary directory.
+ - Use the base file names of the link libraries to find corresponding
+ DLLs like "<base name>*.dll", that usually are named like
+ "<base name>-1_1-x64.dll" or similar.
+ ]]
+ set(openssl_ssl_dll "")
+ set(openssl_crypto_dll "")
+
+ if(OPENSSL_SSL_LIBRARY AND EXISTS "${OPENSSL_SSL_LIBRARY}")
+ get_filename_component(openssl_bin_dir "${OPENSSL_SSL_LIBRARY}" DIRECTORY)
+ get_filename_component(openssl_bin_dir "${openssl_bin_dir}" DIRECTORY)
+ set(openssl_bin_dir "${openssl_bin_dir}/bin")
+
+ if(EXISTS "${openssl_bin_dir}")
+ get_filename_component(openssl_ssl_basename "${OPENSSL_SSL_LIBRARY}" NAME_WE)
+ file(GLOB openssl_ssl_dll "${openssl_bin_dir}/${openssl_ssl_basename}*.dll")
+ list(LENGTH openssl_ssl_dll num_findings)
+ if(num_findings GREATER 1)
+ set(openssl_ssl_dll "")
+ endif()
+
+ get_filename_component(openssl_crypto_basename "${OPENSSL_CRYPTO_LIBRARY}" NAME_WE)
+ file(GLOB openssl_crypto_dll "${openssl_bin_dir}/${openssl_crypto_basename}*.dll")
+ list(LENGTH openssl_crypto_dll num_findings)
+ if(num_findings GREATER 1)
+ set(openssl_crypto_dll "")
+ endif()
+ endif()
+ endif()
+
+ set(MITK_OPENSSL_SSL_DLL "${openssl_ssl_dll}" CACHE FILEPATH "")
+
+ if(DEFINED CACHE{MITK_OPENSSL_SSL_DLL} AND NOT MITK_OPENSSL_SSL_DLL AND openssl_ssl_dll)
+ set(MITK_OPENSSL_SSL_DLL "${openssl_ssl_dll}" CACHE FILEPATH "" FORCE)
+ endif()
+
+ set(MITK_OPENSSL_CRYPTO_DLL "${openssl_crypto_dll}" CACHE FILEPATH "")
+
+ if(DEFINED CACHE{MITK_OPENSSL_CRYPTO_DLL} AND NOT MITK_OPENSSL_CRYPTO_DLL AND openssl_crypto_dll)
+ set(MITK_OPENSSL_CRYPTO_DLL "${openssl_crypto_dll}" CACHE FILEPATH "" FORCE)
+ endif()
if(MITK_OPENSSL_SSL_DLL AND EXISTS "${MITK_OPENSSL_SSL_DLL}" AND MITK_OPENSSL_CRYPTO_DLL AND EXISTS "${MITK_OPENSSL_CRYPTO_DLL}")
foreach(config_type ${CMAKE_CONFIGURATION_TYPES})
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${MITK_BINARY_DIR}/bin/${config_type}")
configure_file("${MITK_OPENSSL_SSL_DLL}" "${MITK_BINARY_DIR}/bin/${config_type}/" COPYONLY)
configure_file("${MITK_OPENSSL_CRYPTO_DLL}" "${MITK_BINARY_DIR}/bin/${config_type}/" COPYONLY)
endforeach()
MITK_INSTALL(FILES
"${MITK_OPENSSL_SSL_DLL}"
"${MITK_OPENSSL_CRYPTO_DLL}"
)
endif()
endif()
# 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)
-# As of Windows 10 Version 1903 (May 2019 Update), applications can use the UTF-8 code page
-if(WIN32)
- option(MITK_UTF8 "Use UTF-8 code page in MITK applications on Windows" ON)
- mark_as_advanced(MITK_UTF8)
-endif()
-
if(NOT MITK_FAST_TESTING)
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")
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_CXX${MITK_CXX_STANDARD}_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} -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-deprecated-copy
-Wno-array-bounds
-Wno-cast-function-type
-Wno-maybe-uninitialized
-Wno-error=stringop-overread
-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_ABSOLUTE_EXTENSION_DIRS})
set(MITK_PACKAGE_DEPENDS_EXTENSION_DIR "${MITK_EXTENSION_DIR}/CMake/PackageDepends")
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.74 1.74.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
# <proj>Config.cmake files pointed at by <proj>_DIR variables.
# Otherwise, existing Find<proj>.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<proj>.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)
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()
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()
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)
# Configuration for the CMake-generated test driver
set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include <stdexcept>")
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 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_ABSOLUTE_EXTENSION_DIRS})
get_filename_component(MITK_ROOT_FOLDER "${MITK_EXTENSION_DIR}" NAME)
set(MITK_MODULES_EXTENSION_DIR "${MITK_EXTENSION_DIR}/Modules")
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)
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_ABSOLUTE_EXTENSION_DIRS})
set(MITK_PLUGINS_EXTENSION_DIR "${MITK_EXTENSION_DIR}/Plugins")
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")
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
#-----------------------------------------------------------------------------
set(MITK_DOXYGEN_ADDITIONAL_INPUT_DIRS)
set(MITK_DOXYGEN_ADDITIONAL_IMAGE_PATHS)
foreach(MITK_EXTENSION_DIR ${MITK_DIR_PLUS_EXTENSION_DIRS})
set(MITK_DOXYGEN_ADDITIONAL_INPUT_DIRS "${MITK_DOXYGEN_ADDITIONAL_INPUT_DIRS} \"${MITK_EXTENSION_DIR}\"")
set(MITK_DOXYGEN_ADDITIONAL_IMAGE_PATHS "${MITK_DOXYGEN_ADDITIONAL_IMAGE_PATHS} \"${MITK_EXTENSION_DIR}\"")
endforeach()
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")
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_ABSOLUTE_EXTENSION_DIRS})
set(MITK_APPLICATIONS_EXTENSION_DIR "${MITK_EXTENSION_DIR}/Applications")
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/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
index 83731979d3..8304a11c44 100644
--- a/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
+++ b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
@@ -1,70 +1,74 @@
/**
\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.
<ul>
<li> \subpage org_mitk_views_basicimageprocessing </li>
<li> \subpage org_mitk_views_datamanager </li>
<li> \subpage org_mitk_editors_dicombrowser </li>
<li> \subpage org_mitk_views_dicominspector </li>
<li> \subpage org_mitk_views_imagecropper </li>
<li> \subpage org_mitk_views_imagenavigator </li>
<li> \subpage org_mitk_views_pixelvalue </li>
<li> \subpage org_blueberry_views_logview </li>
<li> \subpage org_mitk_views_matchpoint_algorithm_browser </li>
<li> \subpage org_mitk_views_matchpoint_algorithm_control </li>
<li> \subpage org_mitk_views_matchpoint_evaluator </li>
<li> \subpage org_mitk_views_matchpoint_framereg </li>
<li> \subpage org_mitk_views_matchpoint_manipulator </li>
<li> \subpage org_mitk_views_matchpoint_mapper </li>
<li> \subpage org_mitk_views_matchpoint_visualizer </li>
<li> \subpage org_mitk_gui_qt_measurementtoolbox
<ul>
<li> \subpage org_mitk_views_measurement </li>
<li> \subpage org_mitk_views_imagestatistics </li>
</ul>
</li>
<li> \subpage org_mitk_views_moviemaker </li>
<li> \subpage org_mitk_views_pointsetinteraction </li>
<li> \subpage org_mitk_views_python </li>
<li> \subpage org_mitk_views_remeshing </li>
<li> \subpage org_mitk_views_screenshotmaker </li>
- <li> \subpage org_mitk_views_segmentation </li>
+ <li> Segmentation
+ <ul>
+ <li> \subpage org_mitk_views_segmentation </li>
+ <li> \subpage org_mitk_views_segmentationutilities </li>
+ <li> \subpage org_mitk_views_segmentationtasklist </li>
+ </ul>
+ </li>
<li> \subpage org_mitk_editors_stdmultiwidget </li>
<li> \subpage org_mitk_editors_mxnmultiwidget </li>
<li> \subpage org_mitk_views_deformableclippingplane </li>
<li> \subpage org_mitk_views_viewnavigator </li>
<li> \subpage org_mitk_views_volumevisualization </li>
<li> \subpage org_mitk_views_properties </li>
<li> \subpage org_mitk_gui_qt_flowapplication </li>
<li> \subpage org_mitk_gui_qt_flow_segmentation </li>
<li> \subpage org_mitk_gui_qt_aicpregistration </li>
<li> \subpage org_mitk_gui_qt_cest </li>
- <li> \subpage org_mitk_gui_qt_classificationsegmentation </li>
<li> \subpage org_mitk_views_cmdlinemodules </li>
<li> \subpage org_mitk_views_pharmacokinetics_concentration_mri </li>
<li> \subpage org_mitk_views_pharmacokinetics_mri </li>
<li> \subpage org_mitk_views_pharmacokinetics_pet </li>
<li> \subpage org_mitk_gui_qt_examples </li>
<li> \subpage org_mitk_gui_qt_geometrytools </li>
<li> \subpage org_mitk_gui_qt_igtexample </li>
<li> \subpage org_mitk_gui_qt_igttracking </li>
<li> \subpage org_mitk_views_igttrackingsemiautomaticmeasurement </li>
<li> \subpage org_mitk_views_fit_demo </li>
<li> \subpage org_mitk_views_fit_genericfitting </li>
<li> \subpage org_mitk_views_fit_inspector </li>
<li> \subpage org_mitkexamplesopencv </li>
<li> \subpage org_mitk_gui_qt_overlaymanager </li>
- <li> \subpage org_mitk_gui_qt_mitkphenotyping </li>
<li> \subpage org_mitk_gui_qt_preprocessing_resampling </li>
<li> \subpage org_mitk_views_pharmacokinetics_curvedescriptor </li>
<li> \subpage org_mitk_views_pharmacokinetics_simulation </li>
<li> \subpage org_surfacematerialeditor </li>
<li> \subpage org_toftutorial </li>
<li> \subpage org_blueberry_ui_qt_objectinspector </li>
<li> \subpage org_mitk_gui_qt_ultrasound </li>
<li> \subpage org_mitk_gui_qt_xnat </li>
</ul>
*/
diff --git a/Documentation/Doxygen/2-UserManual/MiniApps.dox b/Documentation/Doxygen/2-UserManual/MiniApps.dox
index e46a512f74..00ec702760 100644
--- a/Documentation/Doxygen/2-UserManual/MiniApps.dox
+++ b/Documentation/Doxygen/2-UserManual/MiniApps.dox
@@ -1,65 +1,64 @@
/**
\page AdvancedTopicsPage Advanced MITK user topics
\section MiniAppExplainPage MITK MiniApps
<div align="center"><h1>What are MiniApps?</h1></div>
MiniApps are small command line tools. Generally the purpose of each of these tools is designed to fulfill one simple task,
e.g. resample an image or extract image statistics of a given region of interest (ROI).
They are intended to provide command line access to a variety of features of MITK, thus facilitating batched processing of data.
<div align="center"><h1>Usage</h1></div>
Each MiniApp should provide information about its usage. If it is called without parameters it will output help information about expected inputs, outputs and parameters.
Below you can see the help output of the MitkGibbsTracking MiniApp:
\code
$./MitkGibbsTracking
-i, --input, input image (tensor, ODF or FSL/MRTrix SH-coefficient image)
-p, --parameters, parameter file (.gtp)
-m, --mask, binary mask image (optional)
-s, --shConvention, sh coefficient convention (FSL, MRtrix) (optional), (default: FSL)
-o, --outFile, output fiber bundle (.fib)
-f, --noFlip, do not flip input image to match MITK coordinate convention (optional)
\endcode
<div align="center"><h1>Integrating a command line tool into MITK Workbench</h1></div>
The executable file has be to be announced in MITK Workbench. This can be done in Preferences window:
Click 'Window' -> 'Preferences', and select 'Command Line Modules'. You can add directories containing executable files or you can select single executable files.
Click 'OK' button.
The configured command line tools are now available via the drop-down box of the Command Line Modules tab.
\warning The build configuration of your MiniApp should match the build configuration of your MITK application. This is especially relevant for developers. Combining a Release application and Debug MiniApp or vice versa might not work.
<div align="center"><h1>Available MiniApps in MITK</h1></div>
<ul>
<li>\ref mitkBasicImageProcessingMiniAppsPortalPage </li>
-<li> \ref mitkClassificationMiniAppsPortalPage </li>
</ul>
<div align="center"><h1>Technical Information</h1></div>
MiniApps follow the <a href="https://www.slicer.org/slicerWiki/index.php/Slicer3:Execution_Model_Documentation">Slicer Execution Model</a> in describing themselves via xml:
\code
$./GibbsTracking --xml
<executable>
<category>Fiber Tracking and Processing Methods</category>
<title>Gibbs Tracking</title>
<description></description>
<contributor>German Cancer Research Center (DKFZ)</contributor>
<parameters>
...
</parameters>
</executable>
\endcode
\note Full conformity is still a work in progress.
*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/Application/DevelopmentApplication.dox b/Documentation/Doxygen/3-DeveloperManual/Application/DevelopmentApplication.dox
index baf97ed86f..587d9c2803 100644
--- a/Documentation/Doxygen/3-DeveloperManual/Application/DevelopmentApplication.dox
+++ b/Documentation/Doxygen/3-DeveloperManual/Application/DevelopmentApplication.dox
@@ -1,27 +1,22 @@
/**
\page DevelopmentApplication Developing with the MITK Application Framework
MITK offers a powerful application featuring a plugin system and many
predefined plugins. You can configure this application to offer a set of
functionality to the user and easily create an installer.
Working with the application, you will have to learn about extension
points and the Blueberry framework itself. If you are new to the matter,
please also consult \ref Architecture and \ref FirstSteps.
<ul>
<li> \subpage BlueBerryIntro </li>
<li> \subpage BlueBerryExamples </li>
</ul>
The BlueBerry framework extension-point reference is available here:
- \subpage BlueBerryExtPointsIndex
-
-The MITK application extension-point reference is available here:
-
- - \subpage mitkExtPointsIndex
-
*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/Application/ExtensionPointReference.dox b/Documentation/Doxygen/3-DeveloperManual/Application/ExtensionPointReference.dox
deleted file mode 100644
index e324ea7885..0000000000
--- a/Documentation/Doxygen/3-DeveloperManual/Application/ExtensionPointReference.dox
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
-
-\page mitkExtPointsIndex MITK Extension-Point Reference
-
-- \subpage mitkExtPointsIndex_InputDevices
-
-\page mitkExtPointsIndex_InputDevices Input Devices
-
-\tableofcontents
-
-\section mitkExtPointsIndex_InputDevices_Identifier Identifier
-
-\c org.mitk.core.ext.inputdevices
-
-\section mitkExtPointsIndex_InputDevices_Description Description
-
-This extension point is used to define additional input devices.
-
-\section mitkExtPointsIndex_InputDevices_ConfigurationMarkup Configuration Markup
-
-\code{.unparsed}
-<!ELEMENT extension (inputdevice*)>
-<!ATTLIST extension
- point CDATA #REQUIRED
- id CDATA #IMPLIED
- name CDATA #IMPLIED>
-\endcode
-
-- <tt>point</tt>: a fully qualified identifier of the target extension point
-- <tt>id</tt>: an optional identifier of the extension instance
-- <tt>name</tt>: an optional name of the extension instance
-
-\code{.unparsed}
-<!ELEMENT inputdevice (description?)>
-<!ATTLIST inputdevice
- id CDATA #REQUIRED
- name CDATA #IMPLIED
- class CDATA #REQUIRED>
-\endcode
-
-- <tt>id</tt>: the identifier of the input device
-- <tt>name</tt>: an optional name of the input device
-- <tt>class</tt>: a fully qualified name of the class that implements mitk::IInputDevice.
-
-\code{.unparsed}
-<!ELEMENT description (#PCDATA)>
-\endcode
-
-An optional subelement whose body should contain text providing a short description of the input device.
-
-\section mitkExtPointsIndex_InputDevices_Examples Examples
-
-\code{.unparsed}
-<extension point="org.mitk.core.ext.inputdevices">
- <inputdevice
- id="com.xyz.inputdevice.XYZDevice"
- name="XYZ Device"
- class="ns::XYZDevice">
- <description>My new 20-dimensional input device</description>
- </inputdevice>
-</extension>
-\endcode
-
-*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/Concepts/Logging.dox b/Documentation/Doxygen/3-DeveloperManual/Concepts/Logging.dox
index b4d0f0172a..7559e8bc7f 100644
--- a/Documentation/Doxygen/3-DeveloperManual/Concepts/Logging.dox
+++ b/Documentation/Doxygen/3-DeveloperManual/Concepts/Logging.dox
@@ -1,72 +1,72 @@
/**
\page LoggingPage Logging Concept
\tableofcontents
\section LoggingPageSection1 Basic Information on Logging
To use logging in MITK you can stream your messages into a logging stream, similar to the "std::cout" stream in standard c++. A simple example is shown next.
\code
MITK_INFO << "Here comes my message";
\endcode
Please only use the MITK_INFO (respectively MITK_WARN, MITK_ERROR, MITK_FATAL, MITK_DEBUG, see \ref LoggingPageSection3 for more details) in MITK, the std::cout stream should not be used.
You can also log object information, like shown in the next example.
\code
MITK_INFO << "I want to log my vector size: " << m_vector.getSize();
\endcode
All logged information will be displayed in the console and be written to a logging file in the MITK binary folder. Advanced users may want to know that this behavior is controlled by the logging backend class, which can be adapted if you want to change the behavior.
This is everything you need to know about simple logging. Further reading will show you how you can categorize your logging message and what logging levels are.
\section LoggingPageSection2 Categorize your Logging Messages
You may also want to categorize your logging messages, so you can assign messages to your specific topic. You can simply add classes and subclasses to your MITK logging messages by using brackets, like shown in the next example.
\code
MITK_INFO << "no class";
MITK_INFO("MyClass") << "single class";
MITK_INFO("MyClass")("MySubClass") << "class with subclass";
\endcode
This classes makes it easy to e.g. simply filter all logging messages only for relevant information.
\section LoggingPageSection3 Logging Levels
MITK offers different logging levels. You may mostly want to use MITK_INFO, but please consider using the other levels, e.g. when logging debug information or errors.
<b>Debug (MITK_DEBUG)</b>: These messages are designed for debug output, used to debug your source code. Example:
\code
MITK_DEBUG << "Result of method LoadPicture(): true."
\endcode
-These messages are only displayed if you turn the CMake-Variable MBILOG_ENABLE_DEBUG_MESSAGES on. You can also use the debug message in release mode, output only depends on the CMake-Variable. If you want to enable the debug messages only for a single class / module / plugin you can also simply define the variable in your source code for the time you want to see the messages. Therefore you add a line "#define MBILOG_ENABLE_DEBUG" in the beginning of your cpp file. But don't forget to remove the definition before commiting the source code.
+These messages are only displayed if you turn the CMake-Variable MITK_ENABLE_DEBUG_MESSAGES on. You can also use the debug message in release mode, output only depends on the CMake-Variable.
<b>Info (MITK_INFO)</b>: For standard information messages that inform about expected changes/results in the program flow. Info messages should be important and understandable for the users of the program.
Example:
\code
MITK_INFO << "The picture test.nrrd has been loaded successfully."
\endcode
<b>Warning (MITK_WARN)</b>: Warning messages should inform about unexpected or potentially problematic states in the program flow that do not lead directly to an error. Thus, after a warning the program should be able continue without errors and in a clear state.
Example:
\code
MITK_WARN << "The picture test.nrrd was not loaded because access was denied."
\endcode
<b>Error (MITK_ERROR)</b>: Error messages notify the user about corrupt states in the program flow. Such states may occur after unexpected behavior of source code.
Example:
\code
MITK_ERROR << "Error while adding test.nrrd to the data storage, aborting."
\endcode
<b>Fatal (MITK_FATAL)</b>: Fatal messages report corrupt states in the program flow that lead directly to a crash of the program.
Example:
\code
MITK_FATAL << "Memory allocation error during instantiation of image object."
\endcode
\section LoggingPageSection4 Conditional Logging
Another feature of the logging mechanism is that you can directly give conditions for logging your message. These bool values or expressions can be defined in brackets. An example is shown next.
\code
MITK_INFO(x>1000) << "x is too large"; //logs only if x > 1000
\endcode
*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/DeveloperManualPortal.dox b/Documentation/Doxygen/3-DeveloperManual/DeveloperManualPortal.dox
index 678ce379c8..8ab74c6556 100644
--- a/Documentation/Doxygen/3-DeveloperManual/DeveloperManualPortal.dox
+++ b/Documentation/Doxygen/3-DeveloperManual/DeveloperManualPortal.dox
@@ -1,31 +1,28 @@
/**
\developersguidemainpage{DeveloperManualPortal} Developer Manual
Development with MITK can happen under several conditions. Depending on whether you are using the Toolkit or the entire application, different sections may apply to you.
In case you are unsure about what you need, please refer to \link Architecture The Architecture of MITK text\endlink.
An extensive Introduction to MITK is available under \link StartingDevelopment Starting your MITK Development\endlink.
Once you have made yourself familiar with MITK, you should have a look at the \link Concepts Development Concepts\endlink, as MITK implements a lot of high-level functionality.
Knowing about these concepts will prevent you from reimplementing functionality.
Once you start consuming more specific functionality, the \link MITKModuleManualsListPage Module Manual\endlink will be helpful to understand how a specific plugin works and what functionality it provides.
<ul>
<li> \subpage StartingDevelopment </li>
<ul>
<li> \ref Architecture </li>
<li> \ref SettingUpMITK </li>
<li> \ref GettingToKnowMITK </li>
<li> \ref FirstSteps </li>
<li> \ref AboutTestingPage </li>
</ul>
<li> \subpage Concepts </li>
<li> \subpage MITKModuleManualsListPage </li>
<li> \subpage DevelopmentApplication </li>
- <ul>
- <li> \ref mitkExtPointsIndex </li>
- </ul>
<li> \subpage DeploymentPage </li>
</ul>
*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/CMakeFAQ.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/CMakeFAQ.dox
index eb1e126554..475dd319e3 100644
--- a/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/CMakeFAQ.dox
+++ b/Documentation/Doxygen/3-DeveloperManual/Starting/GettingToKnow/CMakeFAQ.dox
@@ -1,44 +1,44 @@
/**
\page CMAKE_FAQ CMake FAQ
\section CMAKE_FAQ_General A general comment
MITK uses %CMake for configuration. If you want to develop either using MITK as a toolkit or by extending the capabilities of the applications provided by us, we recommend using %CMake for your own project too.
While it might be possible to use MITK in conjunction with other options, such as QMake or setting up your own project manually it will invariably involve a lot of work and probably hacks as well.
As we do have no experience with this, we will not be able to help you.
Be prepared to do a lot of tweaking on by yourself.
This guide does not try to give a general introduction to CMake, instead it tries to answer some basic questions that might arise for those new to %CMake, to help you get started on MITK. For a more comprehensive introduction on %CMake see <a href="https://cmake.org/cmake/help/latest/guide/tutorial/index.html">here</a>.
We will assume in this guide, that the path to your source is /MITK/.
\section CMAKE_FAQ_Question Basic Questions
\subsection CMAKE_FAQ_Question_WhereGetIt Where do I get CMake and what version do I need?
See \ref BuildInstructions_Prerequisites.
\subsection CMAKE_FAQ_Question_NewPluginNothing I coded a new plugin for the Workbench and nothing happened. Why?
Do note that you need to move the source to the Plugins directory and you will have to add the plugin to the config file (most likely Plugins/PluginList.cmake). After that see \ref CMAKE_FAQ_Question_HowDoIActivatePlugin.
\subsection CMAKE_FAQ_Question_HowDoIActivatePlugin I want to use a plugin, how do I activate it?
<ol>
<li> Start %CMake in the `MITK-build` directory inside your superbuild folder. E.g.
`cd ~/<your_MITK_superbuild_dir>/MITK-build`
`ccmake .` or `cmake-gui .`
<li> Optional: *Configure* to see all %CMake variables.
<li> Find the variable `MITK_BUILD_<plugin-id>` and activate it. The `<plugin-id>` refers to the package name of the plugin.<br>
- E.g. the plugin-id (also, the package name) `org.mitk.core.ext` is the sub-directory of same name in plugins directory (`~/MITK/Plugins/`).
+ E.g. the plugin-id (also, the package name) `org.mitk.gui.qt.application` is the sub-directory of same name in plugins directory (`~/MITK/Plugins/`).
<li> *Configure*, again
<li> *Generate*
<li> Rebuild the `MITK-build` target using your development environment.
</ol>
\subsection CMAKE_FAQ_Question_HowDoIActivateModule I want to use a module, how do I activate it?
Modules are build automatically if a plugin that requires them is activated. See \ref CMAKE_FAQ_Question_HowDoIActivatePlugin.
\subsection CMAKE_FAQ_Question_HowOwnToolkits MITK always downloads the toolkits, but I want to use my own.
This is covered in \ref HowToNewProjectCustomizingMITKConfigure.
\subsection CMAKE_FAQ_Question_HowOwnProjectMITK I want to use an MITK plugin in my own project but I can not find it.
See \ref HowToNewProjectAddingMITKFunctionality.
*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox
index dd67e482f8..e3111bbf82 100644
--- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox
+++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox
@@ -1,232 +1,232 @@
/**
\page BuildInstructionsPage Build Instructions
\tableofcontents
\section BuildInstructions_Introduction Introduction
The CMake-based build system of MITK supports a "superbuild" process,
meaning that it will download, configure, and build all required third-party
libraries (except Qt) automatically. These instructions will show you how to use
the MITK superbuild.
\note This page explains explicitly how to build MITK itself. If you want to
create your own project based on MITK, the process described below is completely
automated. Please see \ref HowToNewProject.
For more advanced users, the last sections explains how to inject custom build
libraries into the superbuild process.
\section BuildInstructions_Prerequisites Prerequisites
You need:
-# <a href="https://git-scm.com/">Git</a> (there are also numerous third-party graphical
clients available). We recommend using Git, but see below for a way how to
get the current source code without using it.
-# <a href="https://cmake.org/">CMake</a> (version \minimumCMakeVersion or higher)
-# <a href="https://www.qt.io/">Qt</a> \minimumQt5Version if you plan to develop Qt-based
applications
-# If you are using <b>macOS</b> you need an XCode installation and the
Command Line Tools as it provides the neccessary compilers and SDKs
To build MITK on Linux, install the following packages, e. g. with APT:
\code{.unparsed}
sudo apt install build-essential doxygen git graphviz libfreetype6-dev libglu1-mesa-dev libssl-dev libtiff5-dev libxcomposite1 libxcursor1 libxdamage-dev libxi-dev libxkbcommon-x11-0 libxt-dev mesa-common-dev
\endcode
For the optional and experimental (!) Python integration, install NumPy and SimpleITK v1.x, e. g.:
\code{.unparsed}
sudo apt install python3-numpy python3-pip
pip3 install SimpleITK
\endcode
\section BuildInstructions_Qt A note about Qt
As we do not provide Qt in the MITK superbuild you need to install Qt manually.
The Qt Company provides <a href="https://www.qt.io/download/">online installers
for all supported platforms</a>.
We highly recommend to install Qt to the default location of the installer as it will allow MITK to automatically find Qt without any further action needed.
Make sure to also select the following <b>required components</b>:
- QtWebEngine
- QtScript
On Windows, the Qt installer offers a welcome and straight forward way to install <b>OpenSSL</b>.
You find it under the Tools node.
\section BuildInstructions_Get_Source Get a source tree
Since MITK is under active development we recommend to use Git to check out
the latest stable release from the homepage. If you decide to use the most
current nightly release, make sure to get a stable tree: Check the
<a href="https://cdash.mitk.org/index.php?project=MITK">MITK dashboard</a>
before checking out. If the build tree is not clean, you can specify an
older revision for the checkout or get a stable tar ball from
<a href="https://www.mitk.org">www.mitk.org</a>.
To clone MITK's current Git repository do:
\code
git clone https://phabricator.mitk.org/source/mitk.git MITK
\endcode
\section BuildInstructions_Build_With_CMake Build MITK with CMake
Create a new directory for the superbuild binary tree, change to it and call CMake:
In the shell (assuming your current directory is the same as the one where you
issued the git clone command):
\code
mkdir MITK-superbuild
cd MITK-superbuild
ccmake ../MITK
\endcode
If you use <b>Windows</b> or prefer to use the CMake GUI, start the CMake GUI and enter the
location of the source tree and binary tree, choose a suitable generator
and configure the project.
CMake will present you a couple of options, these are the most important ones:
- <tt><b>CMAKE_PREFIX_PATH</b></tt> The path to your Qt installation, e.g., <i>C:/Qt/5.12.9/msvc2017_64</i> or <i>/home/user/Qt/5.12.9/gcc_64</i>
- <tt><b>MITK_USE_BLUEBERRY</b></tt> Build the BlueBerry application framework
- <tt><b>MITK_USE_Boost_LIBRARIES</b></tt> If you need binary Boost libraries,
specify them here.
- <tt><b>MITK_USE_OpenCV</b></tt> Build MITK code which depends on OpenCV (this
will download and build OpenCV 2.4)
- <tt><b>MITK_USE_Python3</b></tt> Enables Python wrapping in MITK. This will also
configure ITK, VTK, and OpenCV (if enabled) to build Python wrappers.
- <tt><b>MITK_USE_Qt5</b></tt> Build MITK code which depends on Qt 5
If you are satisfied with the configuration of your MITK superbuild, generate
the project files with CMake by pressing "Generate".
<b>Linux</b> and <b>macOS</b> users usually just enter "make" (optionally
supplying the number threads to be used for a parallel build):
\code
make -j6
\endcode
<b>Windows</b> users using Visual Studio can open the generated
<tt>MITK-superbuild.sln</tt> solution file in the <tt>MITK-superbuild</tt>
directory and start the build by building the <tt>BUILD_ALL</tt> project.
\section BuildInstructions_Customize Customize your MITK superbuild
The MITK superbuild configures MITK as well as all external libraries. The
build directories of these libraries, and of MITK itself are located inside
the <tt>MITK-superbuild</tt> directory. For example, the directory layout may
look like:
\code
MITK-superbuild
|- ep "external projects"
|-bin
|-lib
|-include
|-src
|- MITK-build
\endcode
To change the configuration of the MITK build itself, choose the MITK-build directory
as the binary directory in the CMake GUI (not the MITK-superbuild directory).
After generating the project files, build the MITK project by either issuing "make"
in the MITK-build directory (Linux, macOS), or by opening MITK-build/MITK.sln (Windows).
You may also change the configuration of any project configured via the
superbuild process. Make sure to also build the changed project and also the
projects which depend on it.
\section BuildInstructions_Running Running Applications
On Linux, just execute the application you want to run. MITK executables are
located in <tt>MITK-superbuild/MITK-build/bin</tt>
On Windows, the <tt>PATH</tt> environment variable must contain the directories
containing the third-party libraries. This is automatically done from Visual Studio.
For running the applications directly use the generated batch files in the
<tt>MITK-superbuild/MITK-build/bin</tt>.
\section BuildInstructions_Documentation Documentation
If you have the <a href="https://www.doxygen.nl/">Doxygen</a> documentation tool
installed, you get a new project (Visual Studio) or "make" target named "doc".
You can build this to generate the HTML documentation of MITK in the
Documentation/Doxygen directory of your MITK-build binary tree or in the
<tt>MITK_DOXYGEN_OUTPUT_DIR</tt> CMake variable (if specified).
\section BuildInstructions_As_Toolkit Use MITK in your own project (as a toolkit)
To use MITK in your external project, add the CMake command
<code>find_package(MITK REQUIRED)</code> to your CMakeLists.txt and make use of
the CMake macros <code>mitk_create_module()</code> and
<code>mitk_create_executable()</code> provided by MITK.
Here is a very basic example CMakeLists.txt including MITK as a project:
\code
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
project(MyProject)
-find_package(MITK 2022.10 REQUIRED)
+find_package(MITK 2023.04 REQUIRED)
add_executable(MyApp main.cpp)
target_link_libraries(MyApp MitkCore)
\endcode
-with the main.ccp being
+with the main.cpp being
\code
#include <iostream>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
int main()
{
MITK_INFO << "Hello world!";
return 0;
}
\endcode
\section BuildInstructions_Advanced_Customization Superbuild customization
You can inject pre-build third-party libraries into the MITK superbuild by
setting certain CMake variables before the first configure step. MITK will
then use these third-party libraries instead of downloading and building them
by itself. Note that you must take care of configuring those libraries with all options
MITK requires.
The variables listed below are provided for injecting third-party libraries.
Their occurrence in the CMake GUI or in ccmake may depend on specific
MITK_USE_* options set to ON. You may also use the variable names below without
the <tt>EXTERNAL_</tt> prefix, for example when providing their values on a
command line call to CMake.
- <tt><b>EXTERNAL_BOOST_ROOT</b></tt> Set this variable to your custom Boost
installation
- <tt><b>EXTERNAL_CTK_DIR</b></tt> Set this variable to your CTK binary tree
(the directory containing the CTKConfig.cmake file)
- <tt><b>EXTERNAL_CableSwig_DIR</b></tt> Set this variable to your CableSwig
binary tree for Python wrapping (the directory containing the
CableSwigConfig.cmake file)
- <tt><b>EXTERNAL_DCMTK_DIR</b></tt> Set this variable to your DCMTK binary
tree (the directory containing the DCMTKConfig.cmake file)
- <tt><b>EXTERNAL_GDCM_DIR</b></tt> Set this variable to your GDCM binary
tree (the directory containing the GDCMConfig.cmake file)
- <tt><b>EXTERNAL_ITK_DIR</b></tt> Set this variable to your ITK binary tree
(the directory containing the ITKConfig.cmake file)
- <tt><b>EXTERNAL_OpenCV_DIR</b></tt> Set this variable to your OpenCV binary
tree (the directory containing the OpenCVConfig.cmake file)
- <tt><b>EXTERNAL_VTK_DIR</b></tt> Set this variable to your VTK binary tree
(the directory containing the VTKConfig.cmake file)
To set CMake options before the first configure step is invoked, supply them
on the command line, i.e.
\code
ccmake -DITK_DIR:PATH=/opt/ITK-release ../MITK
\endcode
*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/HowToNewProject.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/HowToNewProject.dox
index 093fd104e1..c2c773f4bc 100644
--- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/HowToNewProject.dox
+++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/HowToNewProject.dox
@@ -1,230 +1,230 @@
/**
\page HowToNewProject Creating a new MITK project
\tableofcontents
This page is intended to give a comprehensive guide to setting up your own MITK based
project. It will use the application framework provided by MITK and is probably the
preferred way for most users.
The first part of this document is a tutorial aimed at newcomers to MITK and possibly
%CMake and tries to give as much help as possible on setting up your own project. If
you are looking for more technical information about customizing MITK, the structure
of the superbuild or packaging you might want to read the
\ref HowToNewProjectAdvancedInformation.
If you have set up your MITK project already and want to start developing you could
take a look at \ref TutorialPage.
\section HowToNewProjectGettingStarted Getting Started
Use the <a href="https://github.com/MITK/MITK-ProjectTemplate">MITK project template</a> as an
example-based project template.
\section HowToNewProjectPrerequisites Prerequisites
What ever option you choose, a MITK-based project needs essentially the same
prerequisites as MITK itself. Please see \ref BuildInstructions_Prerequisites for
details.
\note If you use one of the two options above you will \b not \b need to build MITK
yourself. This will be done automatically.
\section HowToNewProjectCreatingSourceDir Preparing your source directory
In order to start developing with MITK, you first have to set up the source directory
for your project.
\subsection HowToNewProjectSourceUsingTemplate Using the MITK Project Template
Download the project as a tarball or zipball and extract it to your desired source
directory.
\note This is a <b>template</b>. You must modify it such that it fits the needs of
your particular project. Especially you should do a global search and replace for
the string "awesome" to rename the template application and plug-in. You may want
to rename some files too.
\section HowToNewProjectGeneratingCMake Generating your binary with CMake
After you have set up your source directory you can proceed to generate your binary
directory using %CMake. Depending on your operating system and preferences you might
want to use "cmake-gui" or "ccmake" (shell). This document assumes you are using
cmake-gui.
<ol>
- <li> Start "cmake-gui" and enter your source (e.g. "D:\AwesomeProject") and binary
- directory (e.g. "D:\AwesomeProject-superbuild").
+ <li> Start "cmake-gui" and enter your source (e.g. "D:/AwesomeProject") and binary
+ directory (e.g. "D:/AwesomeProject-superbuild").
<li> Upon first pressing "Configure" you will be prompted to select your generator.
This determines what project files will be generated by %CMake. Set this to the
development tool you are intending to use (e.g. "Visual Studio 2010 64Bit" or
"linux makefiles".
<li> Press "Configure" until no new variables appear and then "Generate". Now all
project files have been generated into your binary directory.
<li> Double-check that the right Qt version is used.
</ol>
Now you are ready to compile your code. Depending on your choice of tool this will
be done differently, we cover two possibilities here.
\subsection HowToNewProjectCompilingLinuxMakefiles Compiling using linux makefiles
<ol>
<li> In the shell, switch to your binary directory.
<li> type "make" and hit enter
</ol>
\subsection HowToNewProjectCompilingVisualStudio Compiling using visual studio
We assume your application is called "AwesomeApp" and your project "AwesomeProject"
-and your binary directory is "D:\AwesomeProject-superbuild\". Replace names and
+and your binary directory is "D:/AwesomeProject-superbuild/". Replace names and
paths accordingly.
<ol>
- <li> Close %CMake and open "D:\AwesomeProject-superbuild\AwesomeProject-superbuild.sln".
+ <li> Close %CMake and open "D:/AwesomeProject-superbuild/AwesomeProject-superbuild.sln".
Your Visual Studio should appear and by pressing F7 you start the compilation.
This will clone the MITK source code, build it, and then start building your own
project.
<li> After the superbuild compilation has finished, close the superbuild solution file and start
- the build solution file "D:\AwesomeProject-superbuild\AwesomeProject-build\AwesomeProject.sln"
+ the build solution file "D:/AwesomeProject-superbuild/AwesomeProject-build/AwesomeProject.sln"
<li> Set the "AwesomeApp" project as start-up project (right click > "Set as StartUp
Project") and press "F5" to start your MITK AwesomeApp.
</ol>
\note Just opening AwesomeProject.sln from your explorer by double-cliking won`t
allow you to start or debug your application because the required environment
variables would be missing. Use the supplied batch files or set your PATH variable
accordingly.
\section HowToNewProjectAddingMITKFunctionality I want to use some MITK plugin but
it is not available
Due to the sheer number of MITK plugins not every plugin is activated by default.
To activate a specific plugin (again replace paths as needed):
<ol>
<li> Start "cmake-gui" and set the binary directory to
- "D:\AwesomeProject-superbuild\MITK-superbuild\MITK-build\", the source will
+ "D:/AwesomeProject-superbuild/MITK-superbuild/MITK-build/", the source will
adjust automatically and you will see new settings appear.
<li> Navigate to the plugin you want to use (e.g. "MITK_BUILD_org.mitk.gui.qt.segmentation")
and tick the checkbox behind it
<li> Press "Configure" until no new variables appear and then "Generate".
<li> Build MITK using your development tool (as in
\ref HowToNewProjectCompilingLinuxMakefiles or \ref HowToNewProjectCompilingVisualStudio
- only in the "D:\AwesomeProject-superbuild\MITK-superbuild\MITK-build\" directory )
+ only in the "D:/AwesomeProject-superbuild/MITK-superbuild/MITK-build/" directory )
<li> Start "cmake-gui" and set the binary directory to
- "D:\AwesomeProject-superbuild\AwesomeProject-build\", the source will adjust
+ "D:/AwesomeProject-superbuild/AwesomeProject-build/", the source will adjust
automatically and you will see new settings appear.
<li> Press "Configure" until no new variables appear and then "Generate".
<li> Build your project
<li> Start your application
</ol>
\note If you want to use an application provided by MITK (e.g. MITK Workbench) you
have to tick the appropriate checkbox as well (in this case MITK_BUILD_APP_Workbench)
and build MITK. Do note, that this application will be located in the bin directory
-of the "D:\AwesomeProject-superbuild\MITK-superbuild\MITK-build\" folder.
+of the "D:/AwesomeProject-superbuild/MITK-superbuild/MITK-build/" folder.
\section HowToNewProjectAdvancedInformation Information for advanced users
\subsection HowToNewProjectCustomizingMITK Customizing MITK
You can either inject an already build MITK to be used by your project or configure
some MITK options directly in your project's superbuild configuration if MITK is
going to be build inside your project.
\subsection HowToNewProjectCustomizingMITKInjectMITK Inject a MITK build
By setting the \b EXTERNAL_MITK_DIR \b variable in your project's superbuild
%CMake configuration to a MITK build directory (containing the MITKConfig.cmake)
you can skip the MITK build process.
If MITK is the only external project in your project, you might want to disable
the superbuild of your project completely (set <your-proj-name>_USE_SUPERBUILD
to OFF or edit your CMakeLists.txt file to set it to OFF by default) and set
the \b MITK_DIR \b %CMake variable to your MITK build directory.
\subsection HowToNewProjectCustomizingMITKConfigure Configure the MITK superbuild
If MITK is being build inside your project's superbuild process, you can enable
the use of certain third-party libraries inside of MITK. The following variables
control the MITK configuration:
<ul>
<li> \b MITK_USE_BLUEBERRY Enable the use of the BlueBerry application framework
<li> \b MITK_USE_CTK Download, compile, and use CTK in MITK
<li> \b MITK_USE_DCMTK Download, compile, and use DCMTK in MITK
<li> \b MITK_USE_OpenCV Download, compile, and use OpenCV in MITK
<li> \b MITK_USE_Python3 Download and compile 1CableSwig and enable Python
wrapping in ITK, VTK, OpenCV, and MITK
<li> \b MITK_USE_Qt5 Use the Qt 5 framework in MITK
</ul>
You can also inject already build third-party libraries from inside your project's
superbuild in the MITK superbuild by using any of the following %CMake variables:
<ul>
<li> \b MITK_CTK_DIR Reuse a CTK build directory in MITK.
<li> \b MITK_CableSwig_DIR Reuse a 1CableSwig build directory in MITK.
<li> \b MITK_DCMTK_DIR Reuse a DCMKT build directory in MITK.
<li> \b MITK_GDCM_DIR Reuse a GDCM build directory in MITK.
<li> \b MITK_ITK_DIR Reuse a ITK build directory in MITK.
<li> \b MITK_OpenCV_DIR Reuse a OpenCV build directory in MITK.
<li> \b MITK_VTK_DIR Reuse a VTK build directory in MITK.
</ul>
If the corresponding \b MITK_USE_<proj> \b option is set to on, the MITK
superbuild will use the provided build directory instead of building the
project itself.
You can also control the source code location for MITK in your project's
superbuild configuration by using the following %CMake variables:
<ul>
<li> \b MITK_SOURCE_DIR The path to the MITK source directory. If the value
for this variable is non-empty, the variables below are ignored.
<li> \b MITK_GIT_REPOSITORY The Git repository containing the MITK source code.
<li> \b MITK_GIT_TAG The hash id, tag or branch name used for a checkout
from MITK_GIT_REPOSITORY.
</ul>
\subsection HowToNewProjectProjectStructure Project Structure
If you are using the superbuild feature of the generated project (the default),
you might want to familiarise yourself with the layout of your build tree.
The top-level build directory which you specified in %CMake when configuring
your project will contain all the required dependencies.
Suppose we call our project MyProject and the build directory is
"C:\MyProject-superbuild". Then the layout looks something like this:
MyProjectLayout.png The top-level directory contains the source code and the
build directories from the dependencies of your project. In the current case,
the only dependency of MyProject is MITK, which in turn has downloaded and built
its own dependencies (CTK, DCMTK, ITK, etc.). The "real" build tree for your
project is located in MyProject-superbuild/MyProject-build, so point the
%CMake-GUI to this build directory if you want to change the set of enabled
plug-ins for example.
Further, you should open the MyProject.sln solution file (for Visual Studio)
or execute "make" in the MyProject-superbuild/MyProject-build/ directory.
Only for the very first time or if you want to update and newly build the
project's dependencies should you use the project files in the
MyProject-superbuild directory directly.
The same applies for the MyProject-superbuild/MITK-superbuild directory. This
directory contains the MITK superbuild, nested inside your project's superbuild.
If you want to change %CMake options for MITK, use the
MyProject-superbuild/MITK-superbuild/MITK-build build directory.
\imageMacro{HowToNewProject-MyProjectLayout.png,"Layout of MyProject",4.02}
\subsection HowToNewProjectPackaging Packaging
You can create deployable packages of your project
for all supported operating systems my building the PACKAGE target. On Linux,
this will create a tarball, on MacOS a .dmg file, and on Windows a zipball and
an NSIS installer (if NSIS is installed and found).
You can read more about deployment \ref DeploymentPage "here".
*/
diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox
index b8781ce573..b96e8c8e25 100644
--- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox
+++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox
@@ -1,115 +1,111 @@
/**
\page thirdpartylibs Third-party libraries
The following third-party libraries can be used with MITK by default and can, in part, be automatically downloaded during superbuild.
\par ACVD
https://www.creatis.insa-lyon.fr/~valette/public/project/acvd/
\par ANN
https://www.cs.umd.edu/~mount/ANN/
\par Boost
https://www.boost.org/
\par C++ REST SDK
https://github.com/Microsoft/cpprestsdk/
\par CppUnit
https://sourceforge.net/projects/cppunit/
\par CTK
https://commontk.org/
\par DCMTK
https://dicom.offis.de/dcmtk
\par Eigen
https://eigen.tuxfamily.org/index.php?title=Main_Page
\par GDCM
https://gdcm.sourceforge.net/
\par HDF5
https://support.hdfgroup.org/HDF5/
\par ITK
https://itk.org/
\par JSON for Modern C++
https://github.com/nlohmann/json
\par lz4
https://github.com/lz4/lz4
\par MatchPoint
https://www.dkfz.de/en/sidt/projects/MatchPoint/info.html
\par OpenCL
https://www.khronos.org/opencl/
\par OpenCV
https://opencv.org/
\par OpenIGTLink
http://openigtlink.org/
\par PCRE
https://www.pcre.org/
\par POCO
https://pocoproject.org/
\par Python
https://www.python.org/
\par Qt
https://www.qt.io/
\par Qwt
https://qwt.sourceforge.io/
\par SWIG
https://www.swig.org/
\par TinyXML-2
https://www.grinninglizard.com/tinyxml2/
-\par VIGRA
-
-https://ukoethe.github.io/vigra/
-
\par VTK
https://vtk.org/
\par zlib
https://zlib.net/
For copyright information on any of the above toolkits see the corresponding home page or the corresponding source folder.
*/
diff --git a/Documentation/Doxygen/4-API/Pages.dox b/Documentation/Doxygen/4-API/Pages.dox
index 66c853c23c..6a94d8dc3f 100644
--- a/Documentation/Doxygen/4-API/Pages.dox
+++ b/Documentation/Doxygen/4-API/Pages.dox
@@ -1,48 +1,51 @@
/**
\defgroup MITKDeprecatedAPI Deprecated
\page deprecatedSince2012_09 Deprecated as of 2012.09
\ingroup MITKDeprecatedAPI
\page deprecatedSince2013_03 Deprecated as of 2013.03
\ingroup MITKDeprecatedAPI
\page deprecatedSince2013_06 Deprecated as of 2013.06
\ingroup MITKDeprecatedAPI
\page deprecatedSince2013_09 Deprecated as of 2013.09
\ingroup MITKDeprecatedAPI
\page deprecatedSince2014_03 Deprecated as of 2014.03
\ingroup MITKDeprecatedAPI
\page deprecatedSince2014_10 Deprecated as of 2014.10
\ingroup MITKDeprecatedAPI
\page deprecatedSince2015_05 Deprecated as of 2015.05
\ingroup MITKDeprecatedAPI
\page deprecatedSince2016_03 Deprecated as of 2016.03
\ingroup MITKDeprecatedAPI
\page deprecatedSince2016_11 Deprecated as of 2016.11
\ingroup MITKDeprecatedAPI
\page deprecatedSince2018_04 Deprecated as of 2018.04
\ingroup MITKDeprecatedAPI
\page deprecatedSince2021_02 Deprecated as of 2021.02
\ingroup MITKDeprecatedAPI
\page deprecatedSince2021_10 Deprecated as of 2021.10
\ingroup MITKDeprecatedAPI
\page deprecatedSince2022_04 Deprecated as of 2022.04
\ingroup MITKDeprecatedAPI
\page deprecatedSince2022_10 Deprecated as of 2022.10
\ingroup MITKDeprecatedAPI
+\page deprecatedSince2023_04 Deprecated as of 2023.04
+\ingroup MITKDeprecatedAPI
+
*/
diff --git a/Documentation/doxygen.conf.in b/Documentation/doxygen.conf.in
index 51573d0011..8f0be3626e 100644
--- a/Documentation/doxygen.conf.in
+++ b/Documentation/doxygen.conf.in
@@ -1,2432 +1,2841 @@
-# Doxyfile 1.8.8
+# Doxyfile 1.9.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "Medical Imaging Interaction Toolkit"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = @MITK_VERSION_STRING@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "Medical Imaging Interaction Toolkit"
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = "@MITK_DOXYGEN_OUTPUT_DIR@"
+OUTPUT_DIRECTORY = @MITK_DOXYGEN_OUTPUT_DIR@
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL = 8
+
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 8
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
-# "sideeffect=@par Side Effects:\n"
+# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
ALIASES = "FIXME=\par Fix Me's:\n" \
"BlueBerry=\if BLUEBERRY" \
"endBlueBerry=\endif" \
"bundlemainpage{1}=\page \1" \
"embmainpage{1}=\page \1" \
"github{2}=<a href=\"https://github.com/MITK/MITK/blob/master/\1\">\2</a>" \
- "deprecatedSince{1}=\xrefitem deprecatedSince\1 \"\" \"Functions deprecated as of \1\" \deprecated (as of \1) " \
+ "deprecatedSince{1}=\xrefitem deprecatedSince\1 \"\" \"Functions deprecated as of \1\" \deprecated (as of \1)" \
"minimumCMakeVersion=@MITK_CMAKE_MINIMUM_REQUIRED_VERSION@" \
"minimumQt5Version=@MITK_QT5_MINIMUM_VERSION@" \
"imageMacro{3}=\image html \1 \2 \n \image latex \1 \2 width=\3cm" \
- "developersguidemainpage{1}=\page \1 " \
- "usersguidemainpage{1}=\page \1 " \
- "nondependentPluginLink{3}= \ref \1 \"\3\" "
+ "developersguidemainpage{1}=\page \1" \
+ "usersguidemainpage{1}=\page \1" \
+ "nondependentPluginLink{3}= \ref \1 \"\3\""
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
EXTENSION_MAPPING = cmake=c++
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = YES
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = @MITK_DOXYGEN_INTERNAL_DOCS@
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = @MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS@
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = @MITK_DOXYGEN_INTERNAL_DOCS@
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = YES
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order. Note that
+# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = YES
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = @MITK_DOXYGEN_GENERATE_TODOLIST@
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = @MITK_DOXYGEN_GENERATE_BUGLIST@
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= @MITK_DOXYGEN_GENERATE_DEPRECATEDLIST@
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS = @MITK_DOXYGEN_ENABLED_SECTIONS@
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 0
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
-LAYOUT_FILE = "@MITK_SOURCE_DIR@/Documentation/MITKDoxygenLayout.xml"
+LAYOUT_FILE = @MITK_SOURCE_DIR@/Documentation/MITKDoxygenLayout.xml
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = NO
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT = "at line $line of file $file"
+
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
-# error (stderr).
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
-
INPUT = "@MITK_SOURCE_DIR@" \
"@MITK_BINARY_DIR@" \
@MITK_DOXYGEN_ADDITIONAL_INPUT_DIRS@
-
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING =
+
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.h \
*.dox \
*.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE = "@MITK_SOURCE_DIR@/Utilities/qtsingleapplication/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/core/doc/snippets/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/core/doc/doxygen/standalone/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/core/test/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/core/examples/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/core/src/util/jsoncpp.cpp" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/third_party" \
"@MITK_SOURCE_DIR@/CMake/PackageDepends" \
"@MITK_SOURCE_DIR@/CMakeExternals" \
"@MITK_SOURCE_DIR@/Licenses" \
"@MITK_BINARY_DIR@/Documentation/Doxygen" \
"@MITK_BINARY_DIR@/bin/" \
"@MITK_BINARY_DIR@/PT/" \
"@MITK_BINARY_DIR@/GP/" \
"@MITK_BINARY_DIR@/_CPack_Packages/" \
@MITK_DOXYGEN_ADDITIONAL_EXCLUDE_DIRS@
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = README* \
moc_* \
ui_* \
qrc_* \
wrap_* \
Register* \
*/files.cmake \
*/.git/* \
*_p.h \
*Private.* \
*/Internal/* \
*/internal/* \
*/Snippets/* \
*/snippets/* \
*/testing/* \
*/Testing/* \
*/test/* \
*/resource/* \
"@MITK_BINARY_DIR@/*.cmake" \
@MITK_DOXYGEN_EXCLUDE_PATTERNS@
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
+# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH = "@MITK_SOURCE_DIR@/Examples/" \
"@MITK_SOURCE_DIR@/Examples/Tutorial/" \
"@MITK_SOURCE_DIR@/Examples/Plugins/" \
"@MITK_SOURCE_DIR@/Examples/QtFreeRender/" \
"@MITK_SOURCE_DIR@/Modules/Core/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/core/doc/snippets/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/core/examples/" \
"@MITK_SOURCE_DIR@/Modules/CppMicroServices/" \
"@MITK_SOURCE_DIR@/Modules/OpenCL/Documentation/doxygen/snippets/" \
"@MITK_SOURCE_DIR@/Modules/IGT/Tutorial/" \
"@MITK_SOURCE_DIR@/Plugins/org.mitk.gui.common/src/" \
"@MITK_SOURCE_DIR@/Plugins/org.mitk.gui.qt.igtexamples/" \
"@MITK_SOURCE_DIR@/Plugins/org.mitk.gui.qt.igttracking/"
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH = "@MITK_SOURCE_DIR@/Documentation/Doxygen/" \
"@MITK_SOURCE_DIR@" \
@MITK_DOXYGEN_ADDITIONAL_IMAGE_PATHS@
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
# <filter> <input-file>
#
# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS = *.cmake=@CMakeDoxygenFilter_EXECUTABLE@
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER = 72
+
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
+# entity all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX = 3
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
+# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra stylesheet files is of importance (e.g. the last
-# stylesheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET = @MITK_DOXYGEN_STYLESHEET@
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES = "@MITK_SOURCE_DIR@/Documentation/Doxygen/mitkLogo.jpg"
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE = AUTO_LIGHT
+
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = @MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS@
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = @MITK_DOXYGEN_GENERATE_QHP@
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE = @MITK_DOXYGEN_QCH_FILE@
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_NAMESPACE = "org.mitk"
+QHP_NAMESPACE = org.mitk
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = MITK
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION = @QT_HELPGENERATOR_EXECUTABLE@
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = YES
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 300
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
-FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = YES
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use <access key> + S
# (what the <access key> is depends on the OS and browser, but it is typically
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
# key> to jump into the search results window, the results can be navigated
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
# to select a filter and <Enter> or <escape> to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES = amssymb
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
#
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
-# for the replacement values of the other commands the user is refered to
-# HTML_HEADER.
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer. See
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
-# special commands can be used inside the footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = NO
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
+# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE = NO
-
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
-# program listings (including syntax highlighting and cross-referencing
-# information) to the DOCBOOK output. Note that enabling this will significantly
-# increase the size of the DOCBOOK output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_PROGRAMLISTING = NO
-
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
-# preprocessor.
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = itkNotUsed(x)= \
"itkSetMacro(name,type)=virtual void Set##name (type _arg);" \
"itkGetMacro(name,type)=virtual type Get##name ();" \
"itkGetConstMacro(name,type)=virtual type Get##name () const;" \
"itkSetStringMacro(name)=virtual void Set##name (const char* _arg);" \
"itkGetStringMacro(name)=virtual const char* Get##name () const;" \
"itkSetClampMacro(name,type,min,max)=virtual void Set##name (type _arg);" \
"itkSetObjectMacro(name,type)=virtual void Set##name (type* _arg);" \
"itkGetObjectMacro(name,type)=virtual type* Get##name ();" \
"itkSetConstObjectMacro(name,type)=virtual void Set##name ( const type* _arg);" \
"itkGetConstObjectMacro(name,type)=virtual const type* Get##name ();" \
"itkGetConstReferenceMacro(name,type)=virtual const type& Get##name ();" \
"itkGetConstReferenceObjectMacro(name,type)=virtual const type::Pointer& Get##name () const;" \
"itkBooleanMacro(name)=virtual void name##On (); virtual void name##Off ();" \
"itkSetVector2Macro(name,type)=virtual void Set##name (type _arg1, type _arg2) virtual void Set##name (type _arg[2]);" \
"itkGetVector2Macro(name,type)=virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2) const; virtual void Get##name (type _arg[2]) const;" \
"itkSetVector3Macro(name,type)=virtual void Set##name (type _arg1, type _arg2, type _arg3) virtual void Set##name (type _arg[3]);" \
"itkGetVector3Macro(name,type)=virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3) const; virtual void Get##name (type _arg[3]) const;" \
"itkSetVector4Macro(name,type)=virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4) virtual void Set##name (type _arg[4]);" \
"itkGetVector4Macro(name,type)=virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4) const; virtual void Get##name (type _arg[4]) const;" \
"itkSetVector6Macro(name,type)=virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4, type _arg5, type _arg6) virtual void Set##name (type _arg[6]);" \
"itkGetVector6Macro(name,type)=virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4, type& _arg5, type& _arg6) const; virtual void Get##name (type _arg[6]) const;" \
"itkSetVectorMacro(name,type,count)=virtual void Set##name(type data[]);" \
"itkGetVectorMacro(name,type,count)=virtual type* Get##name () const;" \
"itkNewMacro(type)=static Pointer New();" \
"itkFactorylessNewMacro(type)=static Pointer New();" \
"itkCloneMacro(type)=Pointer Clone() const;" \
"itkTypeMacro(thisClass,superclass)=virtual const char *GetClassName() const;" \
"itkConceptMacro(name,concept)=enum { name = 0 };" \
"ITK_NUMERIC_LIMITS=std::numeric_limits" \
"ITK_TYPENAME=typename" \
"FEM_ABSTRACT_CLASS(thisClass,parentClass)=public: /** Standard Self typedef.*/ typedef thisClass Self; /** Standard Superclass typedef. */ typedef parentClass Superclass; /** Pointer or SmartPointer to an object. */ typedef Self* Pointer; /** Const pointer or SmartPointer to an object. */ typedef const Self* ConstPointer; private:" \
"FEM_CLASS(thisClass,parentClass)=FEM_ABSTRACT_CLASS(thisClass,parentClass) public: /** Create a new object from the existing one */ virtual Baseclass::Pointer Clone() const; /** Class ID for FEM object factory */ static const int CLID; /** Virtual function to access the class ID */ virtual int ClassID() const { return CLID; /** Object creation in an itk compatible way */ static Self::Pointer New() { return new Self(); } private:" \
FREEVERSION \
ERROR_CHECKING \
HAS_TIFF \
HAS_JPEG \
HAS_NETLIB \
HAS_PNG \
HAS_ZLIB \
HAS_GLUT \
HAS_QT \
VCL_USE_NATIVE_STL=1 \
VCL_USE_NATIVE_COMPLEX=1 \
VCL_HAS_BOOL=1 \
VXL_BIG_ENDIAN=1 \
VXL_LITTLE_ENDIAN=0 \
VNL_DLL_DATA= \
"US_PREPEND_NAMESPACE(x)=us::x" \
"US_BEGIN_NAMESPACE= namespace us {" \
"US_END_NAMESPACE=}" \
"US_BASECLASS_NAME=itk::LightObject" \
US_EXPORT= \
"DEPRECATED(func)=func" \
"mitkSegmentationTaskValueMacro(type, name)=bool Has##name() const; type Get##name() const; void Set##name(const type& value);" \
"mitkSegmentationTaskListValueMacro(type, name)=bool Has##name(size_t index) const; type Get##name(size_t index) const; void SetDefault##name(const type& value);" \
@US_PLATFORM@
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE = @MITK_DOXYGEN_TAGFILE_NAME@
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = NO
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
-
-CLASS_DIAGRAMS = YES
-
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = @HAVE_DOT@
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = @MITK_DOXYGEN_DOT_NUM_THREADS@
-# When you want a differently looking font in the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTNAME = Helvetica
+DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTSIZE = 10
+DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = @MITK_DOXYGEN_UML_LOOK@
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = YES
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = NO
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = NO
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = NO
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH = "@DOXYGEN_DOT_PATH@"
+DOT_PATH = @DOXYGEN_DOT_PATH@
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
-# path where java can find the plantuml.jar file. If left blank, it is assumed
-# PlantUML is not used or called during a preprocessing step. Doxygen will
-# generate a warning when it encounters a \startuml command in this case and
-# will not generate output for the diagram.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 120
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/Documentation/doxygen_developers_guide.conf.in b/Documentation/doxygen_developers_guide.conf.in
index 40b23f0bb8..13903e9c89 100644
--- a/Documentation/doxygen_developers_guide.conf.in
+++ b/Documentation/doxygen_developers_guide.conf.in
@@ -1,2328 +1,2739 @@
-# Doxyfile 1.8.8
+# Doxyfile 1.9.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = MITK
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = @MITK_VERSION_STRING@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "Medical Imaging Interaction Toolkit"
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = "@MITK_DOXYGEN_OUTPUT_DIR@/Guides/Developers_Guide/"
+OUTPUT_DIRECTORY = @MITK_DOXYGEN_OUTPUT_DIR@/Guides/Developers_Guide/
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL = 8
+
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 8
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
-# "sideeffect=@par Side Effects:\n"
+# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
ALIASES = "FIXME=\par Fix Me's:\n" \
"BlueBerry=\if BLUEBERRY" \
"endBlueBerry=\endif" \
"bundlemainpage{1}=\page \1" \
"embmainpage{1}=\page \1" \
"github{2}=<a href=\"https://github.com/MITK/MITK/blob/master/\1\">\2</a>" \
- "deprecatedSince{1}=\xrefitem deprecatedSince\1 \" Deprecated as of \1\" \"Functions deprecated as of \1\" " \
+ "deprecatedSince{1}=\xrefitem deprecatedSince\1 \" Deprecated as of \1\" \"Functions deprecated as of \1\"" \
"minimumCMakeVersion=@MITK_CMAKE_MINIMUM_REQUIRED_VERSION@" \
"minimumQt5Version=@MITK_QT5_MINIMUM_VERSION@" \
"imageMacro{3}=\image html \1 \2 \n \image latex \1 \2 width=\3cm" \
- "developersguidemainpage{1}=\mainpage " \
+ "developersguidemainpage{1}=\mainpage" \
"usersguidemainpage{1}=\page \1" \
- "nondependentPluginLink{3}= \ref \1 \"\3\" "
+ "nondependentPluginLink{3}= \ref \1 \"\3\""
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = YES
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = @MITK_DOXYGEN_INTERNAL_DOCS@
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = @MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS@
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = @MITK_DOXYGEN_INTERNAL_DOCS@
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = YES
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order. Note that
+# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = YES
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = @MITK_DOXYGEN_GENERATE_TODOLIST@
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = @MITK_DOXYGEN_GENERATE_BUGLIST@
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= @MITK_DOXYGEN_GENERATE_DEPRECATEDLIST@
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS = @MITK_DOXYGEN_ENABLED_SECTIONS@
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 0
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = NO
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = NO
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = NO
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT = "at line $line of file $file"
+
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
-# error (stderr).
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = "@MITK_SOURCE_DIR@/Core/Documentation/Doxygen/Concepts/" \
"@MITK_SOURCE_DIR@/Documentation/Doxygen/DeveloperManual/" \
"@MITK_SOURCE_DIR@/Modules/"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING =
+
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.dox \
*.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = modules.dox \
*/Plugins/*/documentation/doxygen/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
+# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH = "@MITK_SOURCE_DIR@/Core/Documentation/Doxygen/Concepts/" \
"@MITK_SOURCE_DIR@/Documentation/Doxygen/DeveloperManual/" \
"@MITK_SOURCE_DIR@/Modules/"
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
# <filter> <input-file>
#
# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS = *.cmake=@CMakeDoxygenFilter_EXECUTABLE@
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER = 72
+
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
+# entity all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX = 3
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = NO
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
+# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra stylesheet files is of importance (e.g. the last
-# stylesheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET = @MITK_DOXYGEN_STYLESHEET@
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE = AUTO_LIGHT
+
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = @MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS@
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = @MITK_DOXYGEN_GENERATE_QHP@
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE = @MITK_DOXYGEN_QCH_FILE@
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_NAMESPACE = "org.mitk"
+QHP_NAMESPACE = org.mitk
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = MITK
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION = @QT_HELPGENERATOR_EXECUTABLE@
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = YES
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 300
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
-FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use <access key> + S
# (what the <access key> is depends on the OS and browser, but it is typically
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
# key> to jump into the search results window, the results can be navigated
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
# to select a filter and <Enter> or <escape> to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES = amssymb
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
#
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
-# for the replacement values of the other commands the user is refered to
-# HTML_HEADER.
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer. See
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
-# special commands can be used inside the footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
+# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = YES
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = YES
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE = NO
-
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
-# program listings (including syntax highlighting and cross-referencing
-# information) to the DOCBOOK output. Note that enabling this will significantly
-# increase the size of the DOCBOOK output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_PROGRAMLISTING = NO
-
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
-# preprocessor.
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES = @BLUEBERRY_DOXYGEN_TAGFILE@
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE = @MITK_DOXYGEN_TAGFILE_NAME@
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = NO
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
-
-CLASS_DIAGRAMS = YES
-
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = @HAVE_DOT@
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = @MITK_DOXYGEN_DOT_NUM_THREADS@
-# When you want a differently looking font in the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTNAME = Helvetica
+DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTSIZE = 10
+DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = @MITK_DOXYGEN_UML_LOOK@
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = YES
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = NO
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = NO
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = NO
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH = "@DOXYGEN_DOT_PATH@"
+DOT_PATH = @DOXYGEN_DOT_PATH@
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
-# path where java can find the plantuml.jar file. If left blank, it is assumed
-# PlantUML is not used or called during a preprocessing step. Doxygen will
-# generate a warning when it encounters a \startuml command in this case and
-# will not generate output for the diagram.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/Documentation/doxygen_plugin_manual.conf.in b/Documentation/doxygen_plugin_manual.conf.in
index 2c92ca6e5c..d05f1931a7 100644
--- a/Documentation/doxygen_plugin_manual.conf.in
+++ b/Documentation/doxygen_plugin_manual.conf.in
@@ -1,2318 +1,2729 @@
-# Doxyfile 1.8.8
+# Doxyfile 1.9.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = "@Plugin-Name@"
+PROJECT_NAME = @Plugin-Name@
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = "@PLUGIN_DOXYGEN_OUTPUT_DIR@"
+OUTPUT_DIRECTORY = @PLUGIN_DOXYGEN_OUTPUT_DIR@
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL = 8
+
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 8
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
-# "sideeffect=@par Side Effects:\n"
+# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
ALIASES = bundlemainpage{1}=\mainpage \
"isHtml=\if NO_SUCH_THING" \
"isHtmlend=\endif" \
"imageMacro{3}=\image html \1 \2 \n \image latex \1 \2 width=\3cm" \
- "developersguidemainpage{1}=\page \1 " \
- "usersguidemainpage{1}=\page \1 " \
- "nondependentPluginLink{3}= <a href=\"qthelp://\2/bundle/\1.html\"> \3 </a> "
+ "developersguidemainpage{1}=\page \1" \
+ "usersguidemainpage{1}=\page \1" \
+ "nondependentPluginLink{3}= <a href=\"qthelp://\2/bundle/\1.html\"> \3 </a>"
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = YES
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order. Note that
+# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = NO
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = NO
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = NO
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = NO
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= NO
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = NO
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = NO
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT = "at line $line of file $file"
+
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
-# error (stderr).
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = "@PLUGIN_DOXYGEN_INPUT_DIR@"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING =
+
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.dox \
*.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
+# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH = "@PLUGIN_DOXYGEN_INPUT_DIR@" \
"@MITK_SOURCE_DIR@/Modules/"
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
# <filter> <input-file>
#
# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER = 72
+
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = YES
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
+# entity all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = NO
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX = 3
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
+# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra stylesheet files is of importance (e.g. the last
-# stylesheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE = AUTO_LIGHT
+
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = NO
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = YES
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE = @Plugin-SymbolicName@
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = bundle
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME = @PLUGIN_QHP_CUST_FILTER_NAME@
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS = @PLUGIN_QHP_CUST_FILTER_ATTRS@
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS = @PLUGIN_QHP_SECT_FILTER_ATTRS@
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = YES
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
-FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use <access key> + S
# (what the <access key> is depends on the OS and browser, but it is typically
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
# key> to jump into the search results window, the results can be navigated
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
# to select a filter and <Enter> or <escape> to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES =
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
#
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
-# for the replacement values of the other commands the user is refered to
-# HTML_HEADER.
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer. See
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
-# special commands can be used inside the footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = NO
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
+# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE = NO
-
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
-# program listings (including syntax highlighting and cross-referencing
-# information) to the DOCBOOK output. Note that enabling this will significantly
-# increase the size of the DOCBOOK output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_PROGRAMLISTING = NO
-
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
-# preprocessor.
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES = @PLUGIN_DOXYGEN_TAGFILES@
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
-GENERATE_TAGFILE = "@PLUGIN_DOXYGEN_OUTPUT_DIR@/@PROJECT_NAME@.tag"
+GENERATE_TAGFILE = @PLUGIN_DOXYGEN_OUTPUT_DIR@/@PROJECT_NAME@.tag
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
-
-CLASS_DIAGRAMS = YES
-
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = NO
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = 0
-# When you want a differently looking font in the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTNAME = Helvetica
+DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTSIZE = 10
+DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = YES
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = YES
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
-# path where java can find the plantuml.jar file. If left blank, it is assumed
-# PlantUML is not used or called during a preprocessing step. Doxygen will
-# generate a warning when it encounters a \startuml command in this case and
-# will not generate output for the diagram.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = YES
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/Documentation/doxygen_users_guide.conf.in b/Documentation/doxygen_users_guide.conf.in
index 9d35050568..b37e0c17ab 100644
--- a/Documentation/doxygen_users_guide.conf.in
+++ b/Documentation/doxygen_users_guide.conf.in
@@ -1,2326 +1,2737 @@
-# Doxyfile 1.8.8
+# Doxyfile 1.9.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = MITK
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = @MITK_VERSION_STRING@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "Medical Imaging Interaction Toolkit"
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = "@MITK_DOXYGEN_OUTPUT_DIR@/Guides/Users_Guide/"
+OUTPUT_DIRECTORY = @MITK_DOXYGEN_OUTPUT_DIR@/Guides/Users_Guide/
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL = 8
+
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 8
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
-# "sideeffect=@par Side Effects:\n"
+# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
ALIASES = "FIXME=\par Fix Me's:\n" \
"BlueBerry=\if BLUEBERRY" \
"endBlueBerry=\endif" \
"bundlemainpage{1}=\page \1" \
"embmainpage{1}=\page \1" \
"github{2}=<a href=\"https://github.com/MITK/MITK/blob/master/\1\">\2</a>" \
- "deprecatedSince{1}=\xrefitem deprecatedSince\1 \" Deprecated as of \1\" \"Functions deprecated as of \1\" " \
+ "deprecatedSince{1}=\xrefitem deprecatedSince\1 \" Deprecated as of \1\" \"Functions deprecated as of \1\"" \
"minimumCMakeVersion=@MITK_CMAKE_MINIMUM_REQUIRED_VERSION@" \
"minimumQt5Version=@MITK_QT5_MINIMUM_VERSION@" \
"imageMacro{3}=\image html \1 \2 \n \image latex \1 \2 width=\3cm" \
- "developersguidemainpage{1}=\page \1 " \
- "usersguidemainpage{1}=\mainpage " \
- "nondependentPluginLink{3}= \ref \1 \"\3\" "
+ "developersguidemainpage{1}=\page \1" \
+ "usersguidemainpage{1}=\mainpage" \
+ "nondependentPluginLink{3}= \ref \1 \"\3\""
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = YES
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = @MITK_DOXYGEN_INTERNAL_DOCS@
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = @MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS@
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = @MITK_DOXYGEN_INTERNAL_DOCS@
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = YES
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order. Note that
+# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = YES
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = @MITK_DOXYGEN_GENERATE_TODOLIST@
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = @MITK_DOXYGEN_GENERATE_BUGLIST@
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= @MITK_DOXYGEN_GENERATE_DEPRECATEDLIST@
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS = @MITK_DOXYGEN_ENABLED_SECTIONS@
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 0
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = NO
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT = "at line $line of file $file"
+
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
-# error (stderr).
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = @USERS_GUIDE_INPUT@
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING =
+
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.dox \
*.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = modules.dox \
*/Plugins/*/documentation/doxygen/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
+# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH = "@MITK_SOURCE_DIR@/Documentation/Doxygen/UserManual/" \
"@MITK_SOURCE_DIR@/Plugins/" \
"@MITK_SOURCE_DIR@/Examples/Plugins/"
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
# <filter> <input-file>
#
# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS = *.cmake=@CMakeDoxygenFilter_EXECUTABLE@
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER = 72
+
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
+# entity all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX = 3
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = NO
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
+# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra stylesheet files is of importance (e.g. the last
-# stylesheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET = @MITK_DOXYGEN_STYLESHEET@
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE = AUTO_LIGHT
+
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = @MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS@
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = @MITK_DOXYGEN_GENERATE_QHP@
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE = @MITK_DOXYGEN_QCH_FILE@
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_NAMESPACE = "org.mitk"
+QHP_NAMESPACE = org.mitk
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = MITK
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION = @QT_HELPGENERATOR_EXECUTABLE@
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = YES
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 300
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
-FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use <access key> + S
# (what the <access key> is depends on the OS and browser, but it is typically
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
# key> to jump into the search results window, the results can be navigated
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
# to select a filter and <Enter> or <escape> to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES = amssymb
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
#
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
-# for the replacement values of the other commands the user is refered to
-# HTML_HEADER.
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer. See
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
-# special commands can be used inside the footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
+# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = YES
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE = NO
-
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
-# program listings (including syntax highlighting and cross-referencing
-# information) to the DOCBOOK output. Note that enabling this will significantly
-# increase the size of the DOCBOOK output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_PROGRAMLISTING = NO
-
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
-# preprocessor.
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES = @BLUEBERRY_DOXYGEN_TAGFILE@
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE = @MITK_DOXYGEN_TAGFILE_NAME@
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = NO
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
-
-CLASS_DIAGRAMS = YES
-
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = @HAVE_DOT@
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = @MITK_DOXYGEN_DOT_NUM_THREADS@
-# When you want a differently looking font in the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTNAME = Helvetica
+DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTSIZE = 10
+DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = @MITK_DOXYGEN_UML_LOOK@
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = YES
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = NO
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = NO
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = NO
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH = "@DOXYGEN_DOT_PATH@"
+DOT_PATH = @DOXYGEN_DOT_PATH@
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
-# path where java can find the plantuml.jar file. If left blank, it is assumed
-# PlantUML is not used or called during a preprocessing step. Doxygen will
-# generate a warning when it encounters a \startuml command in this case and
-# will not generate output for the diagram.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt
index 870475f3a0..2236a819d6 100644
--- a/Examples/CMakeLists.txt
+++ b/Examples/CMakeLists.txt
@@ -1,49 +1,49 @@
#-----------------------------------------------------------------------------
# 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
+ MitkLog
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/autoload/IO/mitkExampleIOMimeTypes.cpp b/Examples/FirstSteps/NewModule/autoload/IO/mitkExampleIOMimeTypes.cpp
index c2719c46b7..f375e04c9a 100644
--- a/Examples/FirstSteps/NewModule/autoload/IO/mitkExampleIOMimeTypes.cpp
+++ b/Examples/FirstSteps/NewModule/autoload/IO/mitkExampleIOMimeTypes.cpp
@@ -1,109 +1,109 @@
/*============================================================================
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 "mitkExampleIOMimeTypes.h"
#include "mitkIOMimeTypes.h"
#include <itksys/SystemTools.hxx>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
namespace mitk
{
std::vector<CustomMimeType *> ExampleIOMimeTypes::Get()
{
std::vector<CustomMimeType *> mimeTypes;
// order matters here (descending rank for mime types)
mimeTypes.push_back(EXAMPLE_MIMETYPE().Clone());
mimeTypes.push_back(EXAMPLE_TWO_MIMETYPE().Clone());
return mimeTypes;
}
// Mime Types
ExampleIOMimeTypes::ExampleDataStructureMimeType::ExampleDataStructureMimeType()
: CustomMimeType(EXAMPLE_MIMETYPE_NAME())
{
std::string category = "Example and Tutorial Data";
this->SetCategory(category);
this->SetComment("Example data structure containing just a string");
this->AddExtension("example");
this->AddExtension("txt");
}
bool ExampleIOMimeTypes::ExampleDataStructureMimeType::AppliesTo(const std::string &path) const
{
bool canRead(CustomMimeType::AppliesTo(path));
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if (!itksys::SystemTools::FileExists(path.c_str()))
{
return canRead;
}
// end fix for bug 18572
std::string ext = this->GetExtension(path);
ext = itksys::SystemTools::LowerCase(ext);
if (ext == ".txt")
{
// we could test something here
if (false)
{
MITK_WARN << "Can not read .txt file as ExampleDataStructure";
canRead = false;
}
}
return canRead;
}
ExampleIOMimeTypes::ExampleDataStructureMimeType *ExampleIOMimeTypes::ExampleDataStructureMimeType::Clone() const
{
return new ExampleDataStructureMimeType(*this);
}
ExampleIOMimeTypes::ExampleDataStructureMimeType ExampleIOMimeTypes::EXAMPLE_MIMETYPE()
{
return ExampleDataStructureMimeType();
}
CustomMimeType ExampleIOMimeTypes::EXAMPLE_TWO_MIMETYPE()
{
CustomMimeType mimeType(EXAMPLE_TWO_MIMETYPE_NAME());
std::string category = "Example and Tutorial Data";
mimeType.SetComment("Simpler Example Data MimeType");
mimeType.SetCategory(category);
mimeType.AddExtension("example2");
return mimeType;
}
// Names
std::string ExampleIOMimeTypes::EXAMPLE_MIMETYPE_NAME()
{
// create a unique and sensible name for this mime type
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".examples.example-data-structure";
return name;
}
std::string ExampleIOMimeTypes::EXAMPLE_TWO_MIMETYPE_NAME()
{
// create a unique and sensible name for this mime type
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".examples.example-data-structure-the-second";
return name;
}
}
diff --git a/Examples/MbiLog/CMakeLists.txt b/Examples/MitkLog/CMakeLists.txt
similarity index 68%
rename from Examples/MbiLog/CMakeLists.txt
rename to Examples/MitkLog/CMakeLists.txt
index d305cf5618..9a7269504d 100644
--- a/Examples/MbiLog/CMakeLists.txt
+++ b/Examples/MitkLog/CMakeLists.txt
@@ -1,3 +1,3 @@
-project(MbiLogExample)
+project(MitkLogExample)
mitk_create_executable(LogExample DEPENDS MitkCore)
diff --git a/Examples/MbiLog/MitkLogExample.cpp b/Examples/MitkLog/MitkLogExample.cpp
similarity index 83%
rename from Examples/MbiLog/MitkLogExample.cpp
rename to Examples/MitkLog/MitkLogExample.cpp
index f0ca47d2d2..ded2935c9b 100644
--- a/Examples/MbiLog/MitkLogExample.cpp
+++ b/Examples/MitkLog/MitkLogExample.cpp
@@ -1,19 +1,20 @@
/*============================================================================
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 <mitkLogMacros.h>
-#include <stdlib.h>
-int main(int /*argc*/, char ** /*argv*/)
+#include <mitkLog.h>
+#include <cstdlib>
+
+int main()
{
MITK_INFO << "Test log ...";
return EXIT_SUCCESS;
}
diff --git a/Examples/MbiLog/files.cmake b/Examples/MitkLog/files.cmake
similarity index 100%
rename from Examples/MbiLog/files.cmake
rename to Examples/MitkLog/files.cmake
diff --git a/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.cpp b/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.cpp
index 3195aa55ef..837e741fc2 100644
--- a/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.cpp
+++ b/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.cpp
@@ -1,211 +1,212 @@
/*============================================================================
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 "SimpleRenderWindowView.h"
#include <QmitkRenderWindow.h>
#include "org_mitk_example_gui_customviewer_views_Activator.h"
#include <mitkIRenderingManager.h>
#include <mitkInteractionConst.h>
#include <mitkSliceNavigationController.h>
+#include <mitkTimeNavigationController.h>
#include <QVBoxLayout>
#include <mitkPlaneGeometry.h>
/**
* \brief Helper class adapted from QmitkAbstractRenderEditor by defining the correct plugin context.
*
* This helper class adapted from QmitkAbstractRenderEditor provides the rendering manager interface.
*/
// //! [SimpleRenderWindowViewHelper]
class AbstractRenderWindowViewPrivate
{
public:
AbstractRenderWindowViewPrivate()
: m_RenderingManagerInterface(mitk::MakeRenderingManagerInterface(mitk::RenderingManager::GetInstance()))
// //! [SimpleRenderWindowViewHelper]
{
}
~AbstractRenderWindowViewPrivate() { delete m_RenderingManagerInterface; }
mitk::IRenderingManager *m_RenderingManagerInterface;
};
const std::string SimpleRenderWindowView::VIEW_ID = "org.mitk.customviewer.views.simplerenderwindowview";
SimpleRenderWindowView::SimpleRenderWindowView() : m_RenderWindow(nullptr), d(new AbstractRenderWindowViewPrivate)
{
}
SimpleRenderWindowView::~SimpleRenderWindowView()
{
}
QmitkRenderWindow *SimpleRenderWindowView::GetActiveQmitkRenderWindow() const
{
return m_RenderWindow;
}
QHash<QString, QmitkRenderWindow *> SimpleRenderWindowView::GetRenderWindows() const
{
QHash<QString, QmitkRenderWindow *> wnds;
wnds.insert("axial", m_RenderWindow);
return wnds;
}
QHash<QString, QmitkRenderWindow *> SimpleRenderWindowView::GetQmitkRenderWindows() const
{
QHash<QString, QmitkRenderWindow *> wnds;
wnds.insert("axial", m_RenderWindow);
return wnds;
}
QmitkRenderWindow *SimpleRenderWindowView::GetRenderWindow(const QString &id) const
{
if (id == "axial")
{
return m_RenderWindow;
}
return nullptr;
}
QmitkRenderWindow *SimpleRenderWindowView::GetQmitkRenderWindow(const QString &id) const
{
if (id == "axial")
{
return m_RenderWindow;
}
return nullptr;
}
QmitkRenderWindow *SimpleRenderWindowView::GetQmitkRenderWindow(const mitk::AnatomicalPlane& orientation) const
{
if (orientation == mitk::AnatomicalPlane::Axial)
{
return m_RenderWindow;
}
return 0;
}
void SimpleRenderWindowView::SetFocus()
{
m_RenderWindow->setFocus();
}
// //! [SimpleRenderWindowViewCreatePartControl]
void SimpleRenderWindowView::CreateQtPartControl(QWidget *parent)
{
QVBoxLayout *layout = new QVBoxLayout(parent);
layout->setContentsMargins(0, 0, 0, 0);
m_RenderWindow = new QmitkRenderWindow(parent);
layout->addWidget(m_RenderWindow);
mitk::DataStorage::Pointer ds = this->GetDataStorage();
m_RenderWindow->GetRenderer()->SetDataStorage(ds);
this->RequestUpdate();
}
// //! [SimpleRenderWindowViewCreatePartControl]
mitk::IRenderingManager *SimpleRenderWindowView::GetRenderingManager() const
{
// we use the global rendering manager here. This should maybe replaced
// by a local one, managing only the render windows specific for the view
return d->m_RenderingManagerInterface;
}
void SimpleRenderWindowView::RequestUpdate(mitk::RenderingManager::RequestType requestType)
{
if (GetRenderingManager())
GetRenderingManager()->RequestUpdateAll(requestType);
}
void SimpleRenderWindowView::ForceImmediateUpdate(mitk::RenderingManager::RequestType requestType)
{
if (GetRenderingManager())
GetRenderingManager()->ForceImmediateUpdateAll(requestType);
}
void SimpleRenderWindowView::InitializeViews(const mitk::TimeGeometry* /*geometry*/, bool /*resetCamera*/)
{
// not implemented
}
void SimpleRenderWindowView::SetInteractionReferenceGeometry(const mitk::TimeGeometry* /*referenceGeometry*/)
{
// not implemented
}
bool SimpleRenderWindowView::HasCoupledRenderWindows() const
{
return false;
}
-mitk::SliceNavigationController *SimpleRenderWindowView::GetTimeNavigationController() const
+mitk::TimeNavigationController *SimpleRenderWindowView::GetTimeNavigationController() const
{
if (GetRenderingManager())
return GetRenderingManager()->GetTimeNavigationController();
return nullptr;
}
mitk::Point3D SimpleRenderWindowView::GetSelectedPosition(const QString& /*id*/) const
{
const mitk::PlaneGeometry* pg = m_RenderWindow->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (pg)
{
return pg->GetCenter();
}
else
{
return mitk::Point3D();
}
}
void SimpleRenderWindowView::SetSelectedPosition(const mitk::Point3D&, const QString&)
{
}
mitk::TimePointType SimpleRenderWindowView::GetSelectedTimePoint(const QString& /*id*/) const
{
auto timeNavigator = this->GetTimeNavigationController();
if (nullptr != timeNavigator)
{
return timeNavigator->GetSelectedTimePoint();
}
return 0;
}
void SimpleRenderWindowView::EnableDecorations(bool enable, const QStringList& decorations)
{
if (decorations.isEmpty() || decorations.contains(DECORATION_MENU))
{
m_RenderWindow->ActivateMenuWidget(enable);
}
}
bool SimpleRenderWindowView::IsDecorationEnabled(const QString& decoration) const
{
if (decoration == DECORATION_MENU)
{
return m_RenderWindow->GetActivateMenuWidgetFlag();
}
return false;
}
QStringList SimpleRenderWindowView::GetDecorations() const
{
QStringList decorations;
decorations << DECORATION_MENU;
return decorations;
}
diff --git a/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.h b/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.h
index 7f055389b9..9c76c3e79c 100644
--- a/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.h
+++ b/Examples/Plugins/org.mitk.example.gui.customviewer.views/src/internal/SimpleRenderWindowView.h
@@ -1,162 +1,162 @@
/*============================================================================
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 SimpleRenderWindowView_H_
#define SimpleRenderWindowView_H_
#include <QmitkAbstractView.h>
#include <berryQtViewPart.h>
#include <mitkIRenderWindowPart.h>
class QmitkRenderWindow;
class AbstractRenderWindowViewPrivate;
/**
* \brief A view class suited for the ViewerPerspective within the custom viewer plug-in.
*
* This view class contributes data node rendering functionality to the ViewerPerspective.
* Being a subclass of QmitkAbstractView, this class yields access to the data storage and
* thus is interconnected with the mitk::QmitkDataManagerView present in the same perspective.
* As a subclass of mitk::IRenderWindowPart, this class provides an instance of QmitkRenderWindow.
* A SimpleRenderWindowView instance is part of the ViewerPerspective for data visualization.
*/
// //! [SimpleRenderWindowViewDeclaration]
class SimpleRenderWindowView : public QmitkAbstractView, public mitk::IRenderWindowPart
// //! [SimpleRenderWindowViewDeclaration]
{
Q_OBJECT
public:
/**
* Standard constructor.
*/
SimpleRenderWindowView();
~SimpleRenderWindowView() override;
/**
* String based view identifier.
*/
static const std::string VIEW_ID;
berryObjectMacro(SimpleRenderWindowView);
// ------------------- mitk::IRenderWindowPart ----------------------
/**
* \see mitk::IRenderWindowPart::GetActiveQmitkRenderWindow()
*/
QmitkRenderWindow *GetActiveQmitkRenderWindow() const override;
QHash<QString, QmitkRenderWindow *> GetRenderWindows() const;
/**
* \see mitk::IRenderWindowPart::GetQmitkRenderWindows()
*/
QHash<QString, QmitkRenderWindow *> GetQmitkRenderWindows() const override;
QmitkRenderWindow *GetRenderWindow(const QString &id) const;
/**
* \see mitk::IRenderWindowPart::GetQmitkRenderWindow(QString)
*/
QmitkRenderWindow *GetQmitkRenderWindow(const QString &id) const override;
/**
* \see mitk::IRenderWindowPart::GetQmitkRenderWindow(mitk::AnatomicalPlane)
*/
QmitkRenderWindow *GetQmitkRenderWindow(const mitk::AnatomicalPlane &orientation) const override;
/**
* \see mitk::QmitkAbstractRenderEditor::GetRenderingManager()
*/
mitk::IRenderingManager *GetRenderingManager() const override;
/**
* \see mitk::QmitkAbstractRenderEditor::RequestUpdate()
*/
void RequestUpdate(
mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL) override;
/**
* \see mitk::QmitkAbstractRenderEditor::ForceImmediateUpdate()
*/
void ForceImmediateUpdate(mitk::RenderingManager::RequestType) override;
/**
* \see mitk::IRenderWindowPart::InitializeViews()
*/
void InitializeViews(const mitk::TimeGeometry* geometry, bool resetCamera) override;
/**
* \see mitk::IRenderWindowPart::SetInteractionReferenceGeometry()
*/
void SetInteractionReferenceGeometry(const mitk::TimeGeometry* referenceGeometry) override;
/**
* \see mitk::IRenderWindowPart::HasCoupledRenderWindows
*/
bool HasCoupledRenderWindows() const override;
/**
* \see mitk::IRenderWindowPart::GetTimeNavigationController()
*/
- mitk::SliceNavigationController *GetTimeNavigationController() const override;
+ mitk::TimeNavigationController* GetTimeNavigationController() const override;
/**
* \see mitk::IRenderWindowPart::GetSelectionPosition()
*/
mitk::Point3D GetSelectedPosition(const QString& id = QString()) const override;
/**
* \see mitk::IRenderWindowPart::SetSelectedPosition()
*/
void SetSelectedPosition(const mitk::Point3D& pos, const QString& id = QString()) override;
/**
* \see mitk::IRenderWindowPart::GetSelectedTimePoint()
*/
mitk::TimePointType GetSelectedTimePoint(const QString& id = QString()) const override;
/**
* \see mitk::IRenderWindowPart::EnableDecorations()
*/
void EnableDecorations(bool enable, const QStringList& decorations = QStringList()) override;
/**
* \see mitk::IRenderWindowPart::IsDecorationEnabled()
*/
bool IsDecorationEnabled(const QString& decoration) const override;
/**
* \see mitk::IRenderWindowPart::GetDecorations()
*/
QStringList GetDecorations() const override;
protected:
void SetFocus() override;
/**
* Creates the QmitkRenderWindow whose renderer is being connected to the view's data storage.
*/
void CreateQtPartControl(QWidget *parent) override;
private:
/**
* The view's render window.
*/
QmitkRenderWindow *m_RenderWindow;
QScopedPointer<AbstractRenderWindowViewPrivate> d;
};
#endif /*SimpleRenderWindowView_H_*/
diff --git a/Examples/Plugins/org.mitk.example.gui.customviewer/manifest_headers.cmake b/Examples/Plugins/org.mitk.example.gui.customviewer/manifest_headers.cmake
index 058dcf0b91..170a057a2d 100644
--- a/Examples/Plugins/org.mitk.example.gui.customviewer/manifest_headers.cmake
+++ b/Examples/Plugins/org.mitk.example.gui.customviewer/manifest_headers.cmake
@@ -1,9 +1,8 @@
set(Plugin-Name "MITK Example Custom Viewer")
set(Plugin-Version "1.0.0")
set(Plugin-Vendor "German Cancer Research Center (DKFZ)")
set(Plugin-ContactAddress "https://www.mitk.org")
set(Require-Plugin
- org.mitk.core.ext # Registers file reader factories
org.mitk.gui.qt.application # Initializes GlobalInteraction and registers MITK Core factories
)
diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp b/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp
index dca9656896..46a131945b 100644
--- a/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp
+++ b/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp
@@ -1,276 +1,275 @@
/*============================================================================
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 "QmitkSimpleExampleView.h"
#include <ui_QmitkSimpleExampleViewControls.h>
#include <vtkImageWriter.h>
#include <vtkJPEGWriter.h>
#include <vtkPNGWriter.h>
#include <vtkRenderLargeImage.h>
-#include "QmitkRenderWindow.h"
-#include "QmitkStepperAdapter.h"
+#include <QmitkRenderWindow.h>
+#include <QmitkStepperAdapter.h>
#include "mitkNodePredicateNot.h"
#include "mitkNodePredicateProperty.h"
#include "mitkProperties.h"
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
const std::string QmitkSimpleExampleView::VIEW_ID = "org.mitk.views.simpleexample";
QmitkSimpleExampleView::QmitkSimpleExampleView()
: m_Controls(nullptr), m_NavigatorsInitialized(false), m_Parent(nullptr)
{
}
QmitkSimpleExampleView::~QmitkSimpleExampleView()
{
}
void QmitkSimpleExampleView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
m_Parent = parent;
// create GUI widgets
m_Controls = new Ui::QmitkSimpleExampleViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
this->RenderWindowPartActivated(this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN));
}
}
void QmitkSimpleExampleView::SetFocus()
{
m_Controls->renderWindowComboBox->setFocus();
}
void QmitkSimpleExampleView::RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart)
{
if (renderWindowPart == nullptr)
{
m_Parent->setEnabled(false);
return;
}
QHashIterator<QString, QmitkRenderWindow *> renderIter(renderWindowPart->GetQmitkRenderWindows());
while (renderIter.hasNext())
{
renderIter.next();
m_Controls->renderWindowComboBox->addItem(renderIter.key());
}
RenderWindowSelected(m_Controls->renderWindowComboBox->currentText());
- m_TimeStepper.reset(new QmitkStepperAdapter(m_Controls->timeSliceNavigationWidget,
- renderWindowPart->GetTimeNavigationController()->GetTime()));
- m_MovieStepper.reset(new QmitkStepperAdapter(m_Controls->movieNavigatorTime,
- renderWindowPart->GetTimeNavigationController()->GetTime()));
+ auto* timeController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ m_TimeStepper.reset(new QmitkStepperAdapter(m_Controls->timeSliceNavigationWidget, timeController->GetStepper()));
+ m_MovieStepper.reset(new QmitkStepperAdapter(m_Controls->movieNavigatorTime, timeController->GetStepper()));
m_Parent->setEnabled(true);
}
void QmitkSimpleExampleView::RenderWindowPartDeactivated(mitk::IRenderWindowPart * /*renderWindowPart*/)
{
m_Parent->setEnabled(false);
m_SliceStepper.reset();
m_TimeStepper.reset();
m_MovieStepper.reset();
m_Controls->renderWindowComboBox->clear();
}
void QmitkSimpleExampleView::CreateConnections()
{
if (m_Controls)
{
connect(m_Controls->renderWindowComboBox,
SIGNAL(currentIndexChanged(QString)),
this,
SLOT(RenderWindowSelected(QString)));
connect(m_Controls->stereoSelect, SIGNAL(activated(int)), this, SLOT(StereoSelectionChanged(int)));
connect(m_Controls->reInitializeNavigatorsButton, SIGNAL(clicked()), this, SLOT(InitNavigators()));
connect(m_Controls->m_TakeScreenshotBtn, SIGNAL(clicked()), this, SLOT(OnTakeScreenshot()));
connect(m_Controls->m_TakeHighResScreenShotBtn, SIGNAL(clicked()), this, SLOT(OnTakeHighResolutionScreenshot()));
}
}
void QmitkSimpleExampleView::InitNavigators()
{
/* get all nodes that have not set "includeInBoundingBox" to false */
mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(
mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false)));
mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred);
/* calculate bounding geometry of these nodes */
auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs);
/* initialize the views to the bounding geometry */
m_NavigatorsInitialized = mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
}
void QmitkSimpleExampleView::StereoSelectionChanged(int id)
{
/* From vtkRenderWindow.h tells us about stereo rendering:
Set/Get what type of stereo rendering to use. CrystalEyes mode uses frame-sequential capabilities available in OpenGL
to drive LCD shutter glasses and stereo projectors. RedBlue mode is a simple type of stereo for use with red-blue
glasses. Anaglyph mode is a superset of RedBlue mode, but the color output channels can be configured using the
AnaglyphColorMask and the color of the original image can be (somewhat maintained using AnaglyphColorSaturation; the
default colors for Anaglyph mode is red-cyan. Interlaced stereo mode produces a composite image where horizontal
lines alternate between left and right views. StereoLeft and StereoRight modes choose one or the other stereo view.
Dresden mode is yet another stereoscopic interleaving.
*/
auto *renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN);
vtkRenderWindow *vtkrenderwindow = renderWindowPart->GetQmitkRenderWindow("3d")->GetVtkRenderWindow();
// note: foreground vtkRenderers (at least the department logo renderer) produce errors in stereoscopic visualization.
// Therefore, we disable the logo visualization during stereo rendering.
switch (id)
{
case 0:
vtkrenderwindow->StereoRenderOff();
break;
case 1:
vtkrenderwindow->SetStereoTypeToRedBlue();
vtkrenderwindow->StereoRenderOn();
renderWindowPart->EnableDecorations(false, QStringList(mitk::IRenderWindowPart::DECORATION_LOGO));
break;
case 2:
vtkrenderwindow->SetStereoTypeToDresden();
vtkrenderwindow->StereoRenderOn();
renderWindowPart->EnableDecorations(false, QStringList(mitk::IRenderWindowPart::DECORATION_LOGO));
break;
}
mitk::BaseRenderer::GetInstance(vtkrenderwindow)->SetMapperID(mitk::BaseRenderer::Standard3D);
renderWindowPart->RequestUpdate();
}
QmitkRenderWindow *QmitkSimpleExampleView::GetSelectedRenderWindow() const
{
QString id = m_Controls->renderWindowComboBox->currentText();
if (id.isEmpty())
{
return nullptr;
}
else
{
return this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow(id);
}
}
void QmitkSimpleExampleView::OnTakeHighResolutionScreenshot()
{
QString filter;
QString fileName = QFileDialog::getSaveFileName(
nullptr, "Save screenshot to...", QDir::currentPath(), m_PNGExtension + ";;" + m_JPGExtension, &filter);
vtkRenderer *renderer = this->GetSelectedRenderWindow()->GetRenderer()->GetVtkRenderer();
if (renderer == nullptr)
return;
this->TakeScreenshot(renderer, 4, fileName, filter);
}
void QmitkSimpleExampleView::OnTakeScreenshot()
{
QString filter;
QString fileName = QFileDialog::getSaveFileName(
nullptr, "Save screenshot to...", QDir::currentPath(), m_PNGExtension + ";;" + m_JPGExtension, &filter);
QmitkRenderWindow *renWin = this->GetSelectedRenderWindow();
if (renWin == nullptr)
return;
vtkRenderer *renderer = renWin->GetRenderer()->GetVtkRenderer();
if (renderer == nullptr)
return;
this->TakeScreenshot(renderer, 1, fileName, filter);
}
void QmitkSimpleExampleView::TakeScreenshot(vtkRenderer *renderer,
unsigned int magnificationFactor,
QString fileName,
QString filter)
{
if ((renderer == nullptr) || (magnificationFactor < 1) || fileName.isEmpty())
return;
bool doubleBuffering(renderer->GetRenderWindow()->GetDoubleBuffer());
renderer->GetRenderWindow()->DoubleBufferOff();
vtkImageWriter *fileWriter = nullptr;
QFileInfo fi(fileName);
QString suffix = fi.suffix().toLower();
if (suffix.isEmpty() || (suffix != "png" && suffix != "jpg" && suffix != "jpeg"))
{
if (filter == m_PNGExtension)
{
suffix = "png";
}
else if (filter == m_JPGExtension)
{
suffix = "jpg";
}
fileName += "." + suffix;
}
if (suffix.compare("jpg", Qt::CaseInsensitive) == 0 || suffix.compare("jpeg", Qt::CaseInsensitive) == 0)
{
vtkJPEGWriter *w = vtkJPEGWriter::New();
w->SetQuality(100);
w->ProgressiveOff();
fileWriter = w;
}
else // default is png
{
fileWriter = vtkPNGWriter::New();
}
vtkRenderLargeImage *magnifier = vtkRenderLargeImage::New();
magnifier->SetInput(renderer);
magnifier->SetMagnification(magnificationFactor);
fileWriter->SetInputConnection(magnifier->GetOutputPort());
fileWriter->SetFileName(fileName.toLatin1());
// vtkRenderLargeImage has problems with different layers, therefore we have to
// temporarily deactivate all other layers.
// we set the background to white, because it is nicer than black...
double oldBackground[3];
renderer->GetBackground(oldBackground);
double white[] = {1.0, 1.0, 1.0};
renderer->SetBackground(white);
mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN);
renderWindowPart->EnableDecorations(false);
fileWriter->Write();
fileWriter->Delete();
renderWindowPart->EnableDecorations(true);
renderer->SetBackground(oldBackground);
renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering);
}
void QmitkSimpleExampleView::RenderWindowSelected(const QString &id)
{
if (!id.isEmpty())
{
m_SliceStepper.reset(new QmitkStepperAdapter(m_Controls->sliceNavigationWidget,
- this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow(id)->GetSliceNavigationController()->GetSlice()));
+ this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow(id)->GetSliceNavigationController()->GetStepper()));
}
}
diff --git a/Examples/QtFreeRender/QtFreeRender.cpp b/Examples/QtFreeRender/QtFreeRender.cpp
index 9c679bbb8b..fbd2d94e1a 100644
--- a/Examples/QtFreeRender/QtFreeRender.cpp
+++ b/Examples/QtFreeRender/QtFreeRender.cpp
@@ -1,319 +1,302 @@
/*============================================================================
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 "mitkRenderWindow.h"
#include <mitkCameraController.h>
#include <mitkDisplayActionEventBroadcast.h>
#include <mitkInteractionConst.h>
#include <mitkLine.h>
#include <mitkPlaneGeometryDataMapper2D.h>
#include <mitkProperties.h>
#include <mitkVtkLayerController.h>
#include <mitkProperties.h>
#include <mitkRenderingManager.h>
#include <mitkStandaloneDataStorage.h>
#include <mitkTransferFunction.h>
#include <mitkTransferFunctionProperty.h>
#include <mitkDataStorage.h>
#include <mitkIOUtil.h>
#include <vtkAnnotatedCubeActor.h>
#include <vtkCornerAnnotation.h>
#include <vtkMitkRectangleProp.h>
#include <vtkOrientationMarkerWidget.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTextProperty.h>
//##Documentation
//## @brief Example of a NON QT DEPENDENT MITK RENDERING APPLICATION.
mitk::RenderWindow::Pointer mitkWidget1;
mitk::RenderWindow::Pointer mitkWidget2;
mitk::RenderWindow::Pointer mitkWidget3;
mitk::RenderWindow::Pointer mitkWidget4;
mitk::DisplayActionEventBroadcast::Pointer m_DisplayActionEventBroadcast;
vtkSmartPointer<vtkMitkRectangleProp> m_RectangleRendering1;
vtkSmartPointer<vtkMitkRectangleProp> m_RectangleRendering2;
vtkSmartPointer<vtkMitkRectangleProp> m_RectangleRendering3;
vtkSmartPointer<vtkMitkRectangleProp> m_RectangleRendering4;
-mitk::SliceNavigationController *m_TimeNavigationController = nullptr;
-
mitk::DataStorage::Pointer m_DataStorage;
mitk::DataNode::Pointer m_PlaneNode1;
mitk::DataNode::Pointer m_PlaneNode2;
mitk::DataNode::Pointer m_PlaneNode3;
mitk::DataNode::Pointer m_Node;
void InitializeWindows()
{
// Set default view directions for SNCs
mitkWidget1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Axial);
mitkWidget2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Sagittal);
mitkWidget3->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Coronal);
mitkWidget4->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Original);
- // initialize m_TimeNavigationController: send time via sliceNavigationControllers
- m_TimeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
- m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget1->GetSliceNavigationController());
- m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget2->GetSliceNavigationController());
- m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget3->GetSliceNavigationController());
- m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget4->GetSliceNavigationController());
- mitkWidget1->GetSliceNavigationController()->ConnectGeometrySendEvent(
- mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow()));
-
- // reverse connection between sliceNavigationControllers and m_TimeNavigationController
- mitkWidget1->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
- mitkWidget2->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
- mitkWidget3->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
- mitkWidget4->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
-
mitkWidget4->GetRenderer()->GetVtkRenderer()->SetBackground(0.1, 0.1, 0.1);
mitkWidget4->GetRenderer()->GetVtkRenderer()->SetBackground(0.5, 0.5, 0.5);
mitkWidget4->GetRenderer()->GetVtkRenderer()->GradientBackgroundOn();
m_RectangleRendering1 = vtkSmartPointer<vtkMitkRectangleProp>::New();
m_RectangleRendering1->SetColor(1.0, 0.0, 0.0);
mitkWidget1->GetRenderer()->GetVtkRenderer()->AddViewProp(m_RectangleRendering1);
m_RectangleRendering2 = vtkSmartPointer<vtkMitkRectangleProp>::New();
m_RectangleRendering2->SetColor(0.0, 1.0, 0.0);
mitkWidget2->GetRenderer()->GetVtkRenderer()->AddViewProp(m_RectangleRendering2);
m_RectangleRendering3 = vtkSmartPointer<vtkMitkRectangleProp>::New();
m_RectangleRendering3->SetColor(0.0, 0.0, 1.0);
mitkWidget3->GetRenderer()->GetVtkRenderer()->AddViewProp(m_RectangleRendering3);
m_RectangleRendering4 = vtkSmartPointer<vtkMitkRectangleProp>::New();
m_RectangleRendering4->SetColor(1.0, 1.0, 0.0);
mitkWidget4->GetRenderer()->GetVtkRenderer()->AddViewProp(m_RectangleRendering4);
}
void AddDisplayPlaneSubTree()
{
// add the displayed planes of the multiwidget to a node to which the subtree
// @a planesSubTree points ...
float white[3] = {1.0f, 1.0f, 1.0f};
mitk::PlaneGeometryDataMapper2D::Pointer mapper;
mitk::IntProperty::Pointer layer = mitk::IntProperty::New(1000);
// ... of widget 1
m_PlaneNode1 =
(mitk::BaseRenderer::GetInstance(mitkWidget1->GetVtkRenderWindow()))->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode1->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow()));
m_PlaneNode1->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode1->SetProperty("name", mitk::StringProperty::New("widget1Plane"));
m_PlaneNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode1->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PlaneNode1->SetProperty("layer", layer);
m_PlaneNode1->SetColor(1.0, 0.0, 0.0);
mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
// ... of widget 2
m_PlaneNode2 =
(mitk::BaseRenderer::GetInstance(mitkWidget2->GetVtkRenderWindow()))->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode2->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow()));
m_PlaneNode2->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode2->SetProperty("name", mitk::StringProperty::New("widget2Plane"));
m_PlaneNode2->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode2->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PlaneNode2->SetProperty("layer", layer);
m_PlaneNode2->SetColor(0.0, 1.0, 0.0);
mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode2->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
// ... of widget 3
m_PlaneNode3 =
(mitk::BaseRenderer::GetInstance(mitkWidget3->GetVtkRenderWindow()))->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode3->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow()));
m_PlaneNode3->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode3->SetProperty("name", mitk::StringProperty::New("widget3Plane"));
m_PlaneNode3->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode3->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PlaneNode3->SetProperty("layer", layer);
m_PlaneNode3->SetColor(0.0, 0.0, 1.0);
mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode3->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
// AddPlanesToDataStorage
if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_Node.IsNotNull())
{
if (m_DataStorage.IsNotNull())
{
m_DataStorage->Add(m_PlaneNode1);
m_DataStorage->Add(m_PlaneNode2);
m_DataStorage->Add(m_PlaneNode3);
}
}
}
void Fit()
{
vtkRenderer *vtkrenderer;
mitk::BaseRenderer::GetInstance(mitkWidget1->GetVtkRenderWindow())->GetCameraController()->Fit();
mitk::BaseRenderer::GetInstance(mitkWidget2->GetVtkRenderWindow())->GetCameraController()->Fit();
mitk::BaseRenderer::GetInstance(mitkWidget3->GetVtkRenderWindow())->GetCameraController()->Fit();
mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())->GetCameraController()->Fit();
int w = vtkObject::GetGlobalWarningDisplay();
vtkObject::GlobalWarningDisplayOff();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget1->GetVtkRenderWindow())->GetVtkRenderer();
if (vtkrenderer != nullptr)
vtkrenderer->ResetCamera();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget2->GetVtkRenderWindow())->GetVtkRenderer();
if (vtkrenderer != nullptr)
vtkrenderer->ResetCamera();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget3->GetVtkRenderWindow())->GetVtkRenderer();
if (vtkrenderer != nullptr)
vtkrenderer->ResetCamera();
vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())->GetVtkRenderer();
if (vtkrenderer != nullptr)
vtkrenderer->ResetCamera();
vtkObject::SetGlobalWarningDisplay(w);
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Usage: %s [filename1] [filename2] ...\n\n", "");
return 1;
}
// Create a DataStorage
m_DataStorage = mitk::StandaloneDataStorage::New();
//*************************************************************************
// Part II: Create some data by reading files
//*************************************************************************
int i;
for (i = 1; i < argc; ++i)
{
// For testing
if (strcmp(argv[i], "-testing") == 0)
continue;
std::string filename = argv[i];
try
{
// Read the file and add it as a data node to the data storage
mitk::DataStorage::SetOfObjects::Pointer nodes = mitk::IOUtil::Load(filename, *m_DataStorage);
for (mitk::DataStorage::SetOfObjects::Iterator nodeIter = nodes->Begin(), nodeIterEnd = nodes->End();
nodeIter != nodeIterEnd;
++nodeIter)
{
mitk::DataNode::Pointer node = nodeIter->Value();
mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(node->GetData());
if (image.IsNotNull())
{
// Set the property "volumerendering" to the Boolean value "true"
node->SetProperty("volumerendering", mitk::BoolProperty::New(false));
node->SetProperty("name", mitk::StringProperty::New("testimage"));
node->SetProperty("layer", mitk::IntProperty::New(1));
}
}
}
catch (...)
{
std::cerr << "Could not open file " << filename << std::endl;
exit(2);
}
}
//*************************************************************************
// Part V: Create window and pass the tree to it
//*************************************************************************
// Create renderwindows
mitkWidget1 = mitk::RenderWindow::New();
mitkWidget2 = mitk::RenderWindow::New();
mitkWidget3 = mitk::RenderWindow::New();
mitkWidget4 = mitk::RenderWindow::New();
mitkWidget1->GetRenderer()->PrepareRender();
mitkWidget2->GetRenderer()->PrepareRender();
mitkWidget3->GetRenderer()->PrepareRender();
// Tell the renderwindow which (part of) the datastorage to render
mitkWidget1->GetRenderer()->SetDataStorage(m_DataStorage);
mitkWidget2->GetRenderer()->SetDataStorage(m_DataStorage);
mitkWidget3->GetRenderer()->SetDataStorage(m_DataStorage);
mitkWidget4->GetRenderer()->SetDataStorage(m_DataStorage);
// instantiate display interactor
if (m_DisplayActionEventBroadcast.IsNull())
{
m_DisplayActionEventBroadcast = mitk::DisplayActionEventBroadcast::New();
m_DisplayActionEventBroadcast->LoadStateMachine("DisplayInteraction.xml");
m_DisplayActionEventBroadcast->SetEventConfig("DisplayConfigMITK.xml");
}
// Use it as a 2D View
mitkWidget1->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D);
mitkWidget2->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D);
mitkWidget3->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D);
mitkWidget4->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D);
mitkWidget1->SetSize(400, 400);
mitkWidget2->GetVtkRenderWindow()->SetPosition(mitkWidget1->GetVtkRenderWindow()->GetPosition()[0] + 420,
mitkWidget1->GetVtkRenderWindow()->GetPosition()[1]);
mitkWidget2->SetSize(400, 400);
mitkWidget3->GetVtkRenderWindow()->SetPosition(mitkWidget1->GetVtkRenderWindow()->GetPosition()[0],
mitkWidget1->GetVtkRenderWindow()->GetPosition()[1] + 450);
mitkWidget3->SetSize(400, 400);
mitkWidget4->GetVtkRenderWindow()->SetPosition(mitkWidget1->GetVtkRenderWindow()->GetPosition()[0] + 420,
mitkWidget1->GetVtkRenderWindow()->GetPosition()[1] + 450);
mitkWidget4->SetSize(400, 400);
InitializeWindows();
AddDisplayPlaneSubTree();
Fit();
// Initialize the RenderWindows
auto geo = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(geo);
m_DataStorage->Print(std::cout);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// reinit the mitkVTKEventProvider;
// this is only necessary once after calling
// ForceImmediateUpdateAll() for the first time
mitkWidget1->ReinitEventProvider();
mitkWidget2->ReinitEventProvider();
mitkWidget3->ReinitEventProvider();
mitkWidget1->GetVtkRenderWindow()->Render();
mitkWidget2->GetVtkRenderWindow()->Render();
mitkWidget3->GetVtkRenderWindow()->Render();
mitkWidget4->GetVtkRenderWindow()->Render();
mitkWidget4->GetVtkRenderWindowInteractor()->Start();
return 0;
}
diff --git a/Examples/Tutorial/Step1/Step1.cpp b/Examples/Tutorial/Step1/Step1.cpp
index c203119b7f..3ac735e7a8 100644
--- a/Examples/Tutorial/Step1/Step1.cpp
+++ b/Examples/Tutorial/Step1/Step1.cpp
@@ -1,85 +1,85 @@
/*============================================================================
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 "QmitkRegisterClasses.h"
#include "QmitkRenderWindow.h"
#include <mitkStandaloneDataStorage.h>
#include <QApplication>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
//##Documentation
//## @brief Load image (nrrd format) and display it in a 2D view
int main(int argc, char *argv[])
{
QApplication qtapplication(argc, argv);
if (argc < 2)
{
fprintf(stderr, "Usage: %s [filename] \n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str());
return 1;
}
// Register Qmitk-dependent global instances
QmitkRegisterClasses();
//*************************************************************************
// Part I: Basic initialization
//*************************************************************************
// Create a DataStorage
// The DataStorage manages all data objects. It is used by the
// rendering mechanism to render all data objects
// We use the standard implementation mitk::StandaloneDataStorage.
mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New();
//*************************************************************************
// Part II: Create some data by reading a file
//*************************************************************************
// Load datanode (eg. many image formats, surface formats, etc.)
mitk::IOUtil::Load(argv[1], *ds);
//*************************************************************************
// Part IV: Create window and pass the datastorage to it
//*************************************************************************
// Create a RenderWindow
QmitkRenderWindow renderWindow;
// Tell the RenderWindow which (part of) the datastorage to render
renderWindow.GetRenderer()->SetDataStorage(ds);
// Initialize the RenderWindow
auto geo = ds->ComputeBoundingGeometry3D(ds->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(geo);
// mitk::RenderingManager::GetInstance()->InitializeViews();
// Select a slice
mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController();
if (sliceNaviController)
- sliceNaviController->GetSlice()->SetPos(0);
+ sliceNaviController->GetStepper()->SetPos(0);
//*************************************************************************
// Part V: Qt-specific initialization
//*************************************************************************
renderWindow.show();
renderWindow.resize(256, 256);
return qtapplication.exec();
}
/**
\example Step1.cpp
*/
diff --git a/Examples/Tutorial/Step2/Step2.cpp b/Examples/Tutorial/Step2/Step2.cpp
index 690cecd5b4..b836cf9447 100644
--- a/Examples/Tutorial/Step2/Step2.cpp
+++ b/Examples/Tutorial/Step2/Step2.cpp
@@ -1,93 +1,93 @@
/*============================================================================
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 "QmitkRegisterClasses.h"
#include "QmitkRenderWindow.h"
#include <mitkStandaloneDataStorage.h>
#include <QApplication>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
//##Documentation
//## @brief Load one or more data sets (many image, surface
//## and other formats) and display it in a 2D view
int main(int argc, char *argv[])
{
QApplication qtapplication(argc, argv);
if (argc < 2)
{
fprintf(
stderr, "Usage: %s [filename1] [filename2] ...\n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str());
return 1;
}
// Register Qmitk-dependent global instances
QmitkRegisterClasses();
//*************************************************************************
// Part I: Basic initialization
//*************************************************************************
// Create a data storage object. We will use it as a singleton
mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New();
//*************************************************************************
// Part II: Create some data by reading files
//*************************************************************************
int i;
for (i = 1; i < argc; ++i)
{
// For testing
if (strcmp(argv[i], "-testing") == 0)
continue;
//*********************************************************************
// Part III: Put the data into the datastorage
//*********************************************************************
// Add the node to the DataStorage
mitk::IOUtil::Load(argv[i], *storage);
}
//*************************************************************************
// Part IV: Create window and pass the datastorage to it
//*************************************************************************
// Create a RenderWindow
QmitkRenderWindow renderWindow;
// Tell the RenderWindow which (part of) the datastorage to render
renderWindow.GetRenderer()->SetDataStorage(storage);
// Initialize the RenderWindow
auto geo = storage->ComputeBoundingGeometry3D(storage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(geo);
// Select a slice
mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController();
if (sliceNaviController)
- sliceNaviController->GetSlice()->SetPos(2);
+ sliceNaviController->GetStepper()->SetPos(2);
//*************************************************************************
// Part V: Qt-specific initialization
//*************************************************************************
renderWindow.show();
renderWindow.resize(256, 256);
return qtapplication.exec();
}
/**
\example Step2.cpp
*/
diff --git a/Modules/Annotation/src/mitkLogoAnnotation.cpp b/Modules/Annotation/src/mitkLogoAnnotation.cpp
index aa8b5f0437..f73b8f357f 100644
--- a/Modules/Annotation/src/mitkLogoAnnotation.cpp
+++ b/Modules/Annotation/src/mitkLogoAnnotation.cpp
@@ -1,177 +1,176 @@
/*============================================================================
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 "mitkLogoAnnotation.h"
#include <mitkIOUtil.h>
-#include "vtkUnicodeString.h"
#include <vtkImageData.h>
#include <vtkImageData.h>
#include <vtkImageMapper.h>
#include <vtkImageMapper.h>
#include <vtkImageReader2.h>
#include <vtkImageReader2Factory.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkTextRenderer.h>
#include <vtkTextRendererStringToImage.h>
#include <mitkVtkLogoRepresentation.h>
#include <vtkImageImport.h>
#include <vtkProperty2D.h>
#include <vtkImageFlip.h>
#include <vtkNew.h>
mitk::LogoAnnotation::LogoAnnotation()
{
m_readerFactory = vtkSmartPointer<vtkImageReader2Factory>::New();
mitk::Point2D offset;
offset.Fill(0.03);
SetOffsetVector(offset);
SetRelativeSize(0.2);
SetLogoImagePath("mbiLogo");
SetCornerPosition(3);
m_VtkImageImport = vtkSmartPointer<vtkImageImport>::New();
m_UpdatedLogoImage = vtkSmartPointer<vtkImageData>::New();
}
mitk::LogoAnnotation::~LogoAnnotation()
{
for (BaseRenderer *renderer : m_LSH.GetRegisteredBaseRenderer())
{
if (renderer)
{
this->RemoveFromBaseRenderer(renderer);
}
}
}
mitk::LogoAnnotation::LocalStorage::~LocalStorage()
{
}
mitk::LogoAnnotation::LocalStorage::LocalStorage()
{
m_LogoRep = vtkSmartPointer<mitkVtkLogoRepresentation>::New();
}
void mitk::LogoAnnotation::UpdateVtkAnnotation(mitk::BaseRenderer *renderer)
{
LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
if (ls->IsGenerateDataRequired(renderer, this))
{
ls->m_LogoImage = m_UpdatedLogoImage;
ls->m_LogoRep->SetImage(ls->m_LogoImage);
ls->m_LogoRep->SetDragable(false);
ls->m_LogoRep->SetMoving(false);
ls->m_LogoRep->SetPickable(false);
ls->m_LogoRep->SetShowBorder(true);
ls->m_LogoRep->SetRenderer(renderer->GetVtkRenderer());
float size = GetRelativeSize();
ls->m_LogoRep->SetPosition2(size, size);
int corner = GetCornerPosition();
ls->m_LogoRep->SetCornerPosition(corner);
mitk::Point2D offset = GetOffsetVector();
ls->m_LogoRep->SetPosition(offset[0], offset[1]);
float opacity = 1.0;
GetOpacity(opacity);
ls->m_LogoRep->GetImageProperty()->SetOpacity(opacity);
ls->m_LogoRep->BuildRepresentation();
ls->UpdateGenerateDataTime();
}
}
void mitk::LogoAnnotation::SetLogoImagePath(std::string path)
{
SetStringProperty("Annotation.LogoImagePath", path.c_str());
Modified();
}
void mitk::LogoAnnotation::LoadLogoImageFromPath()
{
auto imageNodeVector = mitk::IOUtil::Load(this->GetLogoImagePath());
if (imageNodeVector.size() == 1)
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(imageNodeVector.front().GetPointer());
if (image.IsNotNull())
{
vtkNew<vtkImageFlip> flip;
flip->SetInputData(image->GetVtkImageData());
flip->SetFilteredAxis(1);
flip->Update();
m_UpdatedLogoImage->DeepCopy(flip->GetOutput());
Modified();
}
}
}
void mitk::LogoAnnotation::SetLogoImage(vtkSmartPointer<vtkImageData> logo)
{
m_UpdatedLogoImage = logo;
Modified();
}
std::string mitk::LogoAnnotation::GetLogoImagePath() const
{
std::string path;
GetPropertyList()->GetStringProperty("Annotation.LogoImagePath", path);
return path;
}
void mitk::LogoAnnotation::SetOffsetVector(const Point2D &OffsetVector)
{
mitk::Point2dProperty::Pointer OffsetVectorProperty = mitk::Point2dProperty::New(OffsetVector);
SetProperty("Annotation.OffsetVector", OffsetVectorProperty.GetPointer());
Modified();
}
mitk::Point2D mitk::LogoAnnotation::GetOffsetVector() const
{
mitk::Point2D OffsetVector;
OffsetVector.Fill(0);
GetPropertyValue<mitk::Point2D>("Annotation.OffsetVector", OffsetVector);
return OffsetVector;
}
void mitk::LogoAnnotation::SetCornerPosition(const int &corner)
{
SetIntProperty("Annotation.CornerPosition", corner);
Modified();
}
int mitk::LogoAnnotation::GetCornerPosition() const
{
int corner = 0;
GetIntProperty("Annotation.CornerPosition", corner);
return corner;
}
void mitk::LogoAnnotation::SetRelativeSize(const float &size)
{
SetFloatProperty("Annotation.RelativeSize", size);
Modified();
}
float mitk::LogoAnnotation::GetRelativeSize() const
{
float size = 0;
GetFloatProperty("Annotation.RelativeSize", size);
return size;
}
vtkProp *mitk::LogoAnnotation::GetVtkProp(BaseRenderer *renderer) const
{
LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
return ls->m_LogoRep;
}
diff --git a/Modules/Annotation/src/mitkTextAnnotation2D.cpp b/Modules/Annotation/src/mitkTextAnnotation2D.cpp
index 24fab05733..041bec4497 100644
--- a/Modules/Annotation/src/mitkTextAnnotation2D.cpp
+++ b/Modules/Annotation/src/mitkTextAnnotation2D.cpp
@@ -1,155 +1,154 @@
/*============================================================================
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 "mitkTextAnnotation2D.h"
-#include "vtkUnicodeString.h"
#include <vtkPropAssembly.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
mitk::TextAnnotation2D::TextAnnotation2D()
{
mitk::Point2D position;
position[0] = position[1] = 0;
this->SetPosition2D(position);
this->SetOffsetVector(position);
this->SetText("");
this->SetFontSize(20);
this->SetColor(1.0, 1.0, 1.0);
this->SetStringProperty("font.family", "Arial");
this->SetBoolProperty("font.bold", false);
this->SetBoolProperty("font.italic", false);
this->SetBoolProperty("drawShadow", false);
}
mitk::TextAnnotation2D::~TextAnnotation2D()
{
for (BaseRenderer *renderer : m_LSH.GetRegisteredBaseRenderer())
{
if (renderer)
{
this->RemoveFromBaseRenderer(renderer);
}
}
}
mitk::Annotation::Bounds mitk::TextAnnotation2D::GetBoundsOnDisplay(mitk::BaseRenderer *renderer) const
{
LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
mitk::Annotation::Bounds bounds;
bounds.Position = ls->m_TextActor->GetPosition();
double size[2];
ls->m_TextActor->GetSize(renderer->GetVtkRenderer(), size);
bounds.Size[0] = size[0];
bounds.Size[1] = size[1];
return bounds;
}
void mitk::TextAnnotation2D::SetBoundsOnDisplay(mitk::BaseRenderer *renderer, const mitk::Annotation::Bounds &bounds)
{
LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
mitk::Point2D posT, posS;
posT[0] = bounds.Position[0];
posT[1] = bounds.Position[1];
posS[0] = posT[0] + 1;
posS[1] = posT[1] - 1;
ls->m_TextActor->SetDisplayPosition(posT[0], posT[1]);
ls->m_STextActor->SetDisplayPosition(posS[0], posS[1]);
}
mitk::TextAnnotation2D::LocalStorage::~LocalStorage()
{
}
mitk::TextAnnotation2D::LocalStorage::LocalStorage()
{
m_TextActor = vtkSmartPointer<vtkTextActor>::New();
m_TextProp = vtkSmartPointer<vtkTextProperty>::New();
m_STextActor = vtkSmartPointer<vtkTextActor>::New();
m_STextProp = vtkSmartPointer<vtkTextProperty>::New();
m_TextActor->SetTextProperty(m_TextProp);
m_STextActor->SetTextProperty(m_STextProp);
m_Assembly = vtkSmartPointer<vtkPropAssembly>::New();
m_Assembly->AddPart(m_STextActor);
m_Assembly->AddPart(m_TextActor);
}
void mitk::TextAnnotation2D::UpdateVtkAnnotation2D(mitk::BaseRenderer *renderer)
{
LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
if (ls->IsGenerateDataRequired(renderer, this))
{
float color[3] = {0.0, 1.0, 0.0};
float opacity = 1.0;
GetColor(color);
GetOpacity(opacity);
ls->m_TextProp->SetColor(color[0], color[1], color[2]);
ls->m_STextProp->SetColor(0, 0, 0);
ls->m_TextProp->SetFontSize(GetFontSize());
ls->m_TextProp->SetOpacity(opacity);
ls->m_STextProp->SetFontSize(GetFontSize());
ls->m_STextProp->SetOpacity(opacity);
std::string fontFamilyAsString;
if (GetStringProperty("font.family", fontFamilyAsString) == false)
{
fontFamilyAsString = "Arial";
}
ls->m_TextProp->SetFontFamilyAsString(fontFamilyAsString.c_str());
ls->m_STextProp->SetFontFamilyAsString(fontFamilyAsString.c_str());
bool boldFont(false);
GetBoolProperty("font.bold", boldFont);
ls->m_TextProp->SetBold(boldFont);
ls->m_STextProp->SetBold(boldFont);
bool italicFont(false);
GetBoolProperty("font.italic", italicFont);
ls->m_TextProp->SetBold(italicFont);
ls->m_STextProp->SetBold(italicFont);
bool drawShadow;
GetBoolProperty("drawShadow", drawShadow);
ls->m_TextProp->SetShadow(false);
ls->m_STextProp->SetShadow(false);
ls->m_STextActor->SetVisibility(drawShadow);
ls->m_TextActor->SetInput(GetText().c_str());
ls->m_STextActor->SetInput(GetText().c_str());
mitk::Point2D posT, posS;
posT[0] = GetPosition2D()[0] + GetOffsetVector()[0];
posT[1] = GetPosition2D()[1] + GetOffsetVector()[1];
posS[0] = posT[0] + 1;
posS[1] = posT[1] - 1;
ls->m_TextActor->SetDisplayPosition(posT[0], posT[1]);
ls->m_STextActor->SetDisplayPosition(posS[0], posS[1]);
ls->UpdateGenerateDataTime();
}
}
vtkProp *mitk::TextAnnotation2D::GetVtkProp(mitk::BaseRenderer *renderer) const
{
LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
return ls->m_Assembly;
}
vtkActor2D *mitk::TextAnnotation2D::GetVtkActor2D(BaseRenderer *renderer) const
{
LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
return ls->m_TextActor;
}
diff --git a/Modules/AppUtil/src/QmitkSafeApplication.cpp b/Modules/AppUtil/src/QmitkSafeApplication.cpp
index c84ff97eb1..3a6dcbfb7b 100644
--- a/Modules/AppUtil/src/QmitkSafeApplication.cpp
+++ b/Modules/AppUtil/src/QmitkSafeApplication.cpp
@@ -1,41 +1,41 @@
/*============================================================================
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 "QmitkSafeApplication.h"
#include "QmitkSafeNotify.h"
#include <mitkException.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
QmitkSafeApplication::QmitkSafeApplication(int &argc, char **argv, bool safeMode)
: QApplication(argc, argv),
m_SafeMode(safeMode)
{
}
bool QmitkSafeApplication::notify(QObject *receiver, QEvent *event)
{
return m_SafeMode
? QmitkSafeNotify<QApplication>(this, receiver, event)
: QApplication::notify(receiver, event);
}
void QmitkSafeApplication::setSafeMode(bool safeMode)
{
m_SafeMode = safeMode;
}
bool QmitkSafeApplication::getSafeMode() const
{
return m_SafeMode;
}
diff --git a/Modules/AppUtil/src/QmitkSafeNotify.h b/Modules/AppUtil/src/QmitkSafeNotify.h
index 245b10ea6b..3b742172ad 100644
--- a/Modules/AppUtil/src/QmitkSafeNotify.h
+++ b/Modules/AppUtil/src/QmitkSafeNotify.h
@@ -1,69 +1,69 @@
/*============================================================================
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 QmitkSafeNotify_h
#define QmitkSafeNotify_h
#include <mitkException.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <QMessageBox>
template <class A>
bool QmitkSafeNotify(A *app, QObject *receiver, QEvent *event)
{
QString msg;
try
{
return app->A::notify(receiver, event);
}
catch (mitk::Exception &e)
{
msg = QString("MITK Exception:\n\n") + QString("Description: ") + QString(e.GetDescription()) + QString("\n\n") +
QString("Filename: ") + QString(e.GetFile()) + QString("\n\n") + QString("Line: ") +
QString::number(e.GetLine());
}
catch (std::exception &e)
{
msg = e.what();
}
catch (...)
{
msg = "Unknown exception";
}
MITK_ERROR << "An error occurred: " << msg.toStdString();
QMessageBox msgBox;
msgBox.setText("An error occurred. You should save all data and quit the program to prevent possible data loss.");
msgBox.setDetailedText(msg);
msgBox.setIcon(QMessageBox::Critical);
msgBox.addButton(app->trUtf8("Exit immediately"), QMessageBox::YesRole);
msgBox.addButton(app->trUtf8("Ignore"), QMessageBox::NoRole);
int ret = msgBox.exec();
switch (ret)
{
case 0:
MITK_ERROR << "The program was closed.";
app->closeAllWindows();
break;
case 1:
MITK_ERROR
<< "The error was ignored by the user. The program may be in a corrupt state and don't behave like expected!";
break;
}
return false;
}
#endif
diff --git a/Modules/AppUtil/src/mitkBaseApplication.cpp b/Modules/AppUtil/src/mitkBaseApplication.cpp
index b3c458b695..68948a6607 100644
--- a/Modules/AppUtil/src/mitkBaseApplication.cpp
+++ b/Modules/AppUtil/src/mitkBaseApplication.cpp
@@ -1,898 +1,902 @@
/*============================================================================
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 <mitkBaseApplication.h>
#include <mitkCoreServices.h>
#include <mitkIPreferencesService.h>
#include <mitkExceptionMacro.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkProvisioningInfo.h>
#include <QmitkSafeApplication.h>
#include <QmitkSingleApplication.h>
#include <Poco/Util/HelpFormatter.h>
#include <ctkPluginFramework.h>
#include <ctkPluginFramework_global.h>
#include <ctkPluginFrameworkLauncher.h>
#include <usModuleSettings.h>
#include <vtkOpenGLRenderWindow.h>
#include <QVTKOpenGLNativeWidget.h>
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QRunnable>
#include <QSplashScreen>
#include <QStandardPaths>
#include <QTime>
#include <QWebEngineUrlScheme>
namespace
{
void outputQtMessage(QtMsgType type, const QMessageLogContext&, const QString& msg)
{
auto message = msg.toStdString();
switch (type)
{
case QtDebugMsg:
MITK_DEBUG << message;
break;
case QtInfoMsg:
MITK_INFO << message;
break;
case QtWarningMsg:
MITK_WARN << message;
break;
case QtCriticalMsg:
MITK_ERROR << message;
break;
case QtFatalMsg:
MITK_ERROR << message;
abort();
default:
MITK_INFO << message;
break;
}
}
}
namespace mitk
{
const QString BaseApplication::ARG_APPLICATION = "BlueBerry.application";
const QString BaseApplication::ARG_CLEAN = "BlueBerry.clean";
const QString BaseApplication::ARG_CONSOLELOG = "BlueBerry.consoleLog";
const QString BaseApplication::ARG_DEBUG = "BlueBerry.debug";
const QString BaseApplication::ARG_FORCE_PLUGIN_INSTALL = "BlueBerry.forcePlugins";
const QString BaseApplication::ARG_HOME = "BlueBerry.home";
const QString BaseApplication::ARG_NEWINSTANCE = "BlueBerry.newInstance";
const QString BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING = "BlueBerry.noLazyRegistryCacheLoading";
const QString BaseApplication::ARG_NO_REGISTRY_CACHE = "BlueBerry.noRegistryCache";
const QString BaseApplication::ARG_PLUGIN_CACHE = "BlueBerry.plugin_cache_dir";
const QString BaseApplication::ARG_PLUGIN_DIRS = "BlueBerry.plugin_dirs";
const QString BaseApplication::ARG_PRELOAD_LIBRARY = "BlueBerry.preloadLibrary";
const QString BaseApplication::ARG_PRODUCT = "BlueBerry.product";
const QString BaseApplication::ARG_PROVISIONING = "BlueBerry.provisioning";
const QString BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE = "BlueBerry.registryMultiLanguage";
const QString BaseApplication::ARG_SPLASH_IMAGE = "BlueBerry.splashscreen";
const QString BaseApplication::ARG_STORAGE_DIR = "BlueBerry.storageDir";
const QString BaseApplication::ARG_XARGS = "xargs";
const QString BaseApplication::ARG_LOG_QT_MESSAGES = "Qt.logMessages";
const QString BaseApplication::ARG_SEGMENTATION_LABELSET_PRESET = "Segmentation.labelSetPreset";
const QString BaseApplication::ARG_SEGMENTATION_LABEL_SUGGESTIONS = "Segmentation.labelSuggestions";
const QString BaseApplication::PROP_APPLICATION = "blueberry.application";
const QString BaseApplication::PROP_FORCE_PLUGIN_INSTALL = BaseApplication::ARG_FORCE_PLUGIN_INSTALL;
const QString BaseApplication::PROP_NEWINSTANCE = BaseApplication::ARG_NEWINSTANCE;
const QString BaseApplication::PROP_NO_LAZY_REGISTRY_CACHE_LOADING = BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING;
const QString BaseApplication::PROP_NO_REGISTRY_CACHE = BaseApplication::ARG_NO_REGISTRY_CACHE;
const QString BaseApplication::PROP_PRODUCT = "blueberry.product";
const QString BaseApplication::PROP_REGISTRY_MULTI_LANGUAGE = BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE;
class SplashCloserCallback : public QRunnable
{
public:
SplashCloserCallback(QSplashScreen* splashscreen)
: m_Splashscreen(splashscreen)
{
}
void run() override
{
this->m_Splashscreen->close();
}
private:
QSplashScreen *m_Splashscreen; // Owned by BaseApplication::Impl
};
struct BaseApplication::Impl
{
ctkProperties m_FWProps;
QCoreApplication *m_QApp;
int m_Argc;
char **m_Argv;
#ifdef Q_OS_MAC
std::vector<char*> m_Argv_macOS;
#endif
QString m_AppName;
QString m_OrgaName;
QString m_OrgaDomain;
bool m_SingleMode;
bool m_SafeMode;
QSplashScreen *m_Splashscreen;
SplashCloserCallback *m_SplashscreenClosingCallback;
bool m_LogQtMessages;
QStringList m_PreloadLibs;
QString m_ProvFile;
Impl(int argc, char **argv)
: m_Argc(argc),
m_Argv(argv),
#ifdef Q_OS_MAC
m_Argv_macOS(),
#endif
m_SingleMode(false),
m_SafeMode(true),
m_Splashscreen(nullptr),
m_SplashscreenClosingCallback(nullptr),
m_LogQtMessages(false)
{
#ifdef Q_OS_MAC
/* On macOS the process serial number is passed as an command line argument (-psn_<NUMBER>)
in certain circumstances. This option causes a Poco exception. We remove it, if present. */
m_Argv_macOS.reserve(argc + 1);
const char psn[] = "-psn";
for (int i = 0; i < argc; ++i)
{
if (0 == strncmp(argv[i], psn, sizeof(psn) - 1))
continue;
m_Argv_macOS.push_back(argv[i]);
}
m_Argv_macOS.push_back(nullptr);
m_Argc = static_cast<decltype(m_Argc)>(m_Argv_macOS.size() - 1);
m_Argv = m_Argv_macOS.data();
#endif
}
~Impl()
{
delete m_SplashscreenClosingCallback;
delete m_Splashscreen;
delete m_QApp;
}
QVariant getProperty(const QString &property) const
{
auto iter = m_FWProps.find(property);
return m_FWProps.end() != iter
? iter.value()
: QVariant();
}
void handleBooleanOption(const std::string &name, const std::string &)
{
if (ARG_LOG_QT_MESSAGES.toStdString() == name)
{
m_LogQtMessages = true;
return;
}
auto fwKey = QString::fromStdString(name);
// Translate some keys to proper framework properties
if (ARG_CONSOLELOG == fwKey)
fwKey = ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG;
// For all other options we use the command line option name as the
// framework property key.
m_FWProps[fwKey] = true;
}
void handlePreloadLibraryOption(const std::string &, const std::string &value)
{
m_PreloadLibs.push_back(QString::fromStdString(value));
}
void handleClean(const std::string &, const std::string &)
{
m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
}
void initializeCTKPluginFrameworkProperties(Poco::Util::LayeredConfiguration &configuration)
{
// Add all configuration key/value pairs as framework properties
Poco::Util::LayeredConfiguration::Keys keys;
Poco::Util::LayeredConfiguration::Keys keyStack;
configuration.keys(keyStack);
std::vector<std::string> keyChain;
while (!keyStack.empty())
{
const auto currSubKey = keyStack.back();
if (!keyChain.empty() && keyChain.back() == currSubKey)
{
keyChain.pop_back();
keyStack.pop_back();
continue;
}
Poco::Util::LayeredConfiguration::Keys subKeys;
configuration.keys(currSubKey, subKeys);
if (subKeys.empty())
{
std::string finalKey;
keyStack.pop_back();
for (const auto& key : keyChain)
finalKey += key + '.';
finalKey += currSubKey;
keys.push_back(finalKey);
}
else
{
keyChain.push_back(currSubKey);
for (const auto& key : subKeys)
keyStack.push_back(key);
}
}
for (const auto& key : keys)
{
if (configuration.hasProperty(key))
{
// .ini and command line options overwrite already inserted keys
auto qKey = QString::fromStdString(key);
m_FWProps[qKey] = QString::fromStdString(configuration.getString(key));
}
}
}
void parseProvisioningFile(const QString &filePath)
{
// Skip parsing if the file path is empty
if (filePath.isEmpty())
return;
auto consoleLog = this->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool();
// Read initial plugins from a provisioning file
QFileInfo provFile(filePath);
QStringList pluginsToStart;
if (provFile.exists())
{
MITK_INFO(consoleLog) << "Using provisioning file: " << qPrintable(provFile.absoluteFilePath());
ProvisioningInfo provInfo(provFile.absoluteFilePath());
// It can still happen that the encoding is not compatible with the fromUtf8 function (i.e. when
// manipulating the LANG variable). The QStringList in provInfo is empty then.
if (provInfo.getPluginDirs().empty())
{
MITK_ERROR << "Cannot search for provisioning file, the retrieved directory list is empty.\n"
<< "This can happen if there are some special non-ASCII characters in the install path.";
}
else
{
for(const auto& pluginPath : provInfo.getPluginDirs())
ctkPluginFrameworkLauncher::addSearchPath(pluginPath);
auto pluginUrlsToStart = provInfo.getPluginsToStart();
for (const auto& url : qAsConst(pluginUrlsToStart))
pluginsToStart.push_back(url.toString());
}
}
else
{
MITK_INFO(consoleLog) << "Provisionig file does not exist.";
}
if (!pluginsToStart.isEmpty())
{
m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS] = pluginsToStart;
// Use transient start with declared activation policy (this helps when the provisioning file
// changes and some plug-ins should not be installed in the application any more).
ctkPlugin::StartOptions startOptions(ctkPlugin::START_TRANSIENT | ctkPlugin::START_ACTIVATION_POLICY);
m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS_START_OPTIONS] = static_cast<int>(startOptions);
}
}
};
BaseApplication::BaseApplication(int argc, char **argv)
: Application(),
d(new Impl(argc, argv))
{
}
BaseApplication::~BaseApplication()
{
delete d;
}
void BaseApplication::printHelp(const std::string &, const std::string &)
{
Poco::Util::HelpFormatter help(this->options());
help.setAutoIndent();
help.setCommand(this->commandName());
help.format(std::cout);
exit(EXIT_OK);
}
void BaseApplication::setApplicationName(const QString &name)
{
if (nullptr != qApp)
qApp->setApplicationName(name);
d->m_AppName = name;
}
QString BaseApplication::getApplicationName() const
{
return nullptr != qApp
? qApp->applicationName()
: d->m_AppName;
}
void BaseApplication::setOrganizationName(const QString &name)
{
if (nullptr != qApp)
qApp->setOrganizationName(name);
d->m_OrgaName = name;
}
QString BaseApplication::getOrganizationName() const
{
return nullptr != qApp
? qApp->organizationName()
: d->m_OrgaName;
}
void BaseApplication::setOrganizationDomain(const QString &domain)
{
if (nullptr != qApp)
qApp->setOrganizationDomain(domain);
d->m_OrgaDomain = domain;
}
QString BaseApplication::getOrganizationDomain() const
{
return nullptr != qApp
? qApp->organizationDomain()
: d->m_OrgaDomain;
}
void BaseApplication::setSingleMode(bool singleMode)
{
if (nullptr != qApp)
return;
d->m_SingleMode = singleMode;
}
bool BaseApplication::getSingleMode() const
{
return d->m_SingleMode;
}
void BaseApplication::setSafeMode(bool safeMode)
{
if (nullptr != qApp && nullptr == d->m_QApp)
return;
d->m_SafeMode = safeMode;
nullptr == d->m_QApp && getSingleMode()
? static_cast<QmitkSingleApplication *>(d->m_QApp)->setSafeMode(safeMode)
: static_cast<QmitkSafeApplication *>(d->m_QApp)->setSafeMode(safeMode);
}
bool BaseApplication::getSafeMode() const
{
return d->m_SafeMode;
}
void BaseApplication::setPreloadLibraries(const QStringList &libraryBaseNames)
{
d->m_PreloadLibs = libraryBaseNames;
}
QStringList BaseApplication::getPreloadLibraries() const
{
return d->m_PreloadLibs;
}
void BaseApplication::setProvisioningFilePath(const QString &filePath)
{
d->m_ProvFile = filePath;
}
QString BaseApplication::getProvisioningFilePath() const
{
auto provFilePath = d->m_ProvFile;
// A null QString means look up a default provisioning file
if (provFilePath.isNull() && nullptr != qApp)
{
QFileInfo appFilePath(QCoreApplication::applicationFilePath());
QDir basePath(QCoreApplication::applicationDirPath());
auto provFileName = appFilePath.baseName() + ".provisioning";
QFileInfo provFile(basePath.absoluteFilePath(provFileName));
#ifdef Q_OS_MAC
/*
* On macOS, if started from the build directory, the .provisioning file is located at:
* <MITK-build/bin/MitkWorkbench.provisioning>
* The executable path is:
* <MITK-build/bin/MitkWorkbench.app/Contents/MacOS/MitkWorkbench>
* In this case we have to cdUp threetimes.
*
* During packaging the MitkWorkbench.provisioning file is placed at the same
* level like the executable. Nothing has to be done.
*/
if (!provFile.exists())
{
basePath.cdUp();
basePath.cdUp();
basePath.cdUp();
provFile = basePath.absoluteFilePath(provFileName);
}
#endif
if (provFile.exists())
{
provFilePath = provFile.absoluteFilePath();
}
#ifdef CMAKE_INTDIR
else
{
basePath.cdUp();
provFile.setFile(basePath.absoluteFilePath(provFileName));
if (provFile.exists())
provFilePath = provFile.absoluteFilePath();
}
#endif
}
return provFilePath;
}
void BaseApplication::initializeQt()
{
if (nullptr != qApp)
return;
#ifdef Q_OS_LINUX
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--single-process"); // See T29332
#endif
// If parameters have been set before, we have to store them to hand them
// through to the application
auto appName = this->getApplicationName();
auto orgName = this->getOrganizationName();
auto orgDomain = this->getOrganizationDomain();
// Create a QCoreApplication instance
this->getQApplication();
// Provide parameters to QCoreApplication
this->setApplicationName(appName);
this->setOrganizationName(orgName);
this->setOrganizationDomain(orgDomain);
if (d->m_LogQtMessages)
qInstallMessageHandler(outputQtMessage);
QWebEngineUrlScheme qtHelpScheme("qthelp");
qtHelpScheme.setFlags(QWebEngineUrlScheme::LocalScheme | QWebEngineUrlScheme::LocalAccessAllowed);
QWebEngineUrlScheme::registerScheme(qtHelpScheme);
}
void BaseApplication::initialize(Poco::Util::Application &self)
{
// 1. Call the super-class method
Poco::Util::Application::initialize(self);
// 2. Initialize the Qt framework (by creating a QCoreApplication)
this->initializeQt();
// 3. Seed the random number generator, once at startup.
QTime time = QTime::currentTime();
qsrand((uint)time.msec());
// 4. Load the "default" configuration, which involves parsing
// an optional <executable-name>.ini file and parsing any
// command line arguments
this->loadConfiguration();
// 5. Add configuration data from the command line and the
// optional <executable-name>.ini file as CTK plugin
// framework properties.
d->initializeCTKPluginFrameworkProperties(this->config());
// 6. Initialize splash screen if an image path is provided
// in the .ini file
this->initializeSplashScreen(qApp);
// 7. Set the custom CTK Plugin Framework storage directory
QString storageDir = this->getCTKFrameworkStorageDir();
if (!storageDir.isEmpty())
{
d->m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storageDir;
// Initialize core service preferences at the exact same location as their predecessor BlueBerry preferences
mitk::CoreServicePointer preferencesService(mitk::CoreServices::GetPreferencesService());
preferencesService->InitializeStorage(storageDir.toStdString() + "/data/3/prefs.xml");
}
// 8. Set the library search paths and the pre-load library property
this->initializeLibraryPaths();
auto preloadLibs = this->getPreloadLibraries();
if (!preloadLibs.isEmpty())
d->m_FWProps[ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES] = preloadLibs;
// 9. Initialize the CppMicroServices library.
// The initializeCppMicroServices() method reuses the
// FRAMEWORK_STORAGE property, so we call it after the
// getCTKFrameworkStorageDir method.
this->initializeCppMicroServices();
// 10. Parse the (optional) provisioning file and set the
// correct framework properties.
d->parseProvisioningFile(this->getProvisioningFilePath());
// 11. Set the CTK Plugin Framework properties
ctkPluginFrameworkLauncher::setFrameworkProperties(d->m_FWProps);
}
void BaseApplication::uninitialize()
{
auto pfw = this->getFramework();
if (pfw)
{
pfw->stop();
// Wait for up to 10 seconds for the CTK plugin framework to stop
pfw->waitForStop(10000);
}
Poco::Util::Application::uninitialize();
}
int BaseApplication::getArgc() const
{
return d->m_Argc;
}
char **BaseApplication::getArgv() const
{
return d->m_Argv;
}
QString BaseApplication::getCTKFrameworkStorageDir() const
{
QString storageDir;
if (this->getSingleMode())
{
// This function checks if an instance is already running and either sends a message to
// it containing the command line arguments or checks if a new instance was forced by
// providing the BlueBerry.newInstance command line argument. In the latter case, a path
// to a temporary directory for the new application's storage directory is returned.
storageDir = handleNewAppInstance(static_cast<QtSingleApplication *>(d->m_QApp),
d->m_Argc, d->m_Argv, ARG_NEWINSTANCE);
}
if (storageDir.isEmpty())
{
// This is a new instance and no other instance is already running. We specify the
// storage directory here (this is the same code as in berryInternalPlatform.cpp)
// so that we can re-use the location for the persistent data location of the
// the CppMicroServices library.
// Append a hash value of the absolute path of the executable to the data location.
// This allows to start the same application from different build or install trees.
storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/" +
this->getOrganizationName() + "/" + this->getApplicationName() + '_';
storageDir += QString::number(qHash(QCoreApplication::applicationDirPath())) + "/";
}
return storageDir;
}
void BaseApplication::initializeCppMicroServices()
{
auto storageDir = this->getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString();
if (!storageDir.isEmpty())
us::ModuleSettings::SetStoragePath((storageDir + "us" + QDir::separator()).toStdString());
}
QCoreApplication *BaseApplication::getQApplication() const
{
if (nullptr == qApp)
{
vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(0);
auto defaultFormat = QVTKOpenGLNativeWidget::defaultFormat();
defaultFormat.setSamples(0);
QSurfaceFormat::setDefaultFormat(defaultFormat);
#ifdef Q_OS_OSX
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#endif
- QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+ QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
+#endif
+ QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
+
d->m_QApp = this->getSingleMode()
? static_cast<QCoreApplication*>(new QmitkSingleApplication(d->m_Argc, d->m_Argv, this->getSafeMode()))
: static_cast<QCoreApplication*>(new QmitkSafeApplication(d->m_Argc, d->m_Argv, this->getSafeMode()));
}
return qApp;
}
void BaseApplication::initializeLibraryPaths()
{
QStringList suffixes;
suffixes << "plugins";
#ifdef Q_OS_WINDOWS
suffixes << "bin/plugins";
#ifdef CMAKE_INTDIR
suffixes << "bin/" CMAKE_INTDIR "/plugins";
#endif
#else
suffixes << "lib/plugins";
#ifdef CMAKE_INTDIR
suffixes << "lib/" CMAKE_INTDIR "/plugins";
#endif
#endif
#ifdef Q_OS_MAC
suffixes << "../../plugins";
#endif
// We add a couple of standard library search paths for plug-ins
QDir appDir(QCoreApplication::applicationDirPath());
// Walk one directory up and add bin and lib sub-dirs; this might be redundant
appDir.cdUp();
for (const auto& suffix : qAsConst(suffixes))
ctkPluginFrameworkLauncher::addSearchPath(appDir.absoluteFilePath(suffix));
}
int BaseApplication::main(const std::vector<std::string> &args)
{
// Start the plugin framework and all installed plug-ins according to their auto-start setting
QStringList arguments;
for (auto const &arg : args)
arguments.push_back(QString::fromStdString(arg));
if (nullptr != d->m_Splashscreen)
{
// A splash screen is displayed. Create the closing callback.
d->m_SplashscreenClosingCallback = new SplashCloserCallback(d->m_Splashscreen);
}
return ctkPluginFrameworkLauncher::run(d->m_SplashscreenClosingCallback, QVariant::fromValue(arguments)).toInt();
}
void BaseApplication::defineOptions(Poco::Util::OptionSet &options)
{
Poco::Util::Option helpOption("help", "h", "print this help text");
helpOption.callback(Poco::Util::OptionCallback<BaseApplication>(this, &BaseApplication::printHelp));
options.addOption(helpOption);
Poco::Util::Option newInstanceOption(ARG_NEWINSTANCE.toStdString(), "", "forces a new instance of this application");
newInstanceOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
options.addOption(newInstanceOption);
Poco::Util::Option cleanOption(ARG_CLEAN.toStdString(), "", "cleans the plugin cache");
cleanOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleClean));
options.addOption(cleanOption);
Poco::Util::Option productOption(ARG_PRODUCT.toStdString(), "", "the id of the product to be launched");
productOption.argument("<id>").binding(PROP_PRODUCT.toStdString());
options.addOption(productOption);
Poco::Util::Option appOption(ARG_APPLICATION.toStdString(), "", "the id of the application extension to be executed");
appOption.argument("<id>").binding(PROP_APPLICATION.toStdString());
options.addOption(appOption);
Poco::Util::Option provOption(ARG_PROVISIONING.toStdString(), "", "the location of a provisioning file");
provOption.argument("<prov file>").binding(ARG_PROVISIONING.toStdString());
options.addOption(provOption);
Poco::Util::Option storageDirOption(ARG_STORAGE_DIR.toStdString(), "", "the location for storing persistent application data");
storageDirOption.argument("<dir>").binding(ctkPluginConstants::FRAMEWORK_STORAGE.toStdString());
options.addOption(storageDirOption);
Poco::Util::Option consoleLogOption(ARG_CONSOLELOG.toStdString(), "", "log messages to the console");
consoleLogOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
options.addOption(consoleLogOption);
Poco::Util::Option debugOption(ARG_DEBUG.toStdString(), "", "enable debug mode");
debugOption.argument("<options file>", false).binding(ctkPluginFrameworkLauncher::PROP_DEBUG.toStdString());
options.addOption(debugOption);
Poco::Util::Option forcePluginOption(ARG_FORCE_PLUGIN_INSTALL.toStdString(), "", "force installing plug-ins with same symbolic name");
forcePluginOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
options.addOption(forcePluginOption);
Poco::Util::Option preloadLibsOption(ARG_PRELOAD_LIBRARY.toStdString(), "", "preload a library");
preloadLibsOption.argument("<library>")
.repeatable(true)
.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handlePreloadLibraryOption));
options.addOption(preloadLibsOption);
Poco::Util::Option noRegistryCacheOption(ARG_NO_REGISTRY_CACHE.toStdString(), "", "do not use a cache for the registry");
noRegistryCacheOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
options.addOption(noRegistryCacheOption);
Poco::Util::Option noLazyRegistryCacheLoadingOption(ARG_NO_LAZY_REGISTRY_CACHE_LOADING.toStdString(), "", "do not use lazy cache loading for the registry");
noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
options.addOption(noLazyRegistryCacheLoadingOption);
Poco::Util::Option registryMultiLanguageOption(ARG_REGISTRY_MULTI_LANGUAGE.toStdString(), "", "enable multi-language support for the registry");
registryMultiLanguageOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
options.addOption(registryMultiLanguageOption);
Poco::Util::Option splashScreenOption(ARG_SPLASH_IMAGE.toStdString(), "", "optional picture to use as a splash screen");
splashScreenOption.argument("<filename>").binding(ARG_SPLASH_IMAGE.toStdString());
options.addOption(splashScreenOption);
Poco::Util::Option xargsOption(ARG_XARGS.toStdString(), "", "Extended argument list");
xargsOption.argument("<args>").binding(ARG_XARGS.toStdString());
options.addOption(xargsOption);
Poco::Util::Option logQtMessagesOption(ARG_LOG_QT_MESSAGES.toStdString(), "", "log Qt messages");
logQtMessagesOption.callback(Poco::Util::OptionCallback<Impl>(d, &Impl::handleBooleanOption));
options.addOption(logQtMessagesOption);
Poco::Util::Option labelSetPresetOption(ARG_SEGMENTATION_LABELSET_PRESET.toStdString(), "", "use this label set preset for new segmentations");
labelSetPresetOption.argument("<filename>").binding(ARG_SEGMENTATION_LABELSET_PRESET.toStdString());
options.addOption(labelSetPresetOption);
Poco::Util::Option labelSuggestionsOption(ARG_SEGMENTATION_LABEL_SUGGESTIONS.toStdString(), "", "use this list of predefined suggestions for segmentation labels");
labelSuggestionsOption.argument("<filename>").binding(ARG_SEGMENTATION_LABEL_SUGGESTIONS.toStdString());
options.addOption(labelSuggestionsOption);
Poco::Util::Application::defineOptions(options);
}
QSharedPointer<ctkPluginFramework> BaseApplication::getFramework() const
{
return ctkPluginFrameworkLauncher::getPluginFramework();
}
ctkPluginContext *BaseApplication::getFrameworkContext() const
{
auto framework = getFramework();
return framework
? framework->getPluginContext()
: nullptr;
}
void BaseApplication::initializeSplashScreen(QCoreApplication * application) const
{
auto pixmapFileNameProp = d->getProperty(ARG_SPLASH_IMAGE);
if (!pixmapFileNameProp.isNull())
{
auto pixmapFileName = pixmapFileNameProp.toString();
QFileInfo checkFile(pixmapFileName);
if (checkFile.exists() && checkFile.isFile())
{
QPixmap pixmap(checkFile.absoluteFilePath());
d->m_Splashscreen = new QSplashScreen(pixmap, Qt::WindowStaysOnTopHint);
d->m_Splashscreen->show();
application->processEvents();
}
}
}
QHash<QString, QVariant> BaseApplication::getFrameworkProperties() const
{
return d->m_FWProps;
}
int BaseApplication::run()
{
this->init(d->m_Argc, d->m_Argv);
return Application::run();
}
void BaseApplication::setProperty(const QString &property, const QVariant &value)
{
d->m_FWProps[property] = value;
}
QVariant BaseApplication::getProperty(const QString &property) const
{
return d->getProperty(property);
}
void BaseApplication::installTranslator(QTranslator* translator)
{
this->getQApplication()->installTranslator(translator);
}
bool BaseApplication::isRunning()
{
auto app = dynamic_cast<QtSingleApplication*>(this->getQApplication());
if (nullptr != app)
app->isRunning();
mitkThrow() << "Method not implemented.";
}
void BaseApplication::sendMessage(const QByteArray msg)
{
auto app = dynamic_cast<QtSingleApplication*>(this->getQApplication());
if (nullptr != app)
app->sendMessage(msg);
mitkThrow() << "Method not implemented.";
}
}
diff --git a/Modules/AppUtil/src/mitkProvisioningInfo.cpp b/Modules/AppUtil/src/mitkProvisioningInfo.cpp
index a781c173bb..7ccdb6c8ca 100644
--- a/Modules/AppUtil/src/mitkProvisioningInfo.cpp
+++ b/Modules/AppUtil/src/mitkProvisioningInfo.cpp
@@ -1,206 +1,206 @@
/*============================================================================
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 "mitkProvisioningInfo.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
namespace mitk
{
#ifdef CMAKE_INTDIR
const QString ProvisioningInfo::intermediateOutDir = QString(CMAKE_INTDIR);
#else
const QString ProvisioningInfo::intermediateOutDir = QString();
#endif
ProvisioningInfo::ProvisioningInfo(const QString &file) { this->readProvisioningFile(file); }
QStringList ProvisioningInfo::getPluginDirs() const { return pluginDirs.toList(); }
QList<QUrl> ProvisioningInfo::getPluginsToInstall() const { return pluginsToInstall; }
QList<QUrl> ProvisioningInfo::getPluginsToStart() const { return pluginsToStart; }
void ProvisioningInfo::readProvisioningFile(const QString &filePath)
{
QFile file(filePath);
file.open(QFile::ReadOnly);
QTextStream fileStream(&file);
QRegExp sep("\\s+");
QString line;
int count = 1;
do
{
line = fileStream.readLine().trimmed();
if (!line.isEmpty() && !line.startsWith('#'))
{
QString keyword = line.section(sep, 0, 0);
QString value = line.mid(keyword.size()).trimmed();
value = substituteKeywords(value);
if (keyword.isEmpty())
{
MITK_WARN << "Keyword missing in line " << count << " of provisioning file " << filePath.toStdString();
continue;
}
Keyword key = UNKNOWN;
if (keyword.compare("READ", Qt::CaseInsensitive) == 0)
{
key = READ;
}
else if (keyword.compare("INSTALL", Qt::CaseInsensitive) == 0)
{
key = INSTALL;
}
else if (keyword.compare("START", Qt::CaseInsensitive) == 0)
{
key = START;
}
else if (keyword.compare("STOP", Qt::CaseInsensitive) == 0)
{
key = STOP;
}
if (key == UNKNOWN)
{
MITK_WARN << "Keyword " << keyword.toStdString() << " in line " << count << " of provisioning file "
<< filePath.toStdString() << " unknown";
continue;
}
if (value.isEmpty())
{
MITK_WARN << "Value after keyword " << keyword.toStdString() << " missing in line " << count
<< " of provisioning file " << filePath.toStdString();
continue;
}
switch (key)
{
case READ:
{
QUrl readFileUrl(value);
if (!readFileUrl.isValid())
{
MITK_WARN << "The READ URL " << value.toStdString()
<< "is invalid: " << readFileUrl.errorString().toStdString();
break;
}
this->readProvisioningFile(readFileUrl.toLocalFile());
break;
}
case INSTALL:
{
this->addPluginToInstall(value);
break;
}
case START:
{
this->addPluginToStart(value);
break;
}
case STOP:
{
break;
}
case UNKNOWN:
{
break; // error handled above
}
}
}
++count;
} while (!line.isNull());
}
QUrl ProvisioningInfo::addPluginToInstall(const QString &file)
{
QUrl pluginUrl(file);
if (!pluginUrl.isValid())
{
MITK_WARN << "The plugin URL " << file.toStdString() << " is invalid:" << pluginUrl.errorString().toStdString();
return QUrl();
}
QFileInfo fileInfo(pluginUrl.toLocalFile());
if (!fileInfo.exists())
{
QString fileName = fileInfo.fileName();
QString filePath = fileInfo.absolutePath();
if (!intermediateOutDir.isEmpty())
{
// search in the intermediate output dir
QString filePath2 = filePath + "/" + intermediateOutDir;
fileInfo = QFileInfo(filePath2 + "/" + fileName);
if (!fileInfo.exists())
{
MITK_WARN << "The plugin " << fileName.toStdString() << " was not found in " << filePath.toStdString()
<< " or " << filePath2.toStdString();
return QUrl();
}
pluginUrl = QUrl::fromLocalFile(fileInfo.canonicalFilePath());
pluginDirs.insert(fileInfo.canonicalPath());
}
else
{
MITK_WARN << "The plugin " << fileName.toStdString() << " was not found in " << filePath.toStdString();
return QUrl();
}
}
else
{
pluginDirs.insert(fileInfo.canonicalPath());
}
pluginsToInstall.append(pluginUrl);
return pluginUrl;
}
void ProvisioningInfo::addPluginToStart(const QString &file)
{
QUrl pluginUrl = this->addPluginToInstall(file);
if (!pluginUrl.isEmpty())
{
pluginsToStart.append(pluginUrl);
}
}
QString ProvisioningInfo::substituteKeywords(const QString &value) const
{
QString appPath = QCoreApplication::applicationDirPath();
if (appPath.endsWith('/'))
{
appPath.chop(1);
}
#ifdef CMAKE_INTDIR
// Strip the intermediate dir from the application path
QString intDir(CMAKE_INTDIR);
if (appPath.endsWith(intDir))
{
appPath.chop(intDir.size() + 1);
}
#endif
#ifdef _WIN32
if (value.contains("@EXECUTABLE_DIR") && value.contains("blueberry_osgi"))
{
// special case for org_blueberry_osgi in install trees for Windows
return QString(value).replace("@EXECUTABLE_DIR", appPath, Qt::CaseInsensitive).replace("plugins/", "");
}
#endif
return QString(value).replace("@EXECUTABLE_DIR", appPath, Qt::CaseInsensitive);
}
}
diff --git a/Modules/BoundingShape/src/DataManagement/mitkBoundingShapeUtil.cpp b/Modules/BoundingShape/src/DataManagement/mitkBoundingShapeUtil.cpp
index f3b18bb3c9..a82b04d219 100644
--- a/Modules/BoundingShape/src/DataManagement/mitkBoundingShapeUtil.cpp
+++ b/Modules/BoundingShape/src/DataManagement/mitkBoundingShapeUtil.cpp
@@ -1,213 +1,213 @@
/*============================================================================
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 "mitkBoundingShapeUtil.h"
#include "mitkGeometry3D.h"
#include "vtkDoubleArray.h"
#include "vtkMath.h"
#include <vtkSmartPointer.h>
#include <algorithm>
mitk::Handle::Handle() : m_IsActive(false), m_FaceIndices(4), m_Index(0)
{
m_Position.Fill(0.0);
}
mitk::Handle::Handle(mitk::Point3D pos, int index, std::vector<int> faceIndices, bool active)
: m_IsActive(active), m_Position(pos), m_FaceIndices(faceIndices), m_Index(index)
{
}
mitk::Handle::~Handle()
{
}
bool mitk::Handle::IsActive()
{
return m_IsActive;
}
bool mitk::Handle::IsNotActive()
{
return !m_IsActive;
};
void mitk::Handle::SetActive(bool status)
{
m_IsActive = status;
};
void mitk::Handle::SetPosition(mitk::Point3D pos)
{
m_Position = pos;
};
mitk::Point3D mitk::Handle::GetPosition()
{
return m_Position;
};
void mitk::Handle::SetIndex(int index)
{
m_Index = index;
};
int mitk::Handle::GetIndex()
{
return m_Index;
};
std::vector<int> mitk::Handle::GetFaceIndices()
{
return m_FaceIndices;
};
mitk::Point3D mitk::CalcAvgPoint(mitk::Point3D a, mitk::Point3D b)
{
mitk::Point3D c;
c[0] = (a[0] + b[0]) / 2.0;
c[1] = (a[1] + b[1]) / 2.0;
c[2] = (a[2] + b[2]) / 2.0;
return c;
}
std::vector<mitk::Point3D> mitk::GetCornerPoints(mitk::BaseGeometry::Pointer geometry, bool visualizationOffset)
{
if (geometry == nullptr)
mitkThrow() << "Geometry is not valid.";
mitk::BoundingBox::ConstPointer boundingBox = geometry->GetBoundingBox();
mitk::Point3D BBmin = boundingBox->GetMinimum();
mitk::Point3D BBmax = boundingBox->GetMaximum();
// use 0.5 offset because the vtkCubeSource is not center pixel based (only for visualization purpose)
if (visualizationOffset)
{
- BBmin -= 0.5;
- BBmax -= 0.5;
+ BBmin -= mitk::Vector(0.5);
+ BBmax -= mitk::Vector(0.5);
}
mitk::Point3D p0;
p0[0] = BBmin[0];
p0[1] = BBmin[1];
p0[2] = BBmin[2]; // bottom - left - back corner
mitk::Point3D p1;
p1[0] = BBmin[0];
p1[1] = BBmin[1];
p1[2] = BBmax[2]; // top - left - back corner
mitk::Point3D p2;
p2[0] = BBmin[0];
p2[1] = BBmax[1];
p2[2] = BBmin[2]; // bottom - left - front corner
mitk::Point3D p3;
p3[0] = BBmin[0];
p3[1] = BBmax[1];
p3[2] = BBmax[2]; // top - left - front corner
mitk::Point3D p4;
p4[0] = BBmax[0];
p4[1] = BBmin[1];
p4[2] = BBmin[2]; // bottom - right - back corner
mitk::Point3D p5;
p5[0] = BBmax[0];
p5[1] = BBmin[1];
p5[2] = BBmax[2]; // top - right - back corner
mitk::Point3D p6;
p6[0] = BBmax[0];
p6[1] = BBmax[1];
p6[2] = BBmin[2]; // bottom - right - front corner
mitk::Point3D p7;
p7[0] = BBmax[0];
p7[1] = BBmax[1];
p7[2] = BBmax[2]; // top - right - front corner
std::vector<mitk::Point3D> cornerPoints;
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p0));
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p1));
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p2));
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p3));
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p4));
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p5));
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p6));
cornerPoints.push_back(geometry->GetIndexToWorldTransform()->TransformPoint(p7));
return cornerPoints;
}
std::vector<int> mitk::GetHandleIndices(int index)
{
std::vector<int> faceIndices;
faceIndices.resize(4);
// +------+
// / /|
// +------+ |
// | | +
// | |/
// +------+
switch (index)
{
case 0:
{
faceIndices[0] = 0;
faceIndices[1] = 1;
faceIndices[2] = 2;
faceIndices[3] = 3;
}
break;
case 1:
{
faceIndices[0] = 4;
faceIndices[1] = 5;
faceIndices[2] = 6;
faceIndices[3] = 7;
}
break;
case 3:
{
faceIndices[0] = 0;
faceIndices[1] = 2;
faceIndices[2] = 4;
faceIndices[3] = 6;
}
break;
case 2:
{
faceIndices[0] = 1;
faceIndices[1] = 3;
faceIndices[2] = 5;
faceIndices[3] = 7;
}
break;
case 4:
{
faceIndices[0] = 0;
faceIndices[1] = 1;
faceIndices[2] = 4;
faceIndices[3] = 5;
}
break;
case 5:
{
faceIndices[0] = 2;
faceIndices[1] = 3;
faceIndices[2] = 6;
faceIndices[3] = 7;
}
break;
default:
{
faceIndices[0] = 0;
faceIndices[1] = 0;
faceIndices[2] = 0;
faceIndices[3] = 0;
}
break;
}
return faceIndices;
}
diff --git a/Modules/CEST/autoload/IO/mitkCESTIOMimeTypes.cpp b/Modules/CEST/autoload/IO/mitkCESTIOMimeTypes.cpp
index 449b415072..2b7d02c094 100644
--- a/Modules/CEST/autoload/IO/mitkCESTIOMimeTypes.cpp
+++ b/Modules/CEST/autoload/IO/mitkCESTIOMimeTypes.cpp
@@ -1,229 +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 "mitkCESTIOMimeTypes.h"
#include "mitkIOMimeTypes.h"
#include <mitkCustomTagParser.h>
#include <mitkDICOMDCMTKTagScanner.h>
#include <mitkDICOMFileReaderSelector.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <itkGDCMImageIO.h>
#include <itksys/SystemTools.hxx>
namespace mitk
{
std::vector<CustomMimeType *> MitkCESTIOMimeTypes::Get()
{
std::vector<CustomMimeType *> mimeTypes;
// order matters here (descending rank for mime types)
mimeTypes.push_back(CEST_DICOM_WITH_META_FILE_MIMETYPE().Clone());
mimeTypes.push_back(CEST_DICOM_MIMETYPE().Clone());
mimeTypes.push_back(CEST_DICOM_WITHOUT_META_FILE_MIMETYPE().Clone());
return mimeTypes;
}
// Mime Types
MitkCESTIOMimeTypes::MitkCESTDicomMimeType::MitkCESTDicomMimeType() : IOMimeTypes::BaseDicomMimeType(CEST_DICOM_MIMETYPE_NAME())
{
this->SetCategory(IOMimeTypes::CATEGORY_IMAGES());
this->SetComment("CEST DICOM");
}
bool MitkCESTIOMimeTypes::MitkCESTDicomMimeType::AppliesTo(const std::string &path) const
{
bool canRead(IOMimeTypes::BaseDicomMimeType::AppliesTo(path));
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if (!itksys::SystemTools::FileExists(path.c_str()))
{
return canRead;
}
// end fix for bug 18572
if (!canRead)
{
return canRead;
}
mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New();
mitk::DICOMTag siemensCESTprivateTag(0x0029, 0x1020);
mitk::StringList relevantFiles;
relevantFiles.push_back(path);
scanner->AddTag(siemensCESTprivateTag);
scanner->SetInputFiles(relevantFiles);
scanner->Scan();
mitk::DICOMTagCache::Pointer tagCache = scanner->GetScanCache();
mitk::DICOMImageFrameList imageFrameList = mitk::ConvertToDICOMImageFrameList(tagCache->GetFrameInfoList());
bool mapNotEmpty = false;
if (!imageFrameList.empty())
{
mitk::DICOMImageFrameInfo* firstFrame = imageFrameList.begin()->GetPointer();
std::string byteString = tagCache->GetTagValue(firstFrame, siemensCESTprivateTag).value;
if (byteString.empty()) {
return false;
}
mitk::CustomTagParser tagParser(relevantFiles[0]);
auto parsedPropertyList = tagParser.ParseDicomPropertyString(byteString);
mapNotEmpty = !parsedPropertyList->GetMap()->empty();
}
return mapNotEmpty;
}
MitkCESTIOMimeTypes::MitkCESTDicomMimeType *MitkCESTIOMimeTypes::MitkCESTDicomMimeType::Clone() const
{
return new MitkCESTDicomMimeType(*this);
}
MitkCESTIOMimeTypes::MitkCESTDicomMimeType MitkCESTIOMimeTypes::CEST_DICOM_MIMETYPE()
{
return MitkCESTDicomMimeType();
}
std::string MitkCESTIOMimeTypes::CEST_DICOM_MIMETYPE_NAME()
{
// create a unique and sensible name for this mime type
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".image.dicom.cest";
return name;
}
MitkCESTIOMimeTypes::MitkCESTDicomWithMetaFileMimeType::MitkCESTDicomWithMetaFileMimeType() : IOMimeTypes::BaseDicomMimeType(CEST_DICOM_WITH_META_FILE_NAME())
{
this->SetCategory(IOMimeTypes::CATEGORY_IMAGES());
this->SetComment("CEST DICOM");
}
bool MitkCESTIOMimeTypes::MitkCESTDicomWithMetaFileMimeType::AppliesTo(const std::string& path) const
{
bool canRead(IOMimeTypes::BaseDicomMimeType::AppliesTo(path));
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if (!itksys::SystemTools::FileExists(path.c_str()))
{
return canRead;
}
// end fix for bug 18572
if (!canRead)
{
return canRead;
}
std::string dir = path;
if (!itksys::SystemTools::FileIsDirectory(path))
{
dir = itksys::SystemTools::GetProgramPath(path);
}
std::string metafilePath = dir +"/" + "CEST_META.json";
canRead = itksys::SystemTools::FileExists(metafilePath.c_str());
return canRead;
}
MitkCESTIOMimeTypes::MitkCESTDicomWithMetaFileMimeType* MitkCESTIOMimeTypes::MitkCESTDicomWithMetaFileMimeType::Clone() const
{
return new MitkCESTDicomWithMetaFileMimeType(*this);
}
MitkCESTIOMimeTypes::MitkCESTDicomWithMetaFileMimeType MitkCESTIOMimeTypes::CEST_DICOM_WITH_META_FILE_MIMETYPE()
{
return MitkCESTDicomWithMetaFileMimeType();
}
std::string MitkCESTIOMimeTypes::CEST_DICOM_WITH_META_FILE_NAME()
{
// create a unique and sensible name for this mime type
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".image.dicom.cest.generic.meta";
return name;
}
MitkCESTIOMimeTypes::MitkCESTDicomWOMetaFileMimeType::MitkCESTDicomWOMetaFileMimeType() : IOMimeTypes::BaseDicomMimeType(CEST_DICOM_WITHOUT_META_FILE_NAME())
{
this->SetCategory(IOMimeTypes::CATEGORY_IMAGES());
this->SetComment("CEST DICOM");
}
bool MitkCESTIOMimeTypes::MitkCESTDicomWOMetaFileMimeType::AppliesTo(const std::string& path) const
{
bool canRead(IOMimeTypes::BaseDicomMimeType::AppliesTo(path));
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if (!itksys::SystemTools::FileExists(path.c_str()))
{
return canRead;
}
// end fix for bug 18572
if (!canRead)
{
return canRead;
}
std::string dir = path;
if (!itksys::SystemTools::FileIsDirectory(path))
{
dir = itksys::SystemTools::GetProgramPath(path);
}
std::string metafilePath = dir + "/" + "CEST_META.json";
canRead = !itksys::SystemTools::FileExists(metafilePath.c_str());
return canRead;
}
MitkCESTIOMimeTypes::MitkCESTDicomWOMetaFileMimeType* MitkCESTIOMimeTypes::MitkCESTDicomWOMetaFileMimeType::Clone() const
{
return new MitkCESTDicomWOMetaFileMimeType(*this);
}
MitkCESTIOMimeTypes::MitkCESTDicomWOMetaFileMimeType MitkCESTIOMimeTypes::CEST_DICOM_WITHOUT_META_FILE_MIMETYPE()
{
return MitkCESTDicomWOMetaFileMimeType();
}
std::string MitkCESTIOMimeTypes::CEST_DICOM_WITHOUT_META_FILE_NAME()
{
// create a unique and sensible name for this mime type
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".image.dicom.cest.generic.nometa";
return name;
}
}
diff --git a/Modules/CameraCalibration/mitkTransform.h b/Modules/CameraCalibration/mitkTransform.h
index cbd7139879..2ca3713a29 100644
--- a/Modules/CameraCalibration/mitkTransform.h
+++ b/Modules/CameraCalibration/mitkTransform.h
@@ -1,300 +1,300 @@
/*============================================================================
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 mitkTransform_h
#define mitkTransform_h
#include <itkObject.h>
#include <opencv2/calib3d.hpp>
#include <mitkCommon.h>
#include <mitkNumericTypes.h>
#include <mitkNavigationData.h>
#include <sstream>
#include <vtkMatrix4x4.h>
#include <mitkXMLSerializable.h>
#include <MitkCameraCalibrationExports.h>
namespace mitk {
///
/// \brief class representing a transfrom in 3D
///
/// internally it stores a mitk navigation data. this is more
/// or less a wrapper for navigation data for easy casting
/// between opencv/vnl/mitk/xml representations of transform
/// data
///
class MITKCAMERACALIBRATION_EXPORT Transform: public itk::Object,
public XMLSerializable
{
public:
mitkClassMacroItkParent(Transform, itk::Object);
itkFactorylessNewMacro(Transform);
mitkNewMacro1Param(Transform, const mitk::NavigationData*);
mitkNewMacro1Param(Transform, const std::string&);
///
/// constants describing the type of transform
/// represented here
///
static const std::string UNKNOWN_TYPE;
static const std::string ENDOSCOPE_SCOPE_TOOL;
static const std::string ENDOSCOPE_CAM_TOOL;
static const std::string CHESSBOARD_TOOL;
static const std::string POINTER_TOOL;
static const std::string POINTER_TO_CHESSBOARD_ORIGIN;
static const std::string POINTER_TO_CHESSBOARD_X_SUPPORT_POINT;
static const std::string POINTER_TO_CHESSBOARD_Y_SUPPORT_POINT;
static const std::string BOARD_TO_BOARD_TOOL;
static const std::string REFERENCE_CAMERA_TRANSFORM;
static const std::string REFERENCE_SCOPE_TRANSFORM;
static const std::string EYE_TO_HAND_TRANSFORM;
static const std::string CAMERA_EXTRINSICS;
itkGetConstMacro(Type, std::string);
itkSetMacro(Type, std::string&);
///
/// Copies the content of transform to this
/// instance
///
void Copy( const mitk::Transform* transform );
///
/// Copies the content of transform to this
/// instance
///
void Copy( const mitk::NavigationData* transform );
///
/// Inverts the rotation of this transform
/// (Polaris navigation Data have inverted rotation
/// so you may want to call this function when using
/// polaris data)
///
void TransposeRotation();
///
/// get a copy of this transform
///
mitk::Transform::Pointer Clone() const;
///
/// concatenate this transform with the given one,
/// i.e. this transform is done first, then transform
/// ( if x is this transform, y is transform, then this will be y*x)
/// post multiply semantics!
/// \see vtkTransform
///
void Concatenate( mitk::Transform* transform );
///
/// same as above with vnl mat argument
///
void Concatenate( const vnl_matrix_fixed<mitk::ScalarType, 4, 4>& transform );
///
/// same as above with vtk mat argument
///
void Concatenate( const vtkMatrix4x4* transform );
///
/// invert this transform
///
void Invert();
///
/// resets the internal variables except type
///
void Reset();
///
/// read from xml
///
void FromXML(const tinyxml2::XMLElement* elem) override;
///
/// read csv file
///
void FromCSVFile(const std::string& file);
///
/// grafts the data from naviData to this transform
///
void SetNavigationData( const mitk::NavigationData* naviData );
///
/// method to set orientation quat
///
void SetOrientation( const vnl_quaternion<mitk::ScalarType>& orientation);
///
/// method to set float valued orientation quat
///
void SetOrientation( const vnl_quaternion<float>& orientation);
///
/// method to set translation
///
void SetTranslation( const vnl_vector_fixed<mitk::ScalarType, 3>& transl);
///
/// method to set a vector of doubles as translation
///
void SetTranslation( const vnl_vector<double>& transl);
///
/// method to set a mitk::Point3D as position
///
void SetPosition( const mitk::Point3D& transl);
///
/// sets rotation with a rotation matrix
///
void SetRotation( vnl_matrix_fixed<mitk::ScalarType, 3, 3>& mat);
///
/// sets rotation with a non fixed rotation matrix
///
void SetRotation( vnl_matrix<mitk::ScalarType>& mat);
///
/// sets rotation and translation with a transformation matrix
///
void SetMatrix( const vnl_matrix_fixed<mitk::ScalarType, 4, 4>& mat);
///
/// sets rotation and translation with a vtk transformation matrix
///
void SetMatrix( const vtkMatrix4x4* mat);
///
/// sets translation from a POD vector
///
void SetTranslation( float* array );
///
/// sets translation from a POD vector. this must be a
/// 3x3=9 sized vector in row major format (first row = first
/// three elements)
///
void SetRotation( float* array );
///
/// sets translation from a POD vector
///
void SetTranslation( double array[3] );
///
/// sets translation from a POD vector
///
void SetRotation( double array[3][3] );
///
/// method to set translation by cv vector
///
void SetTranslation( const cv::Mat& transl);
///
/// sets rotation with a rotation matrix
///
void SetRotation( const cv::Mat& mat );
///
/// sets rotation with a rodrigues rotation vector
///
void SetRotationVector( const cv::Mat& rotVec);
///
/// \return the navigation data that stores all information
///
mitk::NavigationData::Pointer GetNavigationData() const;
///
/// calls navigationdata::GetPosition()
///
mitk::Point3D GetPosition() const;
///
/// same as GetPosition
///
mitk::Point3D GetTranslation() const;
///
/// calls navigationdata::IsValid()
///
bool IsValid() const;
///
/// calls navigationdata::SetValid()
///
void SetValid(bool valid);
///
/// calls navigationdata::GetOrientation()
///
mitk::Quaternion GetOrientation() const;
///
/// \return the homogeneous matrix representing this transform
///
vnl_matrix_fixed<mitk::ScalarType, 4, 4> GetMatrix() const;
///
- /// \return the homogeneous vtk matrix representing this transform
+ /// returns the homogeneous vtk matrix representing this transform
///
void GetMatrix(vtkMatrix4x4* matrix) const;
///
- /// \return the homogeneous vtk matrix representing this transform
+ /// returns the homogeneous vtk matrix representing this transform
/// in !OpenGL! left handed coordinate system
///
void GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const;
mitk::Point3D TransformPoint(mitk::Point3D point) const;
///
/// create xml representation
///
void ToXML(tinyxml2::XMLElement* elem) const override;
///
/// create string representation
///
std::string ToString() const;
///
/// create string csv representation (only the transformation values!!!!)
///
std::string ToCSVString() const;
///
/// create matlab representation
///
std::string ToMatlabString(const std::string& varname="transform",
bool printLastRow=true) const;
///
/// write csv representation to file (only the transformation values!!!!)
///
void ToCSVFile(const std::string& file) const;
///
/// write matlab representation to file
///
void ToMatlabFile(const std::string& file
, const std::string& varname="transform") const;
///
/// conversion to cv types
///
cv::Mat GetCvTranslation() const;
cv::Mat GetCvRotationVector() const;
cv::Mat GetCvRotationMatrix() const;
cv::Mat GetCvMatrix() const;
///
/// conversion to vnl types
///
vnl_vector_fixed<mitk::ScalarType, 3> GetVnlTranslation() const;
vnl_vector_fixed<double, 3> GetVnlDoubleTranslation() const;
vnl_quaternion<double> GetVnlDoubleQuaternion() const;
vnl_matrix_fixed<mitk::ScalarType, 3, 3> GetVnlRotationMatrix() const;
vnl_matrix_fixed<double, 4, 4> GetVnlDoubleMatrix() const;
protected:
Transform();
Transform(const mitk::NavigationData* nd);
Transform(const std::string& s);
// everything is stored here
mitk::NavigationData::Pointer m_NavData;
///
/// saves the type of the transform (Default is UNKNOWN_TYPE)
///
std::string m_Type;
};
} // namespace mitk
MITKCAMERACALIBRATION_EXPORT std::ostream& operator<<
(std::ostream& os, mitk::Transform::Pointer p);
#endif
diff --git a/Modules/Classification/CLCore/CMakeLists.txt b/Modules/Classification/CLCore/CMakeLists.txt
index cd84cde61e..cdcd91eb6f 100644
--- a/Modules/Classification/CLCore/CMakeLists.txt
+++ b/Modules/Classification/CLCore/CMakeLists.txt
@@ -1,7 +1,5 @@
MITK_CREATE_MODULE(
DEPENDS MitkCore MitkCommandLine
PACKAGE_DEPENDS
PUBLIC Eigen
)
-
-#add_subdirectory(test)
diff --git a/Modules/Classification/CLCore/test/CMakeLists.txt b/Modules/Classification/CLCore/test/CMakeLists.txt
deleted file mode 100644
index 153cd81e2e..0000000000
--- a/Modules/Classification/CLCore/test/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-MITK_CREATE_MODULE_TESTS()
diff --git a/Modules/Classification/CLCore/test/files.cmake b/Modules/Classification/CLCore/test/files.cmake
deleted file mode 100644
index b3c610084e..0000000000
--- a/Modules/Classification/CLCore/test/files.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-set(MODULE_TESTS
- mitkImageToEigenTransformTest.cpp
-)
diff --git a/Modules/Classification/CLImportanceWeighting/CMakeLists.txt b/Modules/Classification/CLImportanceWeighting/CMakeLists.txt
deleted file mode 100644
index 41538b3b47..0000000000
--- a/Modules/Classification/CLImportanceWeighting/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-MITK_CREATE_MODULE(
- DEPENDS MitkCore MitkCLCore MitkDataCollection
- PACKAGE_DEPENDS PUBLIC Vigra
-)
-
-#add_subdirectory(test)
diff --git a/Modules/Classification/CLImportanceWeighting/files.cmake b/Modules/Classification/CLImportanceWeighting/files.cmake
deleted file mode 100644
index a0483df9b6..0000000000
--- a/Modules/Classification/CLImportanceWeighting/files.cmake
+++ /dev/null
@@ -1,16 +0,0 @@
-file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
-
-set(CPP_FILES
- mitkDistModels.cpp
- mitkLinkModels.cpp
- mitkLRDensityEstimation.cpp
- mitkGeneralizedLinearModel.cpp
- #Algorithms/itkLabelSampler.cpp
- #Algorithms/itkSmoothedClassProbabilites.cpp
-
- #Features/itkNeighborhoodFunctorImageFilter.cpp
- #mitkCLUtil.cpp
-)
-
-set( TOOL_FILES
-)
diff --git a/Modules/Classification/CLImportanceWeighting/include/mitkDistModels.h b/Modules/Classification/CLImportanceWeighting/include/mitkDistModels.h
deleted file mode 100644
index 60279d5a54..0000000000
--- a/Modules/Classification/CLImportanceWeighting/include/mitkDistModels.h
+++ /dev/null
@@ -1,37 +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.
-
-============================================================================*/
-
-#ifndef mitkDistModels_h
-#define mitkDistModels_h
-
-#include <MitkCLImportanceWeightingExports.h>
-
-namespace mitk
-{
- class MITKCLIMPORTANCEWEIGHTING_EXPORT AbstractDistribution
- {
- public:
- virtual double SqrtVariance(double mu) = 0;
- virtual double Devariation(double mu, double y) = 0;
- virtual double Init(double y) = 0;
- };
-
- class MITKCLIMPORTANCEWEIGHTING_EXPORT DistSimpleBinominal : AbstractDistribution
- {
- public:
- double SqrtVariance(double mu) override;
- double Devariation(double mu, double y) override;
- double Init(double y) override;
- };
-}
-
-#endif
diff --git a/Modules/Classification/CLImportanceWeighting/include/mitkGeneralizedLinearModel.h b/Modules/Classification/CLImportanceWeighting/include/mitkGeneralizedLinearModel.h
deleted file mode 100644
index b9033ad8e8..0000000000
--- a/Modules/Classification/CLImportanceWeighting/include/mitkGeneralizedLinearModel.h
+++ /dev/null
@@ -1,99 +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.
-
-============================================================================*/
-
-#ifndef mitkGeneralizedLinearModel_h
-#define mitkGeneralizedLinearModel_h
-
-#include <MitkCLImportanceWeightingExports.h>
-
-#include <vnl/vnl_matrix.h>
-#include <vnl/vnl_vector.h>
-
-namespace mitk
-{
- /**
- * \brief Generalized Linear Model that allows linear models for non-gaussian data
- *
- * Generalized linear models are an extension of standard linear models that allow
- * a different apperance of the data. This is for example usefull to calculate
- * Logistic regressions.
- */
- class MITKCLIMPORTANCEWEIGHTING_EXPORT GeneralizedLinearModel
- {
- public:
- /**
- * \brief Initialization of the GLM. The parameters needs to be passed at the beginning.
- *
- * Constructor for a GLM. During the creation process the glm model parameter
- * are guessed.
- *
- * @param xData The input data matrix.
- * @param yData The output data matrix. The values of y must meet the requirements of the link and distribution.
- * @param addConstantColumn Default=True. If True an constant value is added to each row allowing a constant factor in the model.
- */
- GeneralizedLinearModel (const vnl_matrix<double> &xData, const vnl_vector<double> &yData, bool addConstantColumn=true);
-
- /**
- * \brief Predicts the value corresponding to the given vector.
- *
- * From the learned data a guess is given depending on the provided input vector. The
- * value depend on the b-values of the learned model as well as on the chosen link and
- * distribution.
- *
- * No input validation is done. The data and the learned model might not match!
- *
- * @param c Column for which the data is guessed.
- */
- double Predict(const vnl_vector<double> &c);
-
- /**
- * \brief Predicts the value corresponding to the given matrix.
- *
- * From the learned data a guess is given depending on the provided input matrix. The
- * value depend on the b-values of the learned model as well as on the chosen link and
- * distribution.
- *
- * No input validation is done. The data and the learned model might not match!
- *
- * @param x Matrix for which the data is guessed.
- */
- vnl_vector<double> Predict(const vnl_matrix<double> &x);
-
- /**
- * \brief Estimation of the exponential factor for a given function
- *
- * Gives the exponential part of a link function. Only suitable for log-it models. This
- * is especially usefull for calculating the weights for transfer learning since it
- * is equal to the weights.
- *
- */
- vnl_vector<double> ExpMu(const vnl_matrix<double> &x);
-
- /**
- * \brief Returns the b-Vector for the estimation
- */
- vnl_vector<double> B();
-
- private:
-
- // Estimates the rank of the matrix and creates a permutation vector so
- // that the most important columns are first. Depends on a QR-algorithm.
- void EstimatePermutation(const vnl_matrix<double> &xData);
-
- vnl_vector<unsigned int> m_Permutation; // Holds a permutation matrix which is used during calculation of B
- vnl_vector<double> m_B; // B-Values. Linear componentn of the model.
- bool m_AddConstantColumn; // If true, a constant value is added to each row
-// int m_Rank; // The estimated input rank of the matrix.
- };
-}
-
-#endif
diff --git a/Modules/Classification/CLImportanceWeighting/include/mitkLRDensityEstimation.h b/Modules/Classification/CLImportanceWeighting/include/mitkLRDensityEstimation.h
deleted file mode 100644
index d47fedc472..0000000000
--- a/Modules/Classification/CLImportanceWeighting/include/mitkLRDensityEstimation.h
+++ /dev/null
@@ -1,61 +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.
-
-============================================================================*/
-
-#ifndef mitkLRDensityEstimation_h
-#define mitkLRDensityEstimation_h
-
-#include <vigra/matrix.hxx>
-#include <vigra/random_forest.hxx>
-
-#include <mitkDataCollection.h>
-
-#include <MitkCLImportanceWeightingExports.h>
-
-namespace mitk
-{
- class MITKCLIMPORTANCEWEIGHTING_EXPORT LRDensityEstimation
- {
- public:
- typedef vigra::MultiArray<2, double> MatrixType;
-
- void SetCollection(DataCollection::Pointer data);
- DataCollection::Pointer GetCollection();
-
- void SetTestMask(std::string name);
- std::string GetTestMask();
-
- void SetTrainMask(std::string name);
- std::string GetTrainMask();
-
- void SetWeightName(std::string name);
- std::string GetWeightName();
-
- void Update();
- void WeightsForAll(mitk::DataCollection::Pointer train, mitk::DataCollection::Pointer test);
- void SetModalities(std::vector<std::string> modalities);
- std::vector<std::string> GetModalities();
-
- void Predict();
-
- private:
- DataCollection::Pointer m_Collection;
- MatrixType m_Weights;
- std::string m_TestMask;
- std::string m_TrainMask;
- std::string m_WeightName;
- std::vector<std::string> m_Modalities;
-
- std::string m_WeightFileName;
- }; // class LRDensityEstimation
-} //namespace mitk
-
-#endif
diff --git a/Modules/Classification/CLImportanceWeighting/include/mitkLinkModels.h b/Modules/Classification/CLImportanceWeighting/include/mitkLinkModels.h
deleted file mode 100644
index 036fb105ac..0000000000
--- a/Modules/Classification/CLImportanceWeighting/include/mitkLinkModels.h
+++ /dev/null
@@ -1,41 +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.
-
-============================================================================*/
-
-#ifndef mitkLinkModels_h
-#define mitkLinkModels_h
-
-#include <MitkCLImportanceWeightingExports.h>
-
-namespace mitk
-{
- class MITKCLIMPORTANCEWEIGHTING_EXPORT AbstractLinkingFunction
- {
- public:
- virtual double Link(double mu) = 0;
- virtual double DLink(double mu) = 0;
- virtual double InverseLink(double eta) = 0;
- };
-
- class MITKCLIMPORTANCEWEIGHTING_EXPORT LogItLinking : AbstractLinkingFunction
- {
- public:
- LogItLinking();
- double Link(double mu) override;
- double DLink(double mu) override;
- double InverseLink(double eta) override;
- private:
- double lowerBound;
- double upperBound;
- };
-}
-
-#endif
diff --git a/Modules/Classification/CLImportanceWeighting/src/mitkDistModels.cpp b/Modules/Classification/CLImportanceWeighting/src/mitkDistModels.cpp
deleted file mode 100644
index a6b0748a23..0000000000
--- a/Modules/Classification/CLImportanceWeighting/src/mitkDistModels.cpp
+++ /dev/null
@@ -1,29 +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 <mitkDistModels.h>
-#include <cmath>
-
-double mitk::DistSimpleBinominal::Init(double y)
-{
- return ((y + 0.5) / (2));
-}
-
-double mitk::DistSimpleBinominal::Devariation(double mu, double y)
-{
- return 2 * (y * std::log(y) / mu + (1 - y) * std::log(1 - y) / (1 - mu));
-}
-
-double mitk::DistSimpleBinominal::SqrtVariance(double mu)
-{
- return std::sqrt(mu) * std::sqrt(1 - mu);
-}
diff --git a/Modules/Classification/CLImportanceWeighting/src/mitkGeneralizedLinearModel.cpp b/Modules/Classification/CLImportanceWeighting/src/mitkGeneralizedLinearModel.cpp
deleted file mode 100644
index f97cd28264..0000000000
--- a/Modules/Classification/CLImportanceWeighting/src/mitkGeneralizedLinearModel.cpp
+++ /dev/null
@@ -1,279 +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 <mitkGeneralizedLinearModel.h>
-
-#include <mitkDistModels.h>
-#include <mitkLinkModels.h>
-
-#include <v3p_netlib.h>
-#include <vnl/algo/vnl_qr.h>
-#include <mitkLogMacros.h>
-#include <algorithm>
-#include <limits>
-
-static void _UpdateXMatrix(const vnl_matrix<double> &xData, bool addConstant, v3p_netlib_doublereal *x);
-static void _UpdatePermXMatrix(const vnl_matrix<double> &xData, bool addConstant, const vnl_vector<unsigned int> &permutation, vnl_matrix<double> &x);
-static void _InitMuEta(mitk::DistSimpleBinominal *dist, mitk::LogItLinking *link, const vnl_vector<double> &yData, vnl_vector<double> &mu, vnl_vector<double> &eta);
-static void _FinalizeBVector(vnl_vector<double> &b, vnl_vector<unsigned int> &perm, int cols);
-
-
-double mitk::GeneralizedLinearModel::Predict( const vnl_vector<double> &c)
-{
- LogItLinking link;
- double mu = 0;
- int cols = m_B.size();
- for (int i = 0; i < cols; ++i)
- {
- if (!m_AddConstantColumn)
- mu += c(i)* m_B(i);
- else if ( i == 0)
- mu += 1* m_B(i);
- else
- mu += c(i-1)*m_B(i);
- }
- return link.InverseLink(mu);
-}
-
-vnl_vector<double> mitk::GeneralizedLinearModel::Predict(const vnl_matrix<double> &x)
-{
- LogItLinking link;
- vnl_vector<double> mu(x.rows());
- int cols = m_B.size();
- for (unsigned int r = 0 ; r < mu.size(); ++r)
- {
- mu(r) = 0;
- for (int c = 0; c < cols; ++c)
- {
- if (!m_AddConstantColumn)
- mu(r) += x(r,c)*m_B(c);
- else if ( c == 0)
- mu(r) += m_B(c);
- else
- mu(r) += x(r,c-1)*m_B(c);
- }
- mu(r) = link.InverseLink(mu(r));
- }
- return mu;
-}
-
-vnl_vector<double> mitk::GeneralizedLinearModel::B()
-{
- return m_B;
-}
-
-vnl_vector<double> mitk::GeneralizedLinearModel::ExpMu(const vnl_matrix<double> &x)
-{
- LogItLinking link;
- vnl_vector<double> mu(x.rows());
- int cols = m_B.size();
- for (unsigned int r = 0 ; r < mu.size(); ++r)
- {
- mu(r) = 0;
- for (int c = 0; c < cols; ++c)
- {
- if (!m_AddConstantColumn)
- mu(r) += x(r,c)*m_B(c);
- else if ( c == 0)
- mu(r) += m_B(c);
- else
- mu(r) += x(r,c-1)*m_B(c);
- }
- mu(r) = exp(-mu(r));
- }
- return mu;
-}
-
-mitk::GeneralizedLinearModel::GeneralizedLinearModel(const vnl_matrix<double> &xData, const vnl_vector<double> &yData, bool addConstantColumn) :
- m_AddConstantColumn(addConstantColumn)
-{
- EstimatePermutation(xData);
-
- DistSimpleBinominal dist;
- LogItLinking link;
- vnl_matrix<double> x;
- int rows = xData.rows();
- int cols = m_Permutation.size();
- vnl_vector<double> mu(rows);
- vnl_vector<double> eta(rows);
- vnl_vector<double> weightedY(rows);
- vnl_matrix<double> weightedX(rows, cols);
- vnl_vector<double> oldB(cols);
-
- _UpdatePermXMatrix(xData, m_AddConstantColumn, m_Permutation, x);
- _InitMuEta(&dist, &link, yData, mu, eta);
-
- int iter = 0;
- int iterLimit = 100;
- double sqrtEps = sqrt(std::numeric_limits<double>::epsilon());
- double convertCriterion =1e-6;
-
- m_B.set_size(m_Permutation.size());
- m_B.fill(0);
-
- while (iter <= iterLimit)
- {
- ++iter;
-
- oldB = m_B;
- // Do Row-wise operation. No Vector operation at this point.
- for (int r = 0; r<rows; ++r)
- {
- double deta = link.DLink(mu(r));
- double zBuffer = eta(r) + (yData(r) - mu(r))*deta;
- double sqrtWeight = 1 / (std::abs(deta) * dist.SqrtVariance(mu(r)));
-
- weightedY(r) = zBuffer * sqrtWeight;
- for (int c=0; c<cols; ++c)
- {
- weightedX(r,c) = x(r,c) * sqrtWeight;
- }
- }
- vnl_qr<double> qr(weightedX);
- m_B = qr.solve(weightedY);
- eta = x * m_B;
- for (int r = 0; r < rows; ++r)
- {
- mu(r) = link.InverseLink(eta(r));
- }
-
- bool stayInLoop = false;
- for(int c= 0; c < cols; ++c)
- {
- stayInLoop |= std::abs( m_B(c) - oldB(c)) > convertCriterion * std::max(sqrtEps, std::abs(oldB(c)));
- }
- if (!stayInLoop)
- break;
- }
- _FinalizeBVector(m_B, m_Permutation, xData.cols());
-}
-
-void mitk::GeneralizedLinearModel::EstimatePermutation(const vnl_matrix<double> &xData)
-{
- v3p_netlib_integer rows = xData.rows();
- v3p_netlib_integer cols = xData.cols();
-
- if (m_AddConstantColumn)
- ++cols;
-
- v3p_netlib_doublereal *x = new v3p_netlib_doublereal[rows* cols];
- _UpdateXMatrix(xData, m_AddConstantColumn, x);
- v3p_netlib_doublereal *qraux = new v3p_netlib_doublereal[cols];
- v3p_netlib_integer *jpvt = new v3p_netlib_integer[cols];
- std::fill_n(jpvt,cols,0);
- v3p_netlib_doublereal *work = new v3p_netlib_doublereal[cols];
- std::fill_n(work,cols,0);
- v3p_netlib_integer job = 16;
-
- // Make a call to Lapack-DQRDC which does QR with permutation
- // Permutation is saved in JPVT.
- v3p_netlib_dqrdc_(x, &rows, &rows, &cols, qraux, jpvt, work, &job);
-
- double limit = std::abs(x[0]) * std::max(cols, rows) * std::numeric_limits<double>::epsilon();
- // Calculate the rank of the matrix
- int m_Rank = 0;
- for (int i = 0; i <cols; ++i)
- {
- m_Rank += (std::abs(x[i*rows + i]) > limit) ? 1 : 0;
- }
- // Create a permutation vector
- m_Permutation.set_size(m_Rank);
- for (int i = 0; i < m_Rank; ++i)
- {
- m_Permutation(i) = jpvt[i]-1;
- }
-
- delete[] x;
- delete[] qraux;
- delete[] jpvt;
- delete[] work;
-}
-
-// Copy a vnl-matrix to an c-array with row-wise representation.
-// Adds a constant column if required.
-static void _UpdateXMatrix(const vnl_matrix<double> &xData, bool addConstant, v3p_netlib_doublereal *x)
-{
- v3p_netlib_integer rows = xData.rows();
- v3p_netlib_integer cols = xData.cols();
- if (addConstant)
- ++cols;
-
- for (int r=0; r < rows; ++r)
- {
- for (int c=0; c <cols; ++c)
- {
- if (!addConstant)
- {
- x[c*rows + r] = xData(r,c);
- } else if (c == 0)
- {
- x[c*rows + r] = 1.0;
- } else
- {
- x[c*rows + r] = xData(r, c-1);
- }
- }
- }
-}
-
-// Fills the value of the xData-matrix into the x-matrix. Adds a constant
-// column if required. Permutes the rows corresponding to the permutation vector.
-static void _UpdatePermXMatrix(const vnl_matrix<double> &xData, bool addConstant, const vnl_vector<unsigned int> &permutation, vnl_matrix<double> &x)
-{
- int rows = xData.rows();
- int cols = permutation.size();
- x.set_size(rows, cols);
- for (int r=0; r < rows; ++r)
- {
- for (int c=0; c<cols; ++c)
- {
- unsigned int newCol = permutation(c);
- if (!addConstant)
- {
- x(r, c) = xData(r,newCol);
- } else if (newCol == 0)
- {
- x(r, c) = 1.0;
- } else
- {
- x(r, c) = xData(r, newCol-1);
- }
- }
- }
-}
-
-// Initialize mu and eta by calling the corresponding
-// link and distribution functions on each row
-static void _InitMuEta(mitk::DistSimpleBinominal *dist, mitk::LogItLinking *link, const vnl_vector<double> &yData, vnl_vector<double> &mu, vnl_vector<double> &eta)
-{
- int rows = yData.size();
- mu.set_size(rows);
- eta.set_size(rows);
- for (int r = 0; r < rows; ++r)
- {
- mu(r) = dist->Init(yData(r));
- eta(r) = link->Link(mu(r));
- }
-}
-
-// Inverts the permutation on a given b-vector.
-// Necessary to get a b-vector that match the original data
-static void _FinalizeBVector(vnl_vector<double> &b, vnl_vector<unsigned int> &perm, int cols)
-{
- vnl_vector<double> tempB(cols+1);
- tempB.fill(0);
- for (unsigned int c = 0; c < perm.size(); ++c)
- {
- tempB(perm(c)) = b(c);
- }
- b = tempB;
-}
diff --git a/Modules/Classification/CLImportanceWeighting/src/mitkLRDensityEstimation.cpp b/Modules/Classification/CLImportanceWeighting/src/mitkLRDensityEstimation.cpp
deleted file mode 100644
index d95416526a..0000000000
--- a/Modules/Classification/CLImportanceWeighting/src/mitkLRDensityEstimation.cpp
+++ /dev/null
@@ -1,484 +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 <mitkLRDensityEstimation.h>
-
-#include <mitkDataCollectionImageIterator.h>
-#include <mitkDataCollectionSingleImageIterator.h>
-
-#include <itkImageRegionIterator.h>
-
-#include <mitkGeneralizedLinearModel.h>
-
-#include <mitkIOUtil.h>
-#include "itkImageFileWriter.h"
-
-static void EnsureDataImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target);
-//static std::size_t CountElementsInCollection(mitk::DataCollection::Pointer collection, std::string maskName);
-
-void
- mitk::LRDensityEstimation::SetCollection(DataCollection::Pointer data)
-{
- m_Collection = data;
-}
-
-mitk::DataCollection::Pointer
- mitk::LRDensityEstimation::GetCollection()
-{
- return m_Collection;
-}
-
-void
- mitk::LRDensityEstimation::SetTestMask(std::string name)
-{
- m_TestMask = name;
-}
-
-std::string
- mitk::LRDensityEstimation::GetTestMask()
-{
- return m_TestMask;
-}
-
-void
- mitk::LRDensityEstimation::SetTrainMask(std::string name)
-{
- m_TrainMask = name;
-}
-
-std::string
- mitk::LRDensityEstimation::GetTrainMask()
-{
- return m_TrainMask;
-}
-
-void
- mitk::LRDensityEstimation::SetWeightName(std::string name)
-{
- m_WeightName = name;
-}
-
-std::string
- mitk::LRDensityEstimation::GetWeightName()
-{
- return m_WeightName;
-}
-
-void
- mitk::LRDensityEstimation::Update()
-{
- typedef itk::Image<unsigned char, 3> MaskImageType;
- typedef itk::Image<double , 3> FeatureImageType;
-
- /// Ensuring that weighting image is present in data set.
- EnsureDataImageInCollection(m_Collection, m_TrainMask, m_WeightName);
-
- /// Create iterators for iterating over images
- DataCollectionSingleImageIterator<unsigned char, 3> train(m_Collection, m_TrainMask);
- DataCollectionSingleImageIterator<unsigned char, 3> test (m_Collection, m_TestMask);
- DataCollectionSingleImageIterator<double, 3> weight (m_Collection, m_WeightName);
- std::vector<DataCollectionSingleImageIterator<double, 3> > featureList;
- for (unsigned int i = 0; i < m_Modalities.size(); ++i)
- {
- DataCollectionSingleImageIterator<double, 3> iter(m_Collection, m_Modalities[i]);
- featureList.push_back(iter);
- }
-
- // Do for each image...
- // char buchstabe = 'A';
- while (!train.IsAtEnd())
- {
- itk::ImageRegionIterator<MaskImageType> trainIter(train.GetImage(), train.GetImage()->GetLargestPossibleRegion() );
- itk::ImageRegionIterator<MaskImageType> testIter(test.GetImage(), test.GetImage()->GetLargestPossibleRegion() );
-
- int trainElements = 0;
- int testElements = 0;
- while (!trainIter.IsAtEnd())
- {
- if (trainIter.Get() > 0)
- {
- ++trainElements;
- }
- if (testIter.Get() > 0)
- {
- ++testElements;
- }
- ++trainIter;
- ++testIter;
- }
- trainIter.GoToBegin();
- testIter.GoToBegin();
-
- std::vector<itk::ImageRegionIterator<FeatureImageType> > featureIter;
- for (unsigned int i = 0; i < featureList.size(); ++i)
- {
- itk::ImageRegionIterator<FeatureImageType> iter(featureList[i].GetImage(), featureList[i].GetImage()->GetLargestPossibleRegion() );
- featureIter.push_back(iter);
- }
-
- vnl_vector<double> label(trainElements + testElements);
- vnl_matrix<double> feature(trainElements + testElements, featureList.size() );
- vnl_matrix<double> trainFeature(trainElements, featureList.size() );
-
- int index = 0;
- int trainIndex = 0;
- while (!trainIter.IsAtEnd())
- {
- if (trainIter.Get() > 0)
- {
- label(index) = 1;
- for (unsigned int i = 0; i < featureIter.size(); ++i)
- {
- feature(index, i) = featureIter[i].Get();
- trainFeature(trainIndex, i) = featureIter[i].Get();
- }
- ++index;
- ++trainIndex;
- }
- if (testIter.Get() > 0)
- {
- label(index) = 0;
- for (unsigned int i = 0; i < featureIter.size(); ++i)
- {
- feature(index, i) = featureIter[i].Get();
- }
- ++index;
- }
-
- ++trainIter;
- ++testIter;
- for (unsigned int i = 0; i < featureIter.size(); ++i)
- {
- ++(featureIter[i]);
- }
- }
-
- mitk::GeneralizedLinearModel glm(feature, label);
- vnl_vector<double> weightVector = glm.ExpMu(trainFeature);
-
- itk::ImageRegionIterator<FeatureImageType> weightIter(weight.GetImage(), weight.GetImage()->GetLargestPossibleRegion() );
-
- trainIter.GoToBegin();
- index = 0;
- //double ratio = (trainElements * 1.0) / (testElements * 1.0);
- //ratio = 1.0 / weightVector.one_norm()*weightVector.size();
- while(!trainIter.IsAtEnd())
- {
- if (trainIter.Get() > 0)
- {
- weightIter.Set(weightVector(index) );
- ++index;
- }
- ++trainIter;
- ++weightIter;
- }
-
- //std::stringstream s;
- // s<<"d:/tmp/img/datei"<<buchstabe<<".nrrd";
- //std::string blub =s.str();
- //MITK_INFO << blub;
- //FeatureImageType::Pointer image = weight.GetImage();
- //typedef itk::ImageFileWriter< FeatureImageType > WriterType;
- //WriterType::Pointer writer = WriterType::New();
- //writer->SetFileName(blub);
- //writer->SetInput(image);
- //writer->Update();
- //++buchstabe;
-
- ++train;
- ++test;
- ++weight;
- for (unsigned int i = 0; i < featureList.size(); ++i)
- {
- ++(featureList[i]);
- }
- }
-}
-
-void
- mitk::LRDensityEstimation::SetModalities(std::vector<std::string> modalities)
-{
- m_Modalities = modalities;
-}
-
-std::vector<std::string>
- mitk::LRDensityEstimation::GetModalities()
-{
- return m_Modalities;
-}
-
-//static std::size_t CountElementsInCollection(mitk::DataCollection::Pointer collection, std::string maskName)
-//{
-// std::size_t count = 0;
-// mitk::DataCollectionImageIterator<unsigned char,3> iter(collection, maskName);
-// while (!iter.IsAtEnd())
-// {
-// if (iter.GetVoxel() > 0)
-// {
-// ++count;
-// }
-// ++iter;
-// }
-// return count;
-//}
-
-static void EnsureDataImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target)
-{
- typedef itk::Image<double, 3> FeatureImage;
- typedef itk::Image<unsigned char, 3> LabelImage;
-
- mitk::DataCollectionImageIterator<unsigned char , 3> iter( collection, origin);
- while (!iter.IsAtEnd())
- {
- ++iter;
- }
-
- if (collection->HasElement(origin))
- {
- LabelImage::Pointer originImage = dynamic_cast<LabelImage*>(collection->GetData(origin).GetPointer());
- if (!collection->HasElement(target) && originImage.IsNotNull())
- {
- MITK_INFO << "New image necessary";
- FeatureImage::Pointer image = FeatureImage::New();
- image->SetRegions(originImage->GetLargestPossibleRegion());
- image->SetSpacing(originImage->GetSpacing());
- image->SetOrigin(originImage->GetOrigin());
- image->SetDirection(originImage->GetDirection());
- image->Allocate();
-
- collection->AddData(dynamic_cast<itk::DataObject*>(image.GetPointer()),target,"");
- }
- }
- for (std::size_t i = 0; i < collection->Size();++i)
- {
- mitk::DataCollection* newCol = dynamic_cast<mitk::DataCollection*>(collection->GetData(i).GetPointer());
- if (newCol != nullptr)
- {
- EnsureDataImageInCollection(newCol, origin, target);
- }
- }
-}
-
-void
- mitk::LRDensityEstimation::WeightsForAll(mitk::DataCollection::Pointer train, mitk::DataCollection::Pointer test)
-{
- /// Ensuring that weighting image is present in data set.
- EnsureDataImageInCollection(train, m_TrainMask, m_WeightName);
-
- /// Create iterators for iterating over images
- DataCollectionImageIterator<unsigned char, 3> trainIter(train, m_TrainMask);
- DataCollectionImageIterator<unsigned char, 3> testIter (test, m_TestMask);
- DataCollectionImageIterator<double, 3> weightIter (train, m_WeightName);
- std::vector<DataCollectionImageIterator<double, 3> > trainFeatureList;
- std::vector<DataCollectionImageIterator<double, 3> > testFeatureList;
- for (unsigned int i = 0; i < m_Modalities.size(); ++i)
- {
- DataCollectionImageIterator<double, 3> iter(train, m_Modalities[i]);
- trainFeatureList.push_back(iter);
- DataCollectionImageIterator<double, 3> iter2(train, m_Modalities[i]);
- testFeatureList.push_back(iter2);
- }
-
- int trainElements = 0;
- int testElements = 0;
- while (!trainIter.IsAtEnd())
- {
- if (trainIter.GetVoxel() > 0)
- ++trainElements;
- ++trainIter;
- }
- while (!testIter.IsAtEnd() )
- {
- if (testIter.GetVoxel() > 0)
- ++testElements;
- ++testIter;
- }
- trainIter.ToBegin();
- testIter.ToBegin();
-
- vnl_vector<double> label(trainElements + testElements);
- vnl_matrix<double> feature(trainElements + testElements, trainFeatureList.size() );
- vnl_matrix<double> trainFeature(trainElements, trainFeatureList.size() );
-
- int trainIndex = 0;
- int testIndex = 0;
- while (!trainIter.IsAtEnd())
- {
- if (trainIter.GetVoxel() > 0)
- {
- label(trainIndex) = 1;
- for (unsigned int i = 0; i < trainFeatureList.size(); ++i)
- {
- feature(trainIndex, i) = trainFeatureList[i].GetVoxel();
- trainFeature(trainIndex, i) = trainFeatureList[i].GetVoxel();
- }
-
- ++trainIndex;
- }
-
- ++trainIter;
- for (unsigned int i = 0; i < trainFeatureList.size(); ++i)
- {
- ++(trainFeatureList[i]);
- }
- }
-
- while (!testIter.IsAtEnd())
- {
- if (testIter.GetVoxel() > 0)
- {
- label(trainIndex) = 1;
- for (unsigned int i = 0; i < testFeatureList.size(); ++i)
- {
- feature(trainIndex+testIndex, i) = testFeatureList[i].GetVoxel();
- }
- ++testIndex;
- }
-
- ++testIter;
- for (unsigned int i = 0; i < testFeatureList.size(); ++i)
- {
- ++(testFeatureList[i]);
- }
- }
-
- mitk::GeneralizedLinearModel glm(feature, label);
- vnl_vector<double> weightVector = glm.ExpMu(trainFeature);
-
- trainIter.ToBegin();
- int index = 0;
- while (!trainIter.IsAtEnd())
- {
- if (trainIter.GetVoxel() > 0)
- {
- weightIter.SetVoxel(weightVector(index));
- ++index;
- }
- ++trainIter;
- ++weightIter;
- }
-}
-
-void mitk::LRDensityEstimation::Predict()
-{
- typedef itk::Image<unsigned char, 3> MaskImageType;
- typedef itk::Image<double , 3> FeatureImageType;
-
- /// Ensuring that weighting image is present in data set.
- EnsureDataImageInCollection(m_Collection, m_TrainMask, m_WeightName);
-
- /// Create iterators for iterating over images
- DataCollectionSingleImageIterator<unsigned char, 3> train(m_Collection, m_TrainMask);
- DataCollectionSingleImageIterator<unsigned char, 3> test (m_Collection, m_TestMask);
- DataCollectionSingleImageIterator<double, 3> weight (m_Collection, m_WeightName);
- std::vector<DataCollectionSingleImageIterator<double, 3> > featureList;
- for (unsigned int i = 0; i < m_Modalities.size(); ++i)
- {
- DataCollectionSingleImageIterator<double, 3> iter(m_Collection, m_Modalities[i]);
- featureList.push_back(iter);
- }
-
- while (!train.IsAtEnd())
- {
- itk::ImageRegionIterator<MaskImageType> trainIter(train.GetImage(), train.GetImage()->GetLargestPossibleRegion() );
- itk::ImageRegionIterator<MaskImageType> testIter(test.GetImage(), test.GetImage()->GetLargestPossibleRegion() );
-
- int trainElements = 0;
- int testElements = 0;
- while (!trainIter.IsAtEnd())
- {
- if (trainIter.Get() > 0)
- {
- ++trainElements;
- }
- if (testIter.Get() > 0)
- {
- ++testElements;
- }
- ++trainIter;
- ++testIter;
- }
- trainIter.GoToBegin();
- testIter.GoToBegin();
-
- std::vector<itk::ImageRegionIterator<FeatureImageType> > featureIter;
- for (unsigned int i = 0; i < featureList.size(); ++i)
- {
- itk::ImageRegionIterator<FeatureImageType> iter(featureList[i].GetImage(), featureList[i].GetImage()->GetLargestPossibleRegion() );
- featureIter.push_back(iter);
- }
-
- vnl_vector<double> label(trainElements + testElements);
- vnl_matrix<double> feature(trainElements + testElements, featureList.size() );
- vnl_matrix<double> trainFeature(trainElements, featureList.size() );
-
- int index = 0;
- int trainIndex = 0;
- while (!trainIter.IsAtEnd())
- {
- if (trainIter.Get() > 0)
- {
- label(index) = 1;
- for (unsigned int i = 0; i < featureIter.size(); ++i)
- {
- feature(index, i) = featureIter[i].Get();
- trainFeature(trainIndex, i) = featureIter[i].Get();
- }
- ++index;
- ++trainIndex;
- }
- if (testIter.Get() > 0)
- {
- label(index) = 0;
- for (unsigned int i = 0; i < featureIter.size(); ++i)
- {
- feature(index, i) = featureIter[i].Get();
- }
- ++index;
- }
-
- ++trainIter;
- ++testIter;
- for (unsigned int i = 0; i < featureIter.size(); ++i)
- {
- ++(featureIter[i]);
- }
- }
-
- mitk::GeneralizedLinearModel glm(feature, label);
- vnl_vector<double> weightVector = glm.Predict(trainFeature);
-
- itk::ImageRegionIterator<FeatureImageType> weightIter(weight.GetImage(), weight.GetImage()->GetLargestPossibleRegion() );
-
- trainIter.GoToBegin();
- index = 0;
-
- while(!trainIter.IsAtEnd())
- {
- if (trainIter.Get() > 0)
- {
- weightIter.Set(weightVector(index) );
- ++index;
- }
- ++trainIter;
- ++weightIter;
- }
-
- ++train;
- ++test;
- ++weight;
- for (unsigned int i = 0; i < featureList.size(); ++i)
- {
- ++(featureList[i]);
- }
- }
-}
diff --git a/Modules/Classification/CLImportanceWeighting/src/mitkLinkModels.cpp b/Modules/Classification/CLImportanceWeighting/src/mitkLinkModels.cpp
deleted file mode 100644
index 2532f51e91..0000000000
--- a/Modules/Classification/CLImportanceWeighting/src/mitkLinkModels.cpp
+++ /dev/null
@@ -1,52 +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 <mitkLinkModels.h>
-#include <cmath>
-#include <limits>
-
-mitk::LogItLinking::LogItLinking()
-{
- lowerBound = std::log( std::numeric_limits<double>::epsilon());
- upperBound = -lowerBound;
-}
-
-double mitk::LogItLinking::Link(double mu)
-{
- return std::log(mu / (1 - mu));
-}
-
-double mitk::LogItLinking::DLink(double mu)
-{
- return 1 / (mu * (1 - mu));
-}
-
-double mitk::LogItLinking::InverseLink(double eta)
-{
- double result;
- if (eta < lowerBound)
- {
- result = 1 / (1 + std::exp(-lowerBound));
- }
- else if (eta > upperBound)
- {
- result = 1 / (1 + std::exp(-upperBound));
- }
- else
- {
- result = (1 / (1 + std::exp(-eta)));
- }
- if (result <0 ) result = 0;
- if (result > 1) result = 1;
-
- return result;
-}
diff --git a/Modules/Classification/CLImportanceWeighting/test/CMakeLists.txt b/Modules/Classification/CLImportanceWeighting/test/CMakeLists.txt
deleted file mode 100644
index 153cd81e2e..0000000000
--- a/Modules/Classification/CLImportanceWeighting/test/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-MITK_CREATE_MODULE_TESTS()
diff --git a/Modules/Classification/CLImportanceWeighting/test/files.cmake b/Modules/Classification/CLImportanceWeighting/test/files.cmake
deleted file mode 100644
index 6467b84c57..0000000000
--- a/Modules/Classification/CLImportanceWeighting/test/files.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-set(MODULE_TESTS
- #mitkSmoothedClassProbabilitesTest.cpp
-)
diff --git a/Modules/Classification/CLLibSVM/CMakeLists.txt b/Modules/Classification/CLLibSVM/CMakeLists.txt
deleted file mode 100644
index ba57c7e952..0000000000
--- a/Modules/Classification/CLLibSVM/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-MITK_CREATE_MODULE(
- DEPENDS MitkCLCore MitkCLUtilities
- PACKAGE_DEPENDS
- #DEPENDS MitkClassificationCore MitkClassificationUtilities
-)
-
-add_subdirectory(test)
diff --git a/Modules/Classification/CLLibSVM/files.cmake b/Modules/Classification/CLLibSVM/files.cmake
deleted file mode 100644
index 289b6dcbe7..0000000000
--- a/Modules/Classification/CLLibSVM/files.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
-
-set(CPP_FILES
- svm.cpp
- mitkLibSVMClassifier.cpp
-)
-
-set( TOOL_FILES
-)
-
diff --git a/Modules/Classification/CLLibSVM/include/mitkLibSVMClassifier.h b/Modules/Classification/CLLibSVM/include/mitkLibSVMClassifier.h
deleted file mode 100644
index 80f067680c..0000000000
--- a/Modules/Classification/CLLibSVM/include/mitkLibSVMClassifier.h
+++ /dev/null
@@ -1,75 +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.
-
-============================================================================*/
-
-#ifndef mitkLibSVMClassifier_h
-#define mitkLibSVMClassifier_h
-
-#include <MitkCLLibSVMExports.h>
-
-#include <mitkAbstractClassifier.h>
-
-struct svm_parameter;
-struct svm_problem;
-struct svm_node;
-struct svm_model;
-
-namespace mitk
-{
- class MITKCLLIBSVM_EXPORT LibSVMClassifier : public AbstractClassifier
- {
- public:
-
- mitkClassMacro(LibSVMClassifier,AbstractClassifier);
-
- itkFactorylessNewMacro(Self);
-
- itkCloneMacro(Self);
-
- LibSVMClassifier();
- ~LibSVMClassifier() override;
-
- void Train(const Eigen::MatrixXd &X, const Eigen::MatrixXi &Y) override;
- Eigen::MatrixXi Predict(const Eigen::MatrixXd &X) override;
-
- bool SupportsPointWiseWeight() override{return true;}
- bool SupportsPointWiseProbability() override{return false;}
-
- void PrintParameter(std::ostream & str);
- void ConvertParameter();
-
- void SetSvmType(int val);
- void SetProbability(int val);
- void SetShrinking(int val);
- void SetNrWeight(int val);
- void SetNu(double val);
- void SetP(double val);
- void SetEps(double val);
- void SetC(double val);
- void SetCacheSize(double val);
- void SetKernelType(int val);
- void SetDegree(int val);
- void SetGamma(double val);
- void SetCoef0(double val);
-
- private:
-
- void ReadXValues(svm_problem * problem, svm_node** xSpace, const Eigen::MatrixXd &X);
- void ReadYValues(svm_problem * problem, const Eigen::MatrixXi &Y);
- void ReadWValues(svm_problem * problem);
-
- svm_model* m_Model;
- svm_parameter * m_Parameter;
-
- };
-}
-
-#endif
diff --git a/Modules/Classification/CLLibSVM/include/svm.h b/Modules/Classification/CLLibSVM/include/svm.h
deleted file mode 100644
index a5a0e0bfe5..0000000000
--- a/Modules/Classification/CLLibSVM/include/svm.h
+++ /dev/null
@@ -1,152 +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.
-
-============================================================================*/
-
-/*===================================================================
-
-Copyright (c) 2000-2014 Chih-Chung Chang and Chih-Jen Lin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-3. Neither name of copyright holders nor the names of its contributors
-may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-===================================================================*/
-
-#ifndef _LIBSVM_H
-#define _LIBSVM_H
-
-#define LIBSVM_VERSION 318
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int libsvm_version;
-
-struct svm_node
-{
- int index;
- double value;
-};
-
-struct svm_problem
-{
- int l;
- double *y;
- struct svm_node **x;
- double *W; /* instance weight */
-};
-
-enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR }; /* svm_type */
-enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED }; /* kernel_type */
-
-struct svm_parameter
-{
- int svm_type;
- int kernel_type;
- int degree; /* for poly */
- double gamma; /* for poly/rbf/sigmoid */
- double coef0; /* for poly/sigmoid */
-
- /* these are for training only */
- double cache_size; /* in MB */
- double eps; /* stopping criteria */
- double C; /* for C_SVC, EPSILON_SVR and NU_SVR */
- int nr_weight; /* for C_SVC */
- int *weight_label; /* for C_SVC */
- double* weight; /* for C_SVC */
- double nu; /* for NU_SVC, ONE_CLASS, and NU_SVR */
- double p; /* for EPSILON_SVR */
- int shrinking; /* use the shrinking heuristics */
- int probability; /* do probability estimates */
-};
-
-//
-// svm_model
-//
-struct svm_model
-{
- struct svm_parameter param; /* parameter */
- int nr_class; /* number of classes, = 2 in regression/one class svm */
- int l; /* total #SV */
- struct svm_node **SV; /* SVs (SV[l]) */
- double **sv_coef; /* coefficients for SVs in decision functions (sv_coef[k-1][l]) */
- double *rho; /* constants in decision functions (rho[k*(k-1)/2]) */
- double *probA; /* pariwise probability information */
- double *probB;
- int *sv_indices; /* sv_indices[0,...,nSV-1] are values in [1,...,num_traning_data] to indicate SVs in the training set */
-
- /* for classification only */
-
- int *label; /* label of each class (label[k]) */
- int *nSV; /* number of SVs for each class (nSV[k]) */
- /* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
- /* XXX */
- int free_sv; /* 1 if svm_model is created by svm_load_model*/
- /* 0 if svm_model is created by svm_train */
-};
-
-struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);
-void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter *param, int nr_fold, double *target);
-
-int svm_save_model(const char *model_file_name, const struct svm_model *model);
-struct svm_model *svm_load_model(const char *model_file_name);
-
-int svm_get_svm_type(const struct svm_model *model);
-int svm_get_nr_class(const struct svm_model *model);
-void svm_get_labels(const struct svm_model *model, int *label);
-void svm_get_sv_indices(const struct svm_model *model, int *sv_indices);
-int svm_get_nr_sv(const struct svm_model *model);
-double svm_get_svr_probability(const struct svm_model *model);
-
-double svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values);
-double svm_predict(const struct svm_model *model, const struct svm_node *x);
-double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);
-
-void svm_free_model_content(struct svm_model *model_ptr);
-void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);
-void svm_destroy_param(struct svm_parameter *param);
-
-const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param);
-int svm_check_probability_model(const struct svm_model *model);
-
-void svm_set_print_string_function(void (*print_func)(const char *));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LIBSVM_H */
diff --git a/Modules/Classification/CLLibSVM/licence/COPYRIGHT b/Modules/Classification/CLLibSVM/licence/COPYRIGHT
deleted file mode 100644
index 5fe2f2229a..0000000000
--- a/Modules/Classification/CLLibSVM/licence/COPYRIGHT
+++ /dev/null
@@ -1,31 +0,0 @@
-
-Copyright (c) 2000-2014 Chih-Chung Chang and Chih-Jen Lin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-3. Neither name of copyright holders nor the names of its contributors
-may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Modules/Classification/CLLibSVM/licence/FAQ.html b/Modules/Classification/CLLibSVM/licence/FAQ.html
deleted file mode 100644
index 7bb380a6c2..0000000000
--- a/Modules/Classification/CLLibSVM/licence/FAQ.html
+++ /dev/null
@@ -1,2070 +0,0 @@
-
-
-<html>
-<head>
-<title>LIBSVM FAQ</title>
-</head>
-<body bgcolor="#ffffcc">
-
-<a name="_TOP"><b><h1><a
-href=http://www.csie.ntu.edu.tw/~cjlin/libsvm>LIBSVM</a> FAQ </h1></b></a>
-<b>last modified : </b>
-四, 20 3月 2014 16:05:14 GMT
-<class="categories">
-<li><a
-href="#_TOP">All Questions</a>(81)</li>
-<ul><b>
-<li><a
-href="#/Q01:_Some_sample_uses_of_libsvm">Q01:_Some_sample_uses_of_libsvm</a>(2)</li>
-<li><a
-href="#/Q02:_Installation_and_running_the_program">Q02:_Installation_and_running_the_program</a>(13)</li>
-<li><a
-href="#/Q03:_Data_preparation">Q03:_Data_preparation</a>(7)</li>
-<li><a
-href="#/Q04:_Training_and_prediction">Q04:_Training_and_prediction</a>(28)</li>
-<li><a
-href="#/Q05:_Cross_validation_and_parameter_selection">Q05:_Cross_validation_and_parameter_selection</a>(8)</li>
-<li><a
-href="#/Q06:_Probability_outputs">Q06:_Probability_outputs</a>(3)</li>
-<li><a
-href="#/Q07:_Graphic_interface">Q07:_Graphic_interface</a>(3)</li>
-<li><a
-href="#/Q08:_Java_version_of_libsvm">Q08:_Java_version_of_libsvm</a>(4)</li>
-<li><a
-href="#/Q09:_Python_interface">Q09:_Python_interface</a>(1)</li>
-<li><a
-href="#/Q10:_MATLAB_interface">Q10:_MATLAB_interface</a>(12)</li>
-</b></ul>
-</li>
-
-<ul><ul class="headlines">
-<li class="headlines_item"><a href="#faq101">Some courses which have used libsvm as a tool</a></li>
-<li class="headlines_item"><a href="#faq102">Some applications/tools which have used libsvm </a></li>
-<li class="headlines_item"><a href="#f201">Where can I find documents/videos of libsvm ?</a></li>
-<li class="headlines_item"><a href="#f202">Where are change log and earlier versions?</a></li>
-<li class="headlines_item"><a href="#f203">How to cite LIBSVM?</a></li>
-<li class="headlines_item"><a href="#f204">I would like to use libsvm in my software. Is there any license problem?</a></li>
-<li class="headlines_item"><a href="#f205">Is there a repository of additional tools based on libsvm?</a></li>
-<li class="headlines_item"><a href="#f206">On unix machines, I got "error in loading shared libraries" or "cannot open shared object file." What happened ? </a></li>
-<li class="headlines_item"><a href="#f207">I have modified the source and would like to build the graphic interface "svm-toy" on MS windows. How should I do it ?</a></li>
-<li class="headlines_item"><a href="#f208">I am an MS windows user but why only one (svm-toy) of those precompiled .exe actually runs ? </a></li>
-<li class="headlines_item"><a href="#f209">What is the difference between "." and "*" outputed during training? </a></li>
-<li class="headlines_item"><a href="#f210">Why occasionally the program (including MATLAB or other interfaces) crashes and gives a segmentation fault?</a></li>
-<li class="headlines_item"><a href="#f211">How to build a dynamic library (.dll file) on MS windows?</a></li>
-<li class="headlines_item"><a href="#f212">On some systems (e.g., Ubuntu), compiling LIBSVM gives many warning messages. Is this a problem and how to disable the warning message?</a></li>
-<li class="headlines_item"><a href="#f213">In LIBSVM, why you don't use certain C/C++ library functions to make the code shorter?</a></li>
-<li class="headlines_item"><a href="#f301">Why sometimes not all attributes of a data appear in the training/model files ?</a></li>
-<li class="headlines_item"><a href="#f302">What if my data are non-numerical ?</a></li>
-<li class="headlines_item"><a href="#f303">Why do you consider sparse format ? Will the training of dense data be much slower ?</a></li>
-<li class="headlines_item"><a href="#f304">Why sometimes the last line of my data is not read by svm-train?</a></li>
-<li class="headlines_item"><a href="#f305">Is there a program to check if my data are in the correct format?</a></li>
-<li class="headlines_item"><a href="#f306">May I put comments in data files?</a></li>
-<li class="headlines_item"><a href="#f307">How to convert other data formats to LIBSVM format?</a></li>
-<li class="headlines_item"><a href="#f401">The output of training C-SVM is like the following. What do they mean?</a></li>
-<li class="headlines_item"><a href="#f402">Can you explain more about the model file?</a></li>
-<li class="headlines_item"><a href="#f403">Should I use float or double to store numbers in the cache ?</a></li>
-<li class="headlines_item"><a href="#f405">Does libsvm have special treatments for linear SVM?</a></li>
-<li class="headlines_item"><a href="#f406">The number of free support vectors is large. What should I do?</a></li>
-<li class="headlines_item"><a href="#f407">Should I scale training and testing data in a similar way?</a></li>
-<li class="headlines_item"><a href="#f408">Does it make a big difference if I scale each attribute to [0,1] instead of [-1,1]?</a></li>
-<li class="headlines_item"><a href="#f409">The prediction rate is low. How could I improve it?</a></li>
-<li class="headlines_item"><a href="#f410">My data are unbalanced. Could libsvm handle such problems?</a></li>
-<li class="headlines_item"><a href="#f411">What is the difference between nu-SVC and C-SVC?</a></li>
-<li class="headlines_item"><a href="#f412">The program keeps running (without showing any output). What should I do?</a></li>
-<li class="headlines_item"><a href="#f413">The program keeps running (with output, i.e. many dots). What should I do?</a></li>
-<li class="headlines_item"><a href="#f414">The training time is too long. What should I do?</a></li>
-<li class="headlines_item"><a href="#f4141">Does shrinking always help?</a></li>
-<li class="headlines_item"><a href="#f415">How do I get the decision value(s)?</a></li>
-<li class="headlines_item"><a href="#f4151">How do I get the distance between a point and the hyperplane?</a></li>
-<li class="headlines_item"><a href="#f416">On 32-bit machines, if I use a large cache (i.e. large -m) on a linux machine, why sometimes I get "segmentation fault ?"</a></li>
-<li class="headlines_item"><a href="#f417">How do I disable screen output of svm-train?</a></li>
-<li class="headlines_item"><a href="#f418">I would like to use my own kernel. Any example? In svm.cpp, there are two subroutines for kernel evaluations: k_function() and kernel_function(). Which one should I modify ?</a></li>
-<li class="headlines_item"><a href="#f419">What method does libsvm use for multi-class SVM ? Why don't you use the "1-against-the rest" method?</a></li>
-<li class="headlines_item"><a href="#f422">I would like to solve L2-loss SVM (i.e., error term is quadratic). How should I modify the code ?</a></li>
-<li class="headlines_item"><a href="#f425">In one-class SVM, parameter nu should be an upper bound of the training error rate. Why sometimes I get a training error rate bigger than nu?</a></li>
-<li class="headlines_item"><a href="#f427">Why the code gives NaN (not a number) results?</a></li>
-<li class="headlines_item"><a href="#f430">Why the sign of predicted labels and decision values are sometimes reversed?</a></li>
-<li class="headlines_item"><a href="#f431">I don't know class labels of test data. What should I put in the first column of the test file?</a></li>
-<li class="headlines_item"><a href="#f432">How can I use OpenMP to parallelize LIBSVM on a multicore/shared-memory computer?</a></li>
-<li class="headlines_item"><a href="#f433">How could I know which training instances are support vectors?</a></li>
-<li class="headlines_item"><a href="#f434">Why sv_indices (indices of support vectors) are not stored in the saved model file?</a></li>
-<li class="headlines_item"><a href="#f501">After doing cross validation, why there is no model file outputted ?</a></li>
-<li class="headlines_item"><a href="#f502">Why my cross-validation results are different from those in the Practical Guide?</a></li>
-<li class="headlines_item"><a href="#f503">On some systems CV accuracy is the same in several runs. How could I use different data partitions? In other words, how do I set random seed in LIBSVM?</a></li>
-<li class="headlines_item"><a href="#f504">Why on windows sometimes grid.py fails?</a></li>
-<li class="headlines_item"><a href="#f505">Why grid.py/easy.py sometimes generates the following warning message?</a></li>
-<li class="headlines_item"><a href="#f506">How do I choose the kernel?</a></li>
-<li class="headlines_item"><a href="#f507">How does LIBSVM perform parameter selection for multi-class problems? </a></li>
-<li class="headlines_item"><a href="#f508">How do I choose parameters for one-class SVM as training data are in only one class?</a></li>
-<li class="headlines_item"><a href="#f425">Why training a probability model (i.e., -b 1) takes a longer time?</a></li>
-<li class="headlines_item"><a href="#f426">Why using the -b option does not give me better accuracy?</a></li>
-<li class="headlines_item"><a href="#f427">Why using svm-predict -b 0 and -b 1 gives different accuracy values?</a></li>
-<li class="headlines_item"><a href="#f501">How can I save images drawn by svm-toy?</a></li>
-<li class="headlines_item"><a href="#f502">I press the "load" button to load data points but why svm-toy does not draw them ?</a></li>
-<li class="headlines_item"><a href="#f503">I would like svm-toy to handle more than three classes of data, what should I do ?</a></li>
-<li class="headlines_item"><a href="#f601">What is the difference between Java version and C++ version of libsvm?</a></li>
-<li class="headlines_item"><a href="#f602">Is the Java version significantly slower than the C++ version?</a></li>
-<li class="headlines_item"><a href="#f603">While training I get the following error message: java.lang.OutOfMemoryError. What is wrong?</a></li>
-<li class="headlines_item"><a href="#f604">Why you have the main source file svm.m4 and then transform it to svm.java?</a></li>
-<li class="headlines_item"><a href="#f704">Except the python-C++ interface provided, could I use Jython to call libsvm ?</a></li>
-<li class="headlines_item"><a href="#f801">I compile the MATLAB interface without problem, but why errors occur while running it?</a></li>
-<li class="headlines_item"><a href="#f8011">On 64bit Windows I compile the MATLAB interface without problem, but why errors occur while running it?</a></li>
-<li class="headlines_item"><a href="#f802">Does the MATLAB interface provide a function to do scaling?</a></li>
-<li class="headlines_item"><a href="#f803">How could I use MATLAB interface for parameter selection?</a></li>
-<li class="headlines_item"><a href="#f8031">I use MATLAB parallel programming toolbox on a multi-core environment for parameter selection. Why the program is even slower?</a></li>
-<li class="headlines_item"><a href="#f8032">How do I use LIBSVM with OpenMP under MATLAB?</a></li>
-<li class="headlines_item"><a href="#f804">How could I generate the primal variable w of linear SVM?</a></li>
-<li class="headlines_item"><a href="#f805">Is there an OCTAVE interface for libsvm?</a></li>
-<li class="headlines_item"><a href="#f806">How to handle the name conflict between svmtrain in the libsvm matlab interface and that in MATLAB bioinformatics toolbox?</a></li>
-<li class="headlines_item"><a href="#f807">On Windows I got an error message "Invalid MEX-file: Specific module not found" when running the pre-built MATLAB interface in the windows sub-directory. What should I do?</a></li>
-<li class="headlines_item"><a href="#f808">LIBSVM supports 1-vs-1 multi-class classification. If instead I would like to use 1-vs-rest, how to implement it using MATLAB interface?</a></li>
-<li class="headlines_item"><a href="#f809">I tried to install matlab interface on mac, but failed. What should I do?</a></li>
-</ul></ul>
-
-
-<hr size="5" noshade />
-<p/>
-
-<a name="/Q01:_Some_sample_uses_of_libsvm"></a>
-<a name="faq101"><b>Q: Some courses which have used libsvm as a tool</b></a>
-<br/>
-<ul>
-<li><a href=http://lmb.informatik.uni-freiburg.de/lectures/svm_seminar/>Institute for Computer Science,
-Faculty of Applied Science, University of Freiburg, Germany
-</a>
-<li> <a href=http://www.cs.vu.nl/~elena/ml.html>
-Division of Mathematics and Computer Science.
-Faculteit der Exacte Wetenschappen
-Vrije Universiteit, The Netherlands. </a>
-<li>
-<a href=http://www.cae.wisc.edu/~ece539/matlab/>
-Electrical and Computer Engineering Department,
-University of Wisconsin-Madison
-</a>
-<li>
-<a href=http://www.hpl.hp.com/personal/Carl_Staelin/cs236601/project.html>
-Technion (Israel Institute of Technology), Israel.
-<li>
-<a href=http://www.cise.ufl.edu/~fu/learn.html>
-Computer and Information Sciences Dept., University of Florida</a>
-<li>
-<a href=http://www.uonbi.ac.ke/acad_depts/ics/course_material/machine_learning/ML_and_DM_Resources.html>
-The Institute of Computer Science,
-University of Nairobi, Kenya.</a>
-<li>
-<a href=http://cerium.raunvis.hi.is/~tpr/courseware/svm/hugbunadur.html>
-Applied Mathematics and Computer Science, University of Iceland.
-<li>
-<a href=http://chicago05.mlss.cc/tiki/tiki-read_article.php?articleId=2>
-SVM tutorial in machine learning
-summer school, University of Chicago, 2005.
-</a>
-</ul>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q01:_Some_sample_uses_of_libsvm"></a>
-<a name="faq102"><b>Q: Some applications/tools which have used libsvm </b></a>
-<br/>
-(and maybe liblinear).
-<ul>
-<li>
-<a href=http://people.csail.mit.edu/jjl/libpmk/>LIBPMK: A Pyramid Match Toolkit</a>
-</li>
-<li><a href=http://maltparser.org/>Maltparser</a>:
-a system for data-driven dependency parsing
-</li>
-<li>
-<a href=http://www.pymvpa.org/>PyMVPA: python tool for classifying neuroimages</a>
-</li>
-<li>
-<a href=http://solpro.proteomics.ics.uci.edu/>
-SOLpro: protein solubility predictor
-</a>
-</li>
-<li>
-<a href=http://bdval.campagnelab.org>
-BDVal</a>: biomarker discovery in high-throughput datasets.
-</li>
-<li><a href=http://johel.m.free.fr/demo_045.htm>
-Realtime object recognition</a>
-</li>
-<li><a href=http://scikit-learn.sourceforge.net/>
-scikits.learn: machine learning in Python</a>
-</li>
-</ul>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f201"><b>Q: Where can I find documents/videos of libsvm ?</b></a>
-<br/>
-<p>
-
-<ul>
-<li>
-Official implementation document:
-<br>
-C.-C. Chang and
-C.-J. Lin.
-LIBSVM
-: a library for support vector machines.
-ACM Transactions on Intelligent
-Systems and Technology, 2:27:1--27:27, 2011.
-<a href="http://www.csie.ntu.edu.tw/~cjlin/papers/libsvm.pdf">pdf</a>, <a href=http://www.csie.ntu.edu.tw/~cjlin/papers/libsvm.ps.gz>ps.gz</a>,
-<a href=http://portal.acm.org/citation.cfm?id=1961199&CFID=29950432&CFTOKEN=30974232>ACM digital lib</a>.
-
-
-<li> Instructions for using LIBSVM are in the README files in the main directory and some sub-directories.
-<br>
-README in the main directory: details all options, data format, and library calls.
-<br>
-tools/README: parameter selection and other tools
-<li>
-A guide for beginners:
-<br>
-C.-W. Hsu, C.-C. Chang, and
-C.-J. Lin.
-<A HREF="http://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf">
-A practical guide to support vector classification
-</A>
-<li> An <a href=http://www.youtube.com/watch?v=gePWtNAQcK8>introductory video</a>
-for windows users.
-
-</ul>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f202"><b>Q: Where are change log and earlier versions?</b></a>
-<br/>
-<p>See <a href="http://www.csie.ntu.edu.tw/~cjlin/libsvm/log">the change log</a>.
-
-<p> You can download earlier versions
-<a href="http://www.csie.ntu.edu.tw/~cjlin/libsvm/oldfiles">here</a>.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f203"><b>Q: How to cite LIBSVM?</b></a>
-<br/>
-<p>
-Please cite the following paper:
-<p>
-Chih-Chung Chang and Chih-Jen Lin, LIBSVM
-: a library for support vector machines.
-ACM Transactions on Intelligent Systems and Technology, 2:27:1--27:27, 2011.
-Software available at http://www.csie.ntu.edu.tw/~cjlin/libsvm
-<p>
-The bibtex format is
-<pre>
-@article{CC01a,
- author = {Chang, Chih-Chung and Lin, Chih-Jen},
- title = {{LIBSVM}: A library for support vector machines},
- journal = {ACM Transactions on Intelligent Systems and Technology},
- volume = {2},
- issue = {3},
- year = {2011},
- pages = {27:1--27:27},
- note = {Software available at \url{http://www.csie.ntu.edu.tw/~cjlin/libsvm}}
-}
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f204"><b>Q: I would like to use libsvm in my software. Is there any license problem?</b></a>
-<br/>
-<p>
-The libsvm license ("the modified BSD license")
-is compatible with many
-free software licenses such as GPL. Hence, it is very easy to
-use libsvm in your software.
-Please check the COPYRIGHT file in detail. Basically
-you need to
-<ol>
-<li>
-Clearly indicate that LIBSVM is used.
-</li>
-<li>
-Retain the LIBSVM COPYRIGHT file in your software.
-</li>
-</ol>
-It can also be used in commercial products.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f205"><b>Q: Is there a repository of additional tools based on libsvm?</b></a>
-<br/>
-<p>
-Yes, see <a href="http://www.csie.ntu.edu.tw/~cjlin/libsvmtools">libsvm
-tools</a>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f206"><b>Q: On unix machines, I got "error in loading shared libraries" or "cannot open shared object file." What happened ? </b></a>
-<br/>
-
-<p>
-This usually happens if you compile the code
-on one machine and run it on another which has incompatible
-libraries.
-Try to recompile the program on that machine or use static linking.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f207"><b>Q: I have modified the source and would like to build the graphic interface "svm-toy" on MS windows. How should I do it ?</b></a>
-<br/>
-
-<p>
-Build it as a project by choosing "Win32 Project."
-On the other hand, for "svm-train" and "svm-predict"
-you want to choose "Win32 Console Project."
-After libsvm 2.5, you can also use the file Makefile.win.
-See details in README.
-
-
-<p>
-If you are not using Makefile.win and see the following
-link error
-<pre>
-LIBCMTD.lib(wwincrt0.obj) : error LNK2001: unresolved external symbol
-_wWinMain@16
-</pre>
-you may have selected a wrong project type.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f208"><b>Q: I am an MS windows user but why only one (svm-toy) of those precompiled .exe actually runs ? </b></a>
-<br/>
-
-<p>
-You need to open a command window
-and type svmtrain.exe to see all options.
-Some examples are in README file.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f209"><b>Q: What is the difference between "." and "*" outputed during training? </b></a>
-<br/>
-
-<p>
-"." means every 1,000 iterations (or every #data
-iterations is your #data is less than 1,000).
-"*" means that after iterations of using
-a smaller shrunk problem,
-we reset to use the whole set. See the
-<a href=../papers/libsvm.pdf>implementation document</a> for details.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f210"><b>Q: Why occasionally the program (including MATLAB or other interfaces) crashes and gives a segmentation fault?</b></a>
-<br/>
-
-<p>
-Very likely the program consumes too much memory than what the
-operating system can provide. Try a smaller data and see if the
-program still crashes.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f211"><b>Q: How to build a dynamic library (.dll file) on MS windows?</b></a>
-<br/>
-<p>
-
-The easiest way is to use Makefile.win.
-See details in README.
-
-Alternatively, you can use Visual C++. Here is
-the example using Visual Studio .Net 2008:
-<ol>
-<li>Create a Win32 empty DLL project and set (in Project->$Project_Name
-Properties...->Configuration) to "Release."
- About how to create a new dynamic link library, please refer to
-<a href=http://msdn2.microsoft.com/en-us/library/ms235636(VS.80).aspx>http://msdn2.microsoft.com/en-us/library/ms235636(VS.80).aspx</a>
-
-<li> Add svm.cpp, svm.h to your project.
-<li> Add __WIN32__ and _CRT_SECURE_NO_DEPRECATE to Preprocessor definitions (in
-Project->$Project_Name Properties...->C/C++->Preprocessor)
-<li> Set Create/Use Precompiled Header to Not Using Precompiled Headers
-(in Project->$Project_Name Properties...->C/C++->Precompiled Headers)
-<li> Set the path for the Modulation Definition File svm.def (in
-Project->$Project_Name Properties...->Linker->input
-<li> Build the DLL.
-<li> Rename the dll file to libsvm.dll and move it to the correct path.
-</ol>
-
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f212"><b>Q: On some systems (e.g., Ubuntu), compiling LIBSVM gives many warning messages. Is this a problem and how to disable the warning message?</b></a>
-<br/>
-
-<p>
-If you are using a version before 3.18, probably you see
-a warning message like
-<pre>
-svm.cpp:2730: warning: ignoring return value of int fscanf(FILE*, const char*, ...), declared with attribute warn_unused_result
-</pre>
-This is not a problem; see <a href=https://wiki.ubuntu.com/CompilerFlags#-D_FORTIFY_SOURCE=2>this page</a> for more
-details of ubuntu systems.
-To disable the warning message you can replace
-<pre>
-CFLAGS = -Wall -Wconversion -O3 -fPIC
-</pre>
-with
-<pre>
-CFLAGS = -Wall -Wconversion -O3 -fPIC -U_FORTIFY_SOURCE
-</pre>
-in Makefile.
-<p> After version 3.18, we have a better setting so that such warning messages do not appear.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q02:_Installation_and_running_the_program"></a>
-<a name="f213"><b>Q: In LIBSVM, why you don't use certain C/C++ library functions to make the code shorter?</b></a>
-<br/>
-
-<p>
-For portability, we use only features defined in ISO C89. Note that features in ISO C99 may not be available everywhere.
-Even the newest gcc lacks some features in C99 (see <a href=http://gcc.gnu.org/c99status.html>http://gcc.gnu.org/c99status.html</a> for details).
-If the situation changes in the future,
-we might consider using these newer features.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q03:_Data_preparation"></a>
-<a name="f301"><b>Q: Why sometimes not all attributes of a data appear in the training/model files ?</b></a>
-<br/>
-<p>
-libsvm uses the so called "sparse" format where zero
-values do not need to be stored. Hence a data with attributes
-<pre>
-1 0 2 0
-</pre>
-is represented as
-<pre>
-1:1 3:2
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q03:_Data_preparation"></a>
-<a name="f302"><b>Q: What if my data are non-numerical ?</b></a>
-<br/>
-<p>
-Currently libsvm supports only numerical data.
-You may have to change non-numerical data to
-numerical. For example, you can use several
-binary attributes to represent a categorical
-attribute.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q03:_Data_preparation"></a>
-<a name="f303"><b>Q: Why do you consider sparse format ? Will the training of dense data be much slower ?</b></a>
-<br/>
-<p>
-This is a controversial issue. The kernel
-evaluation (i.e. inner product) of sparse vectors is slower
-so the total training time can be at least twice or three times
-of that using the dense format.
-However, we cannot support only dense format as then we CANNOT
-handle extremely sparse cases. Simplicity of the code is another
-concern. Right now we decide to support
-the sparse format only.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q03:_Data_preparation"></a>
-<a name="f304"><b>Q: Why sometimes the last line of my data is not read by svm-train?</b></a>
-<br/>
-
-<p>
-We assume that you have '\n' in the end of
-each line. So please press enter in the end
-of your last line.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q03:_Data_preparation"></a>
-<a name="f305"><b>Q: Is there a program to check if my data are in the correct format?</b></a>
-<br/>
-
-<p>
-The svm-train program in libsvm conducts only a simple check of the input data. To do a
-detailed check, after libsvm 2.85, you can use the python script tools/checkdata.py. See tools/README for details.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q03:_Data_preparation"></a>
-<a name="f306"><b>Q: May I put comments in data files?</b></a>
-<br/>
-
-<p>
-We don't officially support this. But, currently LIBSVM
-is able to process data in the following
-format:
-<pre>
-1 1:2 2:1 # your comments
-</pre>
-Note that the character ":" should not appear in your
-comments.
-<!--
-No, for simplicity we don't support that.
-However, you can easily preprocess your data before
-using libsvm. For example,
-if you have the following data
-<pre>
-test.txt
-1 1:2 2:1 # proten A
-</pre>
-then on unix machines you can do
-<pre>
-cut -d '#' -f 1 < test.txt > test.features
-cut -d '#' -f 2 < test.txt > test.comments
-svm-predict test.feature train.model test.predicts
-paste -d '#' test.predicts test.comments | sed 's/#/ #/' > test.results
-</pre>
--->
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q03:_Data_preparation"></a>
-<a name="f307"><b>Q: How to convert other data formats to LIBSVM format?</b></a>
-<br/>
-
-<p>
-It depends on your data format. A simple way is to use
-libsvmwrite in the libsvm matlab/octave interface.
-
-Take a CSV (comma-separated values) file
-in UCI machine learning repository as an example.
-We download <a href=http://archive.ics.uci.edu/ml/machine-learning-databases/spect/SPECTF.train>SPECTF.train</a>.
-Labels are in the first column. The following steps produce
-a file in the libsvm format.
-<pre>
-matlab> SPECTF = csvread('SPECTF.train'); % read a csv file
-matlab> labels = SPECTF(:, 1); % labels from the 1st column
-matlab> features = SPECTF(:, 2:end);
-matlab> features_sparse = sparse(features); % features must be in a sparse matrix
-matlab> libsvmwrite('SPECTFlibsvm.train', labels, features_sparse);
-</pre>
-The tranformed data are stored in SPECTFlibsvm.train.
-
-<p>
-Alternatively, you can use <a href="./faqfiles/convert.c">convert.c</a>
-to convert CSV format to libsvm format.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f401"><b>Q: The output of training C-SVM is like the following. What do they mean?</b></a>
-<br/>
-<br>optimization finished, #iter = 219
-<br>nu = 0.431030
-<br>obj = -100.877286, rho = 0.424632
-<br>nSV = 132, nBSV = 107
-<br>Total nSV = 132
-<p>
-obj is the optimal objective value of the dual SVM problem.
-rho is the bias term in the decision function
-sgn(w^Tx - rho).
-nSV and nBSV are number of support vectors and bounded support
-vectors (i.e., alpha_i = C). nu-svm is a somewhat equivalent
-form of C-SVM where C is replaced by nu. nu simply shows the
-corresponding parameter. More details are in
-<a href="http://www.csie.ntu.edu.tw/~cjlin/papers/libsvm.pdf">
-libsvm document</a>.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f402"><b>Q: Can you explain more about the model file?</b></a>
-<br/>
-
-<p>
-In the model file, after parameters and other informations such as labels , each line represents a support vector.
-Support vectors are listed in the order of "labels" shown earlier.
-(i.e., those from the first class in the "labels" list are
-grouped first, and so on.)
-If k is the total number of classes,
-in front of a support vector in class j, there are
-k-1 coefficients
-y*alpha where alpha are dual solution of the
-following two class problems:
-<br>
-1 vs j, 2 vs j, ..., j-1 vs j, j vs j+1, j vs j+2, ..., j vs k
-<br>
-and y=1 in first j-1 coefficients, y=-1 in the remaining
-k-j coefficients.
-
-For example, if there are 4 classes, the file looks like:
-
-<pre>
-+-+-+-+--------------------+
-|1|1|1| |
-|v|v|v| SVs from class 1 |
-|2|3|4| |
-+-+-+-+--------------------+
-|1|2|2| |
-|v|v|v| SVs from class 2 |
-|2|3|4| |
-+-+-+-+--------------------+
-|1|2|3| |
-|v|v|v| SVs from class 3 |
-|3|3|4| |
-+-+-+-+--------------------+
-|1|2|3| |
-|v|v|v| SVs from class 4 |
-|4|4|4| |
-+-+-+-+--------------------+
-</pre>
-See also
-<a href="#f804"> an illustration using
-MATLAB/OCTAVE.</a>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f403"><b>Q: Should I use float or double to store numbers in the cache ?</b></a>
-<br/>
-
-<p>
-We have float as the default as you can store more numbers
-in the cache.
-In general this is good enough but for few difficult
-cases (e.g. C very very large) where solutions are huge
-numbers, it might be possible that the numerical precision is not
-enough using only float.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f405"><b>Q: Does libsvm have special treatments for linear SVM?</b></a>
-<br/>
-
-<p>
-
-No, libsvm solves linear/nonlinear SVMs by the
-same way.
-Some tricks may save training/testing time if the
-linear kernel is used,
-so libsvm is <b>NOT</b> particularly efficient for linear SVM,
-especially when
-C is large and
-the number of data is much larger
-than the number of attributes.
-You can either
-<ul>
-<li>
-Use small C only. We have shown in the following paper
-that after C is larger than a certain threshold,
-the decision function is the same.
-<p>
-<a href="http://guppy.mpe.nus.edu.sg/~mpessk/">S. S. Keerthi</a>
-and
-<B>C.-J. Lin</B>.
-<A HREF="papers/limit.pdf">
-Asymptotic behaviors of support vector machines with
-Gaussian kernel
-</A>
-.
-<I><A HREF="http://mitpress.mit.edu/journal-home.tcl?issn=08997667">Neural Computation</A></I>, 15(2003), 1667-1689.
-
-
-<li>
-Check <a href=http://www.csie.ntu.edu.tw/~cjlin/liblinear>liblinear</a>,
-which is designed for large-scale linear classification.
-</ul>
-
-<p> Please also see our <a href=../papers/guide/guide.pdf>SVM guide</a>
-on the discussion of using RBF and linear
-kernels.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f406"><b>Q: The number of free support vectors is large. What should I do?</b></a>
-<br/>
- <p>
-This usually happens when the data are overfitted.
-If attributes of your data are in large ranges,
-try to scale them. Then the region
-of appropriate parameters may be larger.
-Note that there is a scale program
-in libsvm.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f407"><b>Q: Should I scale training and testing data in a similar way?</b></a>
-<br/>
-<p>
-Yes, you can do the following:
-<pre>
-> svm-scale -s scaling_parameters train_data > scaled_train_data
-> svm-scale -r scaling_parameters test_data > scaled_test_data
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f408"><b>Q: Does it make a big difference if I scale each attribute to [0,1] instead of [-1,1]?</b></a>
-<br/>
-
-<p>
-For the linear scaling method, if the RBF kernel is
-used and parameter selection is conducted, there
-is no difference. Assume Mi and mi are
-respectively the maximal and minimal values of the
-ith attribute. Scaling to [0,1] means
-<pre>
- x'=(x-mi)/(Mi-mi)
-</pre>
-For [-1,1],
-<pre>
- x''=2(x-mi)/(Mi-mi)-1.
-</pre>
-In the RBF kernel,
-<pre>
- x'-y'=(x-y)/(Mi-mi), x''-y''=2(x-y)/(Mi-mi).
-</pre>
-Hence, using (C,g) on the [0,1]-scaled data is the
-same as (C,g/2) on the [-1,1]-scaled data.
-
-<p> Though the performance is the same, the computational
-time may be different. For data with many zero entries,
-[0,1]-scaling keeps the sparsity of input data and hence
-may save the time.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f409"><b>Q: The prediction rate is low. How could I improve it?</b></a>
-<br/>
-<p>
-Try to use the model selection tool grid.py in the tools
-directory find
-out good parameters. To see the importance of model selection,
-please
-see our guide for beginners:
-<A HREF="http://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf">
-A practical guide to support vector
-classification
-</A>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f410"><b>Q: My data are unbalanced. Could libsvm handle such problems?</b></a>
-<br/>
-<p>
-Yes, there is a -wi options. For example, if you use
-<pre>
-> svm-train -s 0 -c 10 -w1 1 -w-1 5 data_file
-</pre>
-<p>
-the penalty for class "-1" is larger.
-Note that this -w option is for C-SVC only.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f411"><b>Q: What is the difference between nu-SVC and C-SVC?</b></a>
-<br/>
-<p>
-Basically they are the same thing but with different
-parameters. The range of C is from zero to infinity
-but nu is always between [0,1]. A nice property
-of nu is that it is related to the ratio of
-support vectors and the ratio of the training
-error.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f412"><b>Q: The program keeps running (without showing any output). What should I do?</b></a>
-<br/>
-<p>
-You may want to check your data. Each training/testing
-data must be in one line. It cannot be separated.
-In addition, you have to remove empty lines.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f413"><b>Q: The program keeps running (with output, i.e. many dots). What should I do?</b></a>
-<br/>
-<p>
-In theory libsvm guarantees to converge.
-Therefore, this means you are
-handling ill-conditioned situations
-(e.g. too large/small parameters) so numerical
-difficulties occur.
-<p>
-You may get better numerical stability by replacing
-<pre>
-typedef float Qfloat;
-</pre>
-in svm.cpp with
-<pre>
-typedef double Qfloat;
-</pre>
-That is, elements in the kernel cache are stored
-in double instead of single. However, this means fewer elements
-can be put in the kernel cache.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f414"><b>Q: The training time is too long. What should I do?</b></a>
-<br/>
-<p>
-For large problems, please specify enough cache size (i.e.,
--m).
-Slow convergence may happen for some difficult cases (e.g. -c is large).
-You can try to use a looser stopping tolerance with -e.
-If that still doesn't work, you may train only a subset of the data.
-You can use the program subset.py in the directory "tools"
-to obtain a random subset.
-
-<p>
-If you have extremely large data and face this difficulty, please
-contact us. We will be happy to discuss possible solutions.
-
-<p> When using large -e, you may want to check if -h 0 (no shrinking) or -h 1 (shrinking) is faster.
-See a related question below.
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f4141"><b>Q: Does shrinking always help?</b></a>
-<br/>
-<p>
-If the number of iterations is high, then shrinking
-often helps.
-However, if the number of iterations is small
-(e.g., you specify a large -e), then
-probably using -h 0 (no shrinking) is better.
-See the
-<a href=../papers/libsvm.pdf>implementation document</a> for details.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f415"><b>Q: How do I get the decision value(s)?</b></a>
-<br/>
-<p>
-We print out decision values for regression. For classification,
-we solve several binary SVMs for multi-class cases. You
-can obtain values by easily calling the subroutine
-svm_predict_values. Their corresponding labels
-can be obtained from svm_get_labels.
-Details are in
-README of libsvm package.
-
-<p>
-If you are using MATLAB/OCTAVE interface, svmpredict can directly
-give you decision values. Please see matlab/README for details.
-
-<p>
-We do not recommend the following. But if you would
-like to get values for
-TWO-class classification with labels +1 and -1
-(note: +1 and -1 but not things like 5 and 10)
-in the easiest way, simply add
-<pre>
- printf("%f\n", dec_values[0]*model->label[0]);
-</pre>
-after the line
-<pre>
- svm_predict_values(model, x, dec_values);
-</pre>
-of the file svm.cpp.
-Positive (negative)
-decision values correspond to data predicted as +1 (-1).
-
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f4151"><b>Q: How do I get the distance between a point and the hyperplane?</b></a>
-<br/>
-<p>
-The distance is |decision_value| / |w|.
-We have |w|^2 = w^Tw = alpha^T Q alpha = 2*(dual_obj + sum alpha_i).
-Thus in svm.cpp please find the place
-where we calculate the dual objective value
-(i.e., the subroutine Solve())
-and add a statement to print w^Tw.
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f416"><b>Q: On 32-bit machines, if I use a large cache (i.e. large -m) on a linux machine, why sometimes I get "segmentation fault ?"</b></a>
-<br/>
-<p>
-
-On 32-bit machines, the maximum addressable
-memory is 4GB. The Linux kernel uses 3:1
-split which means user space is 3G and
-kernel space is 1G. Although there are
-3G user space, the maximum dynamic allocation
-memory is 2G. So, if you specify -m near 2G,
-the memory will be exhausted. And svm-train
-will fail when it asks more memory.
-For more details, please read
-<a href=http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&selm=3BA164F6.BAFA4FB%40daimi.au.dk>
-this article</a>.
-<p>
-The easiest solution is to switch to a
- 64-bit machine.
-Otherwise, there are two ways to solve this. If your
-machine supports Intel's PAE (Physical Address
-Extension), you can turn on the option HIGHMEM64G
-in Linux kernel which uses 4G:4G split for
-kernel and user space. If you don't, you can
-try a software `tub' which can eliminate the 2G
-boundary for dynamic allocated memory. The `tub'
-is available at
-<a href=http://www.bitwagon.com/tub.html>http://www.bitwagon.com/tub.html</a>.
-
-
-<!--
-
-This may happen only when the cache is large, but each cached row is
-not large enough. <b>Note:</b> This problem is specific to
-gnu C library which is used in linux.
-The solution is as follows:
-
-<p>
-In our program we have malloc() which uses two methods
-to allocate memory from kernel. One is
-sbrk() and another is mmap(). sbrk is faster, but mmap
-has a larger address
-space. So malloc uses mmap only if the wanted memory size is larger
-than some threshold (default 128k).
-In the case where each row is not large enough (#elements < 128k/sizeof(float)) but we need a large cache ,
-the address space for sbrk can be exhausted. The solution is to
-lower the threshold to force malloc to use mmap
-and increase the maximum number of chunks to allocate
-with mmap.
-
-<p>
-Therefore, in the main program (i.e. svm-train.c) you want
-to have
-<pre>
- #include &lt;malloc.h&gt;
-</pre>
-and then in main():
-<pre>
- mallopt(M_MMAP_THRESHOLD, 32768);
- mallopt(M_MMAP_MAX,1000000);
-</pre>
-You can also set the environment variables instead
-of writing them in the program:
-<pre>
-$ M_MMAP_MAX=1000000 M_MMAP_THRESHOLD=32768 ./svm-train .....
-</pre>
-More information can be found by
-<pre>
-$ info libc "Malloc Tunable Parameters"
-</pre>
--->
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f417"><b>Q: How do I disable screen output of svm-train?</b></a>
-<br/>
-<p>
-For commend-line users, use the -q option:
-<pre>
-> ./svm-train -q heart_scale
-</pre>
-<p>
-For library users, set the global variable
-<pre>
-extern void (*svm_print_string) (const char *);
-</pre>
-to specify the output format. You can disable the output by the following steps:
-<ol>
-<li>
-Declare a function to output nothing:
-<pre>
-void print_null(const char *s) {}
-</pre>
-</li>
-<li>
-Assign the output function of libsvm by
-<pre>
-svm_print_string = &print_null;
-</pre>
-</li>
-</ol>
-Finally, a way used in earlier libsvm
-is by updating svm.cpp from
-<pre>
-#if 1
-void info(const char *fmt,...)
-</pre>
-to
-<pre>
-#if 0
-void info(const char *fmt,...)
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f418"><b>Q: I would like to use my own kernel. Any example? In svm.cpp, there are two subroutines for kernel evaluations: k_function() and kernel_function(). Which one should I modify ?</b></a>
-<br/>
-<p>
-An example is "LIBSVM for string data" in LIBSVM Tools.
-<p>
-The reason why we have two functions is as follows.
-For the RBF kernel exp(-g |xi - xj|^2), if we calculate
-xi - xj first and then the norm square, there are 3n operations.
-Thus we consider exp(-g (|xi|^2 - 2dot(xi,xj) +|xj|^2))
-and by calculating all |xi|^2 in the beginning,
-the number of operations is reduced to 2n.
-This is for the training. For prediction we cannot
-do this so a regular subroutine using that 3n operations is
-needed.
-
-The easiest way to have your own kernel is
-to put the same code in these two
-subroutines by replacing any kernel.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f419"><b>Q: What method does libsvm use for multi-class SVM ? Why don't you use the "1-against-the rest" method?</b></a>
-<br/>
-<p>
-It is one-against-one. We chose it after doing the following
-comparison:
-C.-W. Hsu and C.-J. Lin.
-<A HREF="http://www.csie.ntu.edu.tw/~cjlin/papers/multisvm.pdf">
-A comparison of methods
-for multi-class support vector machines
-</A>,
-<I>IEEE Transactions on Neural Networks</A></I>, 13(2002), 415-425.
-
-<p>
-"1-against-the rest" is a good method whose performance
-is comparable to "1-against-1." We do the latter
-simply because its training time is shorter.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f422"><b>Q: I would like to solve L2-loss SVM (i.e., error term is quadratic). How should I modify the code ?</b></a>
-<br/>
-<p>
-It is extremely easy. Taking c-svc for example, to solve
-<p>
-min_w w^Tw/2 + C \sum max(0, 1- (y_i w^Tx_i+b))^2,
-<p>
-only two
-places of svm.cpp have to be changed.
-First, modify the following line of
-solve_c_svc from
-<pre>
- s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y,
- alpha, Cp, Cn, param->eps, si, param->shrinking);
-</pre>
-to
-<pre>
- s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y,
- alpha, INF, INF, param->eps, si, param->shrinking);
-</pre>
-Second, in the class of SVC_Q, declare C as
-a private variable:
-<pre>
- double C;
-</pre>
-In the constructor replace
-<pre>
- for(int i=0;i&lt;prob.l;i++)
- QD[i]= (Qfloat)(this->*kernel_function)(i,i);
-</pre>
-with
-<pre>
- this->C = param.C;
- for(int i=0;i&lt;prob.l;i++)
- QD[i]= (Qfloat)(this->*kernel_function)(i,i)+0.5/C;
-</pre>
-Then in the subroutine get_Q, after the for loop, add
-<pre>
- if(i >= start && i < len)
- data[i] += 0.5/C;
-</pre>
-
-<p>
-For one-class svm, the modification is exactly the same. For SVR, you don't need an if statement like the above. Instead, you only need a simple assignment:
-<pre>
- data[real_i] += 0.5/C;
-</pre>
-
-
-<p>
-For large linear L2-loss SVM, please use
-<a href=../liblinear>LIBLINEAR</a>.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f425"><b>Q: In one-class SVM, parameter nu should be an upper bound of the training error rate. Why sometimes I get a training error rate bigger than nu?</b></a>
-<br/>
-
-<p>
-At optimum, some training instances should satisfy
-w^Tx - rho = 0. However, numerically they may be slightly
-smaller than zero
-Then they are wrongly counted
-as training errors. You can use a smaller stopping tolerance
-(by the -e option) to make this problem less serious.
-
-<p>
-This issue <b>does not occur</b> for nu-SVC for
-two-class classification.
-We have that
-<ol>
-<li>nu is an upper bound on the ratio of training points
-on the wrong side of the hyperplane, and
-<li>therefore, nu is also an upper bound on the training error rate.
-</ol>
-Numerical issues occur in calculating the first case
-because some training points satisfying y(w^Tx + b) - rho = 0
-become negative.
-However, we have no numerical problems for the second case because
-we compare y(w^Tx + b) and 0 for counting training errors.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f427"><b>Q: Why the code gives NaN (not a number) results?</b></a>
-<br/>
-<p>
-This rarely happens, but few users reported the problem.
-It seems that their
-computers for training libsvm have the VPN client
-running. The VPN software has some bugs and causes this
-problem. Please try to close or disconnect the VPN client.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f430"><b>Q: Why the sign of predicted labels and decision values are sometimes reversed?</b></a>
-<br/>
-<p>
-
-This situation may occur <b>before version 3.17</b>.
-Nothing is wrong. Very likely you have two labels +1/-1 and the first instance in your data
-has -1. We give the following explanation.
-
-<p>
-Internally class labels are ordered by their first occurrence in the training set. For a k-class data, internally labels
-are 0, ..., k-1, and each two-class SVM considers pair
-(i, j) with i < j. Then class i is treated as positive (+1)
-and j as negative (-1).
-For example, if the data set has labels +5/+10 and +10 appears
-first, then internally the +5 versus +10 SVM problem
-has +10 as positive (+1) and +5 as negative (-1).
-
-<p>
-By this setting, if you have labels +1 and -1,
-it's possible that internally they correspond to -1 and +1,
-respectively. Some new users have been confused about
-this, so <b>after version 3.17</b>, if the data set has only
-two labels +1 and -1,
-internally we ensure +1 to be before -1. Then class +1
-is always treated as positive in the SVM problem.
-Note that this is for <b>two-class data only.</b>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f431"><b>Q: I don't know class labels of test data. What should I put in the first column of the test file?</b></a>
-<br/>
-<p>Any value is ok. In this situation, what you will use is the output file of svm-predict, which gives predicted class labels.
-
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f432"><b>Q: How can I use OpenMP to parallelize LIBSVM on a multicore/shared-memory computer?</b></a>
-<br/>
-
-<p>It is very easy if you are using GCC 4.2
-or after.
-
-<p> In Makefile, add -fopenmp to CFLAGS.
-
-<p> In class SVC_Q of svm.cpp, modify the for loop
-of get_Q to:
-<pre>
-#pragma omp parallel for private(j)
- for(j=start;j&lt;len;j++)
-</pre>
-<p> In the subroutine svm_predict_values of svm.cpp, add one line to the for loop:
-<pre>
-#pragma omp parallel for private(i)
- for(i=0;i&lt;l;i++)
- kvalue[i] = Kernel::k_function(x,model-&gt;SV[i],model-&gt;param);
-</pre>
-For regression, you need to modify
-class SVR_Q instead. The loop in svm_predict_values
-is also different because you need
-a reduction clause for the variable sum:
-<pre>
-#pragma omp parallel for private(i) reduction(+:sum)
- for(i=0;i&lt;model->l;i++)
- sum += sv_coef[i] * Kernel::k_function(x,model-&gt;SV[i],model-&gt;param);
-</pre>
-
-<p> Then rebuild the package. Kernel evaluations in training/testing will be parallelized. An example of running this modification on
-an 8-core machine using the data set
-<a href=../libsvmtools/datasets/binary/ijcnn1.bz2>ijcnn1</a>:
-
-<p> 8 cores:
-<pre>
-%setenv OMP_NUM_THREADS 8
-%time svm-train -c 16 -g 4 -m 400 ijcnn1
-27.1sec
-</pre>
-1 core:
-<pre>
-%setenv OMP_NUM_THREADS 1
-%time svm-train -c 16 -g 4 -m 400 ijcnn1
-79.8sec
-</pre>
-For this data, kernel evaluations take 80% of training time. In the above example, we assume you use csh. For bash, use
-<pre>
-export OMP_NUM_THREADS=8
-</pre>
-instead.
-
-<p> For Python interface, you need to add the -lgomp link option:
-<pre>
-$(CXX) -lgomp -shared -dynamiclib svm.o -o libsvm.so.$(SHVER)
-</pre>
-
-<p> For MS Windows, you need to add /openmp in CFLAGS of Makefile.win
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f433"><b>Q: How could I know which training instances are support vectors?</b></a>
-<br/>
-
-<p>
-It's very simple. Since version 3.13, you can use the function
-<pre>
-void svm_get_sv_indices(const struct svm_model *model, int *sv_indices)
-</pre>
-to get indices of support vectors. For example, in svm-train.c, after
-<pre>
- model = svm_train(&amp;prob, &amp;param);
-</pre>
-you can add
-<pre>
- int nr_sv = svm_get_nr_sv(model);
- int *sv_indices = Malloc(int, nr_sv);
- svm_get_sv_indices(model, sv_indices);
- for (int i=0; i&lt;nr_sv; i++)
- printf("instance %d is a support vector\n", sv_indices[i]);
-</pre>
-
-<p> If you use matlab interface, you can directly check
-<pre>
-model.sv_indices
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q04:_Training_and_prediction"></a>
-<a name="f434"><b>Q: Why sv_indices (indices of support vectors) are not stored in the saved model file?</b></a>
-<br/>
-
-<p>
-Although sv_indices is a member of the model structure
-to
-indicate support vectors in the training set,
-we do not store its contents in the model file.
-The model file is mainly used in the future for
-prediction, so it is basically <b>independent</b>
-from training data. Thus
-storing sv_indices is not necessary.
-Users should find support vectors right after
-the training process. See the previous FAQ.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f501"><b>Q: After doing cross validation, why there is no model file outputted ?</b></a>
-<br/>
-<p>
-Cross validation is used for selecting good parameters.
-After finding them, you want to re-train the whole
-data without the -v option.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f502"><b>Q: Why my cross-validation results are different from those in the Practical Guide?</b></a>
-<br/>
-<p>
-
-Due to random partitions of
-the data, on different systems CV accuracy values
-may be different.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f503"><b>Q: On some systems CV accuracy is the same in several runs. How could I use different data partitions? In other words, how do I set random seed in LIBSVM?</b></a>
-<br/>
-<p>
-If you use GNU C library,
-the default seed 1 is considered. Thus you always
-get the same result of running svm-train -v.
-To have different seeds, you can add the following code
-in svm-train.c:
-<pre>
-#include &lt;time.h&gt;
-</pre>
-and in the beginning of main(),
-<pre>
-srand(time(0));
-</pre>
-Alternatively, if you are not using GNU C library
-and would like to use a fixed seed, you can have
-<pre>
-srand(1);
-</pre>
-
-<p>
-For Java, the random number generator
-is initialized using the time information.
-So results of two CV runs are different.
-To fix the seed, after version 3.1 (released
-in mid 2011), you can add
-<pre>
-svm.rand.setSeed(0);
-</pre>
-in the main() function of svm_train.java.
-
-<p>
-If you use CV to select parameters, it is recommended to use identical folds
-under different parameters. In this case, you can consider fixing the seed.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f504"><b>Q: Why on windows sometimes grid.py fails?</b></a>
-<br/>
-<p>
-
-This problem shouldn't happen after version
-2.85. If you are using earlier versions,
-please download the latest one.
-
-<!--
-<p>
-If you are using earlier
-versions, the error message is probably
-<pre>
-Traceback (most recent call last):
- File "grid.py", line 349, in ?
- main()
- File "grid.py", line 344, in main
- redraw(db)
- File "grid.py", line 132, in redraw
- gnuplot.write("set term windows\n")
-IOError: [Errno 22] Invalid argument
-</pre>
-
-<p>Please try to close gnuplot windows and rerun.
-If the problem still occurs, comment the following
-two lines in grid.py by inserting "#" in the beginning:
-<pre>
- redraw(db)
- redraw(db,1)
-</pre>
-Then you get accuracy only but not cross validation contours.
--->
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f505"><b>Q: Why grid.py/easy.py sometimes generates the following warning message?</b></a>
-<br/>
-<pre>
-Warning: empty z range [62.5:62.5], adjusting to [61.875:63.125]
-Notice: cannot contour non grid data!
-</pre>
-<p>Nothing is wrong and please disregard the
-message. It is from gnuplot when drawing
-the contour.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f506"><b>Q: How do I choose the kernel?</b></a>
-<br/>
-
-<p>
-In general we suggest you to try the RBF kernel first.
-A recent result by Keerthi and Lin
-(<a href=http://www.csie.ntu.edu.tw/~cjlin/papers/limit.pdf>
-download paper here</a>)
-shows that if RBF is used with model selection,
-then there is no need to consider the linear kernel.
-The kernel matrix using sigmoid may not be positive definite
-and in general it's accuracy is not better than RBF.
-(see the paper by Lin and Lin
-(<a href=http://www.csie.ntu.edu.tw/~cjlin/papers/tanh.pdf>
-download paper here</a>).
-Polynomial kernels are ok but if a high degree is used,
-numerical difficulties tend to happen
-(thinking about dth power of (<1) goes to 0
-and (>1) goes to infinity).
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f507"><b>Q: How does LIBSVM perform parameter selection for multi-class problems? </b></a>
-<br/>
-
-<p>
-LIBSVM implements "one-against-one" multi-class method, so there are
-k(k-1)/2 binary models, where k is the number of classes.
-
-<p>
-We can consider two ways to conduct parameter selection.
-
-<ol>
-<li>
-For any two classes of data, a parameter selection procedure is conducted. Finally,
-each decision function has its own optimal parameters.
-</li>
-<li>
-The same parameters are used for all k(k-1)/2 binary classification problems.
-We select parameters that achieve the highest overall performance.
-</li>
-</ol>
-
-Each has its own advantages. A
-single parameter set may not be uniformly good for all k(k-1)/2 decision functions.
-However, as the overall accuracy is the final consideration, one parameter set
-for one decision function may lead to over-fitting. In the paper
-<p>
-Chen, Lin, and Sch&ouml;lkopf,
-<A HREF="../papers/nusvmtutorial.pdf">
-A tutorial on nu-support vector machines.
-</A>
-Applied Stochastic Models in Business and Industry, 21(2005), 111-136,
-
-<p>
-they have experimentally
-shown that the two methods give similar performance.
-Therefore, currently the parameter selection in LIBSVM
-takes the second approach by considering the same parameters for
-all k(k-1)/2 models.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q05:_Cross_validation_and_parameter_selection"></a>
-<a name="f508"><b>Q: How do I choose parameters for one-class SVM as training data are in only one class?</b></a>
-<br/>
-<p>
-You have pre-specified true positive rate in mind and then search for
-parameters which achieve similar cross-validation accuracy.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q06:_Probability_outputs"></a>
-<a name="f425"><b>Q: Why training a probability model (i.e., -b 1) takes a longer time?</b></a>
-<br/>
-<p>
-To construct this probability model, we internally conduct a
-cross validation, which is more time consuming than
-a regular training.
-Hence, in general you do parameter selection first without
--b 1. You only use -b 1 when good parameters have been
-selected. In other words, you avoid using -b 1 and -v
-together.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q06:_Probability_outputs"></a>
-<a name="f426"><b>Q: Why using the -b option does not give me better accuracy?</b></a>
-<br/>
-<p>
-There is absolutely no reason the probability outputs guarantee
-you better accuracy. The main purpose of this option is
-to provide you the probability estimates, but not to boost
-prediction accuracy. From our experience,
-after proper parameter selections, in general with
-and without -b have similar accuracy. Occasionally there
-are some differences.
-It is not recommended to compare the two under
-just a fixed parameter
-set as more differences will be observed.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q06:_Probability_outputs"></a>
-<a name="f427"><b>Q: Why using svm-predict -b 0 and -b 1 gives different accuracy values?</b></a>
-<br/>
-<p>
-Let's just consider two-class classification here. After probability information is obtained in training,
-we do not have
-<p>
-prob > = 0.5 if and only if decision value >= 0.
-<p>
-So predictions may be different with -b 0 and 1.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q07:_Graphic_interface"></a>
-<a name="f501"><b>Q: How can I save images drawn by svm-toy?</b></a>
-<br/>
-<p>
-For Microsoft windows, first press the "print screen" key on the keyboard.
-Open "Microsoft Paint"
-(included in Windows)
-and press "ctrl-v." Then you can clip
-the part of picture which you want.
-For X windows, you can
-use the program "xv" or "import" to grab the picture of the svm-toy window.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q07:_Graphic_interface"></a>
-<a name="f502"><b>Q: I press the "load" button to load data points but why svm-toy does not draw them ?</b></a>
-<br/>
-<p>
-The program svm-toy assumes both attributes (i.e. x-axis and y-axis
-values) are in (0,1). Hence you want to scale your
-data to between a small positive number and
-a number less than but very close to 1.
-Moreover, class labels must be 1, 2, or 3
-(not 1.0, 2.0 or anything else).
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q07:_Graphic_interface"></a>
-<a name="f503"><b>Q: I would like svm-toy to handle more than three classes of data, what should I do ?</b></a>
-<br/>
-<p>
-Taking windows/svm-toy.cpp as an example, you need to
-modify it and the difference
-from the original file is as the following: (for five classes of
-data)
-<pre>
-30,32c30
-< RGB(200,0,200),
-< RGB(0,160,0),
-< RGB(160,0,0)
----
-> RGB(200,0,200)
-39c37
-< HBRUSH brush1, brush2, brush3, brush4, brush5;
----
-> HBRUSH brush1, brush2, brush3;
-113,114d110
-< brush4 = CreateSolidBrush(colors[7]);
-< brush5 = CreateSolidBrush(colors[8]);
-155,157c151
-< else if(v==3) return brush3;
-< else if(v==4) return brush4;
-< else return brush5;
----
-> else return brush3;
-325d318
-< int colornum = 5;
-327c320
-< svm_node *x_space = new svm_node[colornum * prob.l];
----
-> svm_node *x_space = new svm_node[3 * prob.l];
-333,338c326,331
-< x_space[colornum * i].index = 1;
-< x_space[colornum * i].value = q->x;
-< x_space[colornum * i + 1].index = 2;
-< x_space[colornum * i + 1].value = q->y;
-< x_space[colornum * i + 2].index = -1;
-< prob.x[i] = &x_space[colornum * i];
----
-> x_space[3 * i].index = 1;
-> x_space[3 * i].value = q->x;
-> x_space[3 * i + 1].index = 2;
-> x_space[3 * i + 1].value = q->y;
-> x_space[3 * i + 2].index = -1;
-> prob.x[i] = &x_space[3 * i];
-397c390
-< if(current_value > 5) current_value = 1;
----
-> if(current_value > 3) current_value = 1;
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q08:_Java_version_of_libsvm"></a>
-<a name="f601"><b>Q: What is the difference between Java version and C++ version of libsvm?</b></a>
-<br/>
-<p>
-They are the same thing. We just rewrote the C++ code
-in Java.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q08:_Java_version_of_libsvm"></a>
-<a name="f602"><b>Q: Is the Java version significantly slower than the C++ version?</b></a>
-<br/>
-<p>
-This depends on the VM you used. We have seen good
-VM which leads the Java version to be quite competitive with
-the C++ code. (though still slower)
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q08:_Java_version_of_libsvm"></a>
-<a name="f603"><b>Q: While training I get the following error message: java.lang.OutOfMemoryError. What is wrong?</b></a>
-<br/>
-<p>
-You should try to increase the maximum Java heap size.
-For example,
-<pre>
-java -Xmx2048m -classpath libsvm.jar svm_train ...
-</pre>
-sets the maximum heap size to 2048M.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q08:_Java_version_of_libsvm"></a>
-<a name="f604"><b>Q: Why you have the main source file svm.m4 and then transform it to svm.java?</b></a>
-<br/>
-<p>
-Unlike C, Java does not have a preprocessor built-in.
-However, we need some macros (see first 3 lines of svm.m4).
-
-</ul>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q09:_Python_interface"></a>
-<a name="f704"><b>Q: Except the python-C++ interface provided, could I use Jython to call libsvm ?</b></a>
-<br/>
-<p> Yes, here are some examples:
-
-<pre>
-$ export CLASSPATH=$CLASSPATH:~/libsvm-2.91/java/libsvm.jar
-$ ./jython
-Jython 2.1a3 on java1.3.0 (JIT: jitc)
-Type "copyright", "credits" or "license" for more information.
->>> from libsvm import *
->>> dir()
-['__doc__', '__name__', 'svm', 'svm_model', 'svm_node', 'svm_parameter',
-'svm_problem']
->>> x1 = [svm_node(index=1,value=1)]
->>> x2 = [svm_node(index=1,value=-1)]
->>> param = svm_parameter(svm_type=0,kernel_type=2,gamma=1,cache_size=40,eps=0.001,C=1,nr_weight=0,shrinking=1)
->>> prob = svm_problem(l=2,y=[1,-1],x=[x1,x2])
->>> model = svm.svm_train(prob,param)
-*
-optimization finished, #iter = 1
-nu = 1.0
-obj = -1.018315639346838, rho = 0.0
-nSV = 2, nBSV = 2
-Total nSV = 2
->>> svm.svm_predict(model,x1)
-1.0
->>> svm.svm_predict(model,x2)
--1.0
->>> svm.svm_save_model("test.model",model)
-
-</pre>
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f801"><b>Q: I compile the MATLAB interface without problem, but why errors occur while running it?</b></a>
-<br/>
-<p>
-Your compiler version may not be supported/compatible for MATLAB.
-Please check <a href=http://www.mathworks.com/support/compilers/current_release>this MATLAB page</a> first and then specify the version
-number. For example, if g++ X.Y is supported, replace
-<pre>
-CXX = g++
-</pre>
-in the Makefile with
-<pre>
-CXX = g++-X.Y
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f8011"><b>Q: On 64bit Windows I compile the MATLAB interface without problem, but why errors occur while running it?</b></a>
-<br/>
-<p>
-
-
-Please make sure that you use
-the -largeArrayDims option in make.m. For example,
-<pre>
-mex -largeArrayDims -O -c svm.cpp
-</pre>
-
-Moreover, if you use Microsoft Visual Studio,
-probabally it is not properly installed.
-See the explanation
-<a href=http://www.mathworks.com/support/compilers/current_release/win64.html#n7>here</a>.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f802"><b>Q: Does the MATLAB interface provide a function to do scaling?</b></a>
-<br/>
-<p>
-It is extremely easy to do scaling under MATLAB.
-The following one-line code scale each feature to the range
-of [0,1]:
-<pre>
-(data - repmat(min(data,[],1),size(data,1),1))*spdiags(1./(max(data,[],1)-min(data,[],1))',0,size(data,2),size(data,2))
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f803"><b>Q: How could I use MATLAB interface for parameter selection?</b></a>
-<br/>
-<p>
-One can do this by a simple loop.
-See the following example:
-<pre>
-bestcv = 0;
-for log2c = -1:3,
- for log2g = -4:1,
- cmd = ['-v 5 -c ', num2str(2^log2c), ' -g ', num2str(2^log2g)];
- cv = svmtrain(heart_scale_label, heart_scale_inst, cmd);
- if (cv >= bestcv),
- bestcv = cv; bestc = 2^log2c; bestg = 2^log2g;
- end
- fprintf('%g %g %g (best c=%g, g=%g, rate=%g)\n', log2c, log2g, cv, bestc, bestg, bestcv);
- end
-end
-</pre>
-You may adjust the parameter range in the above loops.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f8031"><b>Q: I use MATLAB parallel programming toolbox on a multi-core environment for parameter selection. Why the program is even slower?</b></a>
-<br/>
-<p>
-Fabrizio Lacalandra of University of Pisa reported this issue.
-It seems the problem is caused by the screen output.
-If you disable the <b>info</b> function
-using <pre>#if 0,</pre> then the problem
-may be solved.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f8032"><b>Q: How do I use LIBSVM with OpenMP under MATLAB?</b></a>
-<br/>
-<p>
-In Makefile,
-you need to add -fopenmp to CFLAGS and -lgomp to MEX_OPTION. For Octave, you need the same modification.
-
-<p> However, a minor problem is that
-the number of threads cannot
-be specified in MATLAB. We tried Version 7.12 (R2011a) and gcc-4.6.1.
-
-<pre>
-% export OMP_NUM_THREADS=4; matlab
->> setenv('OMP_NUM_THREADS', '1');
-</pre>
-
-Then OMP_NUM_THREADS is still 4 while running the program. Please contact us if you
-see how to solve this problem. You can, however,
-specify the number in the source code (thanks
-to comments from Ricardo Santiago-mozos):
-<pre>
-#pragma omp parallel for private(i) num_threads(4)
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f804"><b>Q: How could I generate the primal variable w of linear SVM?</b></a>
-<br/>
-<p>
-Let's start from the binary class and
-assume you have two labels -1 and +1.
-After obtaining the model from calling svmtrain,
-do the following to have w and b:
-<pre>
-w = model.SVs' * model.sv_coef;
-b = -model.rho;
-
-if model.Label(1) == -1
- w = -w;
- b = -b;
-end
-</pre>
-If you do regression or one-class SVM, then the if statement is not needed.
-
-<p> For multi-class SVM, we illustrate the setting
-in the following example of running the iris
-data, which have 3 classes
-<pre>
-> [y, x] = libsvmread('../../htdocs/libsvmtools/datasets/multiclass/iris.scale');
-> m = svmtrain(y, x, '-t 0')
-
-m =
-
- Parameters: [5x1 double]
- nr_class: 3
- totalSV: 42
- rho: [3x1 double]
- Label: [3x1 double]
- ProbA: []
- ProbB: []
- nSV: [3x1 double]
- sv_coef: [42x2 double]
- SVs: [42x4 double]
-</pre>
-sv_coef is like:
-<pre>
-+-+-+--------------------+
-|1|1| |
-|v|v| SVs from class 1 |
-|2|3| |
-+-+-+--------------------+
-|1|2| |
-|v|v| SVs from class 2 |
-|2|3| |
-+-+-+--------------------+
-|1|2| |
-|v|v| SVs from class 3 |
-|3|3| |
-+-+-+--------------------+
-</pre>
-so we need to see nSV of each classes.
-<pre>
-> m.nSV
-
-ans =
-
- 3
- 21
- 18
-</pre>
-Suppose the goal is to find the vector w of classes
-1 vs 3. Then
-y_i alpha_i of training 1 vs 3 are
-<pre>
-> coef = [m.sv_coef(1:3,2); m.sv_coef(25:42,1)];
-</pre>
-and SVs are:
-<pre>
-> SVs = [m.SVs(1:3,:); m.SVs(25:42,:)];
-</pre>
-Hence, w is
-<pre>
-> w = SVs'*coef;
-</pre>
-For rho,
-<pre>
-> m.rho
-
-ans =
-
- 1.1465
- 0.3682
- -1.9969
-> b = -m.rho(2);
-</pre>
-because rho is arranged by 1vs2 1vs3 2vs3.
-
-
-
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f805"><b>Q: Is there an OCTAVE interface for libsvm?</b></a>
-<br/>
-<p>
-Yes, after libsvm 2.86, the matlab interface
-works on OCTAVE as well. Please use make.m by typing
-<pre>
->> make
-</pre>
-under OCTAVE.
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f806"><b>Q: How to handle the name conflict between svmtrain in the libsvm matlab interface and that in MATLAB bioinformatics toolbox?</b></a>
-<br/>
-<p>
-The easiest way is to rename the svmtrain binary
-file (e.g., svmtrain.mexw32 on 32-bit windows)
-to a different
-name (e.g., svmtrain2.mexw32).
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f807"><b>Q: On Windows I got an error message "Invalid MEX-file: Specific module not found" when running the pre-built MATLAB interface in the windows sub-directory. What should I do?</b></a>
-<br/>
-<p>
-
-The error usually happens
-when there are missing runtime components
-such as MSVCR100.dll on your Windows platform.
-You can use tools such as
-<a href=http://www.dependencywalker.com/>Dependency
-Walker</a> to find missing library files.
-
-<p>
-For example, if the pre-built MEX files are compiled by
-Visual C++ 2010,
-you must have installed
-Microsoft Visual C++ Redistributable Package 2010
-(vcredist_x86.exe). You can easily find the freely
-available file from Microsoft's web site.
-
-<p>
-For 64bit Windows, the situation is similar. If
-the pre-built files are by
-Visual C++ 2008, then you must have
-Microsoft Visual C++ Redistributable Package 2008
-(vcredist_x64.exe).
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f808"><b>Q: LIBSVM supports 1-vs-1 multi-class classification. If instead I would like to use 1-vs-rest, how to implement it using MATLAB interface?</b></a>
-<br/>
-
-<p>
-Please use code in the following <a href=../libsvmtools/ovr_multiclass>directory</a>. The following example shows how to
-train and test the problem dna (<a href=../libsvmtools/datasets/multiclass/dna.scale>training</a> and <a href=../libsvmtools/datasets/multiclass/dna.scale.t>testing</a>).
-
-<p> Load, train and predict data:
-<pre>
-[trainY trainX] = libsvmread('./dna.scale');
-[testY testX] = libsvmread('./dna.scale.t');
-model = ovrtrain(trainY, trainX, '-c 8 -g 4');
-[pred ac decv] = ovrpredict(testY, testX, model);
-fprintf('Accuracy = %g%%\n', ac * 100);
-</pre>
-Conduct CV on a grid of parameters
-<pre>
-bestcv = 0;
-for log2c = -1:2:3,
- for log2g = -4:2:1,
- cmd = ['-q -c ', num2str(2^log2c), ' -g ', num2str(2^log2g)];
- cv = get_cv_ac(trainY, trainX, cmd, 3);
- if (cv >= bestcv),
- bestcv = cv; bestc = 2^log2c; bestg = 2^log2g;
- end
- fprintf('%g %g %g (best c=%g, g=%g, rate=%g)\n', log2c, log2g, cv, bestc, bestg, bestcv);
- end
-end
-</pre>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <a name="/Q10:_MATLAB_interface"></a>
-<a name="f809"><b>Q: I tried to install matlab interface on mac, but failed. What should I do?</b></a>
-<br/>
-
-<p>
-We assume that in a matlab command window you change directory to libsvm/matlab and type
-<pre>
->> make
-</pre>
-We discuss the following situations.
-
-<ol>
-<li>An error message like "libsvmread.c:1:19: fatal error:
-stdio.h: No such file or directory" appears.
-
-<p>
-Reason: "make" looks for a C++ compiler, but
-no compiler is found. To get one, you can
-<ul>
-<li> Install XCode offered by Apple Inc.
-<li> Install XCode Command Line Tools.
-</ul>
-
-<p>
-<li> On OS X with Xcode 4.2+, I got an error message like "llvm-gcc-4.2:
-command not found."
-
-<p>
-Reason: Since Apple Inc. only ships llsvm-gcc instead of gcc-4.2,
-llvm-gcc-4.2 cannot be found.
-
-<p>
-If you are using Xcode 4.2-4.6,
-a related solution is offered at
-<a href=http://www.mathworks.com/matlabcentral/answers/94092>http://www.mathworks.com/matlabcentral/answers/94092</a>.
-
-<p>
-On the other hand, for Xcode 5 (including Xcode 4.2-4.6), in a Matlab command window, enter
-<ul>
-<li> cd (matlabroot)
-<li> cd bin
-<li> Backup your mexopts.sh first
-<li> edit mexopts.sh
-<li> Scroll down to "maci64" section. Change
-<pre>
- CC='llvm-gcc-4.2'
- CXX='llvm-g++-4.2'
-</pre>
-to
-<pre>
- CC='llvm-gcc'
- CXX='llvm-g++'
-</pre>
-</ul>
-
-Please also ensure that SDKROOT corresponds to the SDK version you are using.
-
-<p>
-<li> Other errors: you may check <a href=http://www.mathworks.com/matlabcentral/answers/94092>http://www.mathworks.com/matlabcentral/answers/94092</a>.
-
-</ol>
-<p align="right">
-<a href="#_TOP">[Go Top]</a>
-<hr/>
- <p align="middle">
-<a href="http://www.csie.ntu.edu.tw/~cjlin/libsvm">LIBSVM home page</a>
-</p>
-</body>
-</html>
diff --git a/Modules/Classification/CLLibSVM/licence/README b/Modules/Classification/CLLibSVM/licence/README
deleted file mode 100644
index 3f919736f2..0000000000
--- a/Modules/Classification/CLLibSVM/licence/README
+++ /dev/null
@@ -1,771 +0,0 @@
-Libsvm is a simple, easy-to-use, and efficient software for SVM
-classification and regression. It solves C-SVM classification, nu-SVM
-classification, one-class-SVM, epsilon-SVM regression, and nu-SVM
-regression. It also provides an automatic model selection tool for
-C-SVM classification. This document explains the use of libsvm.
-
-Libsvm is available at
-http://www.csie.ntu.edu.tw/~cjlin/libsvm
-Please read the COPYRIGHT file before using libsvm.
-
-Table of Contents
-=================
-
-- Quick Start
-- Installation and Data Format
-- `svm-train' Usage
-- `svm-predict' Usage
-- `svm-scale' Usage
-- Tips on Practical Use
-- Examples
-- Precomputed Kernels
-- Library Usage
-- Java Version
-- Building Windows Binaries
-- Additional Tools: Sub-sampling, Parameter Selection, Format checking, etc.
-- MATLAB/OCTAVE Interface
-- Python Interface
-- Additional Information
-
-Quick Start
-===========
-
-If you are new to SVM and if the data is not large, please go to
-`tools' directory and use easy.py after installation. It does
-everything automatic -- from data scaling to parameter selection.
-
-Usage: easy.py training_file [testing_file]
-
-More information about parameter selection can be found in
-`tools/README.'
-
-Installation and Data Format
-============================
-
-On Unix systems, type `make' to build the `svm-train' and `svm-predict'
-programs. Run them without arguments to show the usages of them.
-
-On other systems, consult `Makefile' to build them (e.g., see
-'Building Windows binaries' in this file) or use the pre-built
-binaries (Windows binaries are in the directory `windows').
-
-The format of training and testing data file is:
-
-<label> <index1>:<value1> <index2>:<value2> ...
-.
-.
-.
-
-Each line contains an instance and is ended by a '\n' character. For
-classification, <label> is an integer indicating the class label
-(multi-class is supported). For regression, <label> is the target
-value which can be any real number. For one-class SVM, it's not used
-so can be any number. The pair <index>:<value> gives a feature
-(attribute) value: <index> is an integer starting from 1 and <value>
-is a real number. The only exception is the precomputed kernel, where
-<index> starts from 0; see the section of precomputed kernels. Indices
-must be in ASCENDING order. Labels in the testing file are only used
-to calculate accuracy or errors. If they are unknown, just fill the
-first column with any numbers.
-
-A sample classification data included in this package is
-`heart_scale'. To check if your data is in a correct form, use
-`tools/checkdata.py' (details in `tools/README').
-
-Type `svm-train heart_scale', and the program will read the training
-data and output the model file `heart_scale.model'. If you have a test
-set called heart_scale.t, then type `svm-predict heart_scale.t
-heart_scale.model output' to see the prediction accuracy. The `output'
-file contains the predicted class labels.
-
-For classification, if training data are in only one class (i.e., all
-labels are the same), then `svm-train' issues a warning message:
-`Warning: training data in only one class. See README for details,'
-which means the training data is very unbalanced. The label in the
-training data is directly returned when testing.
-
-There are some other useful programs in this package.
-
-svm-scale:
-
- This is a tool for scaling input data file.
-
-svm-toy:
-
- This is a simple graphical interface which shows how SVM
- separate data in a plane. You can click in the window to
- draw data points. Use "change" button to choose class
- 1, 2 or 3 (i.e., up to three classes are supported), "load"
- button to load data from a file, "save" button to save data to
- a file, "run" button to obtain an SVM model, and "clear"
- button to clear the window.
-
- You can enter options in the bottom of the window, the syntax of
- options is the same as `svm-train'.
-
- Note that "load" and "save" consider dense data format both in
- classification and the regression cases. For classification,
- each data point has one label (the color) that must be 1, 2,
- or 3 and two attributes (x-axis and y-axis values) in
- [0,1). For regression, each data point has one target value
- (y-axis) and one attribute (x-axis values) in [0, 1).
-
- Type `make' in respective directories to build them.
-
- You need Qt library to build the Qt version.
- (available from http://www.trolltech.com)
-
- You need GTK+ library to build the GTK version.
- (available from http://www.gtk.org)
-
- The pre-built Windows binaries are in the `windows'
- directory. We use Visual C++ on a 32-bit machine, so the
- maximal cache size is 2GB.
-
-`svm-train' Usage
-=================
-
-Usage: svm-train [options] training_set_file [model_file]
-options:
--s svm_type : set type of SVM (default 0)
- 0 -- C-SVC (multi-class classification)
- 1 -- nu-SVC (multi-class classification)
- 2 -- one-class SVM
- 3 -- epsilon-SVR (regression)
- 4 -- nu-SVR (regression)
--t kernel_type : set type of kernel function (default 2)
- 0 -- linear: u'*v
- 1 -- polynomial: (gamma*u'*v + coef0)^degree
- 2 -- radial basis function: exp(-gamma*|u-v|^2)
- 3 -- sigmoid: tanh(gamma*u'*v + coef0)
- 4 -- precomputed kernel (kernel values in training_set_file)
--d degree : set degree in kernel function (default 3)
--g gamma : set gamma in kernel function (default 1/num_features)
--r coef0 : set coef0 in kernel function (default 0)
--c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
--n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
--p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
--m cachesize : set cache memory size in MB (default 100)
--e epsilon : set tolerance of termination criterion (default 0.001)
--h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1)
--b probability_estimates : whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)
--wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1)
--v n: n-fold cross validation mode
--q : quiet mode (no outputs)
-
-
-The k in the -g option means the number of attributes in the input data.
-
-option -v randomly splits the data into n parts and calculates cross
-validation accuracy/mean squared error on them.
-
-See libsvm FAQ for the meaning of outputs.
-
-`svm-predict' Usage
-===================
-
-Usage: svm-predict [options] test_file model_file output_file
-options:
--b probability_estimates: whether to predict probability estimates, 0 or 1 (default 0); for one-class SVM only 0 is supported
-
-model_file is the model file generated by svm-train.
-test_file is the test data you want to predict.
-svm-predict will produce output in the output_file.
-
-`svm-scale' Usage
-=================
-
-Usage: svm-scale [options] data_filename
-options:
--l lower : x scaling lower limit (default -1)
--u upper : x scaling upper limit (default +1)
--y y_lower y_upper : y scaling limits (default: no y scaling)
--s save_filename : save scaling parameters to save_filename
--r restore_filename : restore scaling parameters from restore_filename
-
-See 'Examples' in this file for examples.
-
-Tips on Practical Use
-=====================
-
-* Scale your data. For example, scale each attribute to [0,1] or [-1,+1].
-* For C-SVC, consider using the model selection tool in the tools directory.
-* nu in nu-SVC/one-class-SVM/nu-SVR approximates the fraction of training
- errors and support vectors.
-* If data for classification are unbalanced (e.g. many positive and
- few negative), try different penalty parameters C by -wi (see
- examples below).
-* Specify larger cache size (i.e., larger -m) for huge problems.
-
-Examples
-========
-
-> svm-scale -l -1 -u 1 -s range train > train.scale
-> svm-scale -r range test > test.scale
-
-Scale each feature of the training data to be in [-1,1]. Scaling
-factors are stored in the file range and then used for scaling the
-test data.
-
-> svm-train -s 0 -c 5 -t 2 -g 0.5 -e 0.1 data_file
-
-Train a classifier with RBF kernel exp(-0.5|u-v|^2), C=10, and
-stopping tolerance 0.1.
-
-> svm-train -s 3 -p 0.1 -t 0 data_file
-
-Solve SVM regression with linear kernel u'v and epsilon=0.1
-in the loss function.
-
-> svm-train -c 10 -w1 1 -w-2 5 -w4 2 data_file
-
-Train a classifier with penalty 10 = 1 * 10 for class 1, penalty 50 =
-5 * 10 for class -2, and penalty 20 = 2 * 10 for class 4.
-
-> svm-train -s 0 -c 100 -g 0.1 -v 5 data_file
-
-Do five-fold cross validation for the classifier using
-the parameters C = 100 and gamma = 0.1
-
-> svm-train -s 0 -b 1 data_file
-> svm-predict -b 1 test_file data_file.model output_file
-
-Obtain a model with probability information and predict test data with
-probability estimates
-
-Precomputed Kernels
-===================
-
-Users may precompute kernel values and input them as training and
-testing files. Then libsvm does not need the original
-training/testing sets.
-
-Assume there are L training instances x1, ..., xL and.
-Let K(x, y) be the kernel
-value of two instances x and y. The input formats
-are:
-
-New training instance for xi:
-
-<label> 0:i 1:K(xi,x1) ... L:K(xi,xL)
-
-New testing instance for any x:
-
-<label> 0:? 1:K(x,x1) ... L:K(x,xL)
-
-That is, in the training file the first column must be the "ID" of
-xi. In testing, ? can be any value.
-
-All kernel values including ZEROs must be explicitly provided. Any
-permutation or random subsets of the training/testing files are also
-valid (see examples below).
-
-Note: the format is slightly different from the precomputed kernel
-package released in libsvmtools earlier.
-
-Examples:
-
- Assume the original training data has three four-feature
- instances and testing data has one instance:
-
- 15 1:1 2:1 3:1 4:1
- 45 2:3 4:3
- 25 3:1
-
- 15 1:1 3:1
-
- If the linear kernel is used, we have the following new
- training/testing sets:
-
- 15 0:1 1:4 2:6 3:1
- 45 0:2 1:6 2:18 3:0
- 25 0:3 1:1 2:0 3:1
-
- 15 0:? 1:2 2:0 3:1
-
- ? can be any value.
-
- Any subset of the above training file is also valid. For example,
-
- 25 0:3 1:1 2:0 3:1
- 45 0:2 1:6 2:18 3:0
-
- implies that the kernel matrix is
-
- [K(2,2) K(2,3)] = [18 0]
- [K(3,2) K(3,3)] = [0 1]
-
-Library Usage
-=============
-
-These functions and structures are declared in the header file
-`svm.h'. You need to #include "svm.h" in your C/C++ source files and
-link your program with `svm.cpp'. You can see `svm-train.c' and
-`svm-predict.c' for examples showing how to use them. We define
-LIBSVM_VERSION and declare `extern int libsvm_version; ' in svm.h, so
-you can check the version number.
-
-Before you classify test data, you need to construct an SVM model
-(`svm_model') using training data. A model can also be saved in
-a file for later use. Once an SVM model is available, you can use it
-to classify new data.
-
-- Function: struct svm_model *svm_train(const struct svm_problem *prob,
- const struct svm_parameter *param);
-
- This function constructs and returns an SVM model according to
- the given training data and parameters.
-
- struct svm_problem describes the problem:
-
- struct svm_problem
- {
- int l;
- double *y;
- struct svm_node **x;
- };
-
- where `l' is the number of training data, and `y' is an array containing
- their target values. (integers in classification, real numbers in
- regression) `x' is an array of pointers, each of which points to a sparse
- representation (array of svm_node) of one training vector.
-
- For example, if we have the following training data:
-
- LABEL ATTR1 ATTR2 ATTR3 ATTR4 ATTR5
- ----- ----- ----- ----- ----- -----
- 1 0 0.1 0.2 0 0
- 2 0 0.1 0.3 -1.2 0
- 1 0.4 0 0 0 0
- 2 0 0.1 0 1.4 0.5
- 3 -0.1 -0.2 0.1 1.1 0.1
-
- then the components of svm_problem are:
-
- l = 5
-
- y -> 1 2 1 2 3
-
- x -> [ ] -> (2,0.1) (3,0.2) (-1,?)
- [ ] -> (2,0.1) (3,0.3) (4,-1.2) (-1,?)
- [ ] -> (1,0.4) (-1,?)
- [ ] -> (2,0.1) (4,1.4) (5,0.5) (-1,?)
- [ ] -> (1,-0.1) (2,-0.2) (3,0.1) (4,1.1) (5,0.1) (-1,?)
-
- where (index,value) is stored in the structure `svm_node':
-
- struct svm_node
- {
- int index;
- double value;
- };
-
- index = -1 indicates the end of one vector. Note that indices must
- be in ASCENDING order.
-
- struct svm_parameter describes the parameters of an SVM model:
-
- struct svm_parameter
- {
- int svm_type;
- int kernel_type;
- int degree; /* for poly */
- double gamma; /* for poly/rbf/sigmoid */
- double coef0; /* for poly/sigmoid */
-
- /* these are for training only */
- double cache_size; /* in MB */
- double eps; /* stopping criteria */
- double C; /* for C_SVC, EPSILON_SVR, and NU_SVR */
- int nr_weight; /* for C_SVC */
- int *weight_label; /* for C_SVC */
- double* weight; /* for C_SVC */
- double nu; /* for NU_SVC, ONE_CLASS, and NU_SVR */
- double p; /* for EPSILON_SVR */
- int shrinking; /* use the shrinking heuristics */
- int probability; /* do probability estimates */
- };
-
- svm_type can be one of C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR.
-
- C_SVC: C-SVM classification
- NU_SVC: nu-SVM classification
- ONE_CLASS: one-class-SVM
- EPSILON_SVR: epsilon-SVM regression
- NU_SVR: nu-SVM regression
-
- kernel_type can be one of LINEAR, POLY, RBF, SIGMOID.
-
- LINEAR: u'*v
- POLY: (gamma*u'*v + coef0)^degree
- RBF: exp(-gamma*|u-v|^2)
- SIGMOID: tanh(gamma*u'*v + coef0)
- PRECOMPUTED: kernel values in training_set_file
-
- cache_size is the size of the kernel cache, specified in megabytes.
- C is the cost of constraints violation.
- eps is the stopping criterion. (we usually use 0.00001 in nu-SVC,
- 0.001 in others). nu is the parameter in nu-SVM, nu-SVR, and
- one-class-SVM. p is the epsilon in epsilon-insensitive loss function
- of epsilon-SVM regression. shrinking = 1 means shrinking is conducted;
- = 0 otherwise. probability = 1 means model with probability
- information is obtained; = 0 otherwise.
-
- nr_weight, weight_label, and weight are used to change the penalty
- for some classes (If the weight for a class is not changed, it is
- set to 1). This is useful for training classifier using unbalanced
- input data or with asymmetric misclassification cost.
-
- nr_weight is the number of elements in the array weight_label and
- weight. Each weight[i] corresponds to weight_label[i], meaning that
- the penalty of class weight_label[i] is scaled by a factor of weight[i].
-
- If you do not want to change penalty for any of the classes,
- just set nr_weight to 0.
-
- *NOTE* Because svm_model contains pointers to svm_problem, you can
- not free the memory used by svm_problem if you are still using the
- svm_model produced by svm_train().
-
- *NOTE* To avoid wrong parameters, svm_check_parameter() should be
- called before svm_train().
-
- struct svm_model stores the model obtained from the training procedure.
- It is not recommended to directly access entries in this structure.
- Programmers should use the interface functions to get the values.
-
- struct svm_model
- {
- struct svm_parameter param; /* parameter */
- int nr_class; /* number of classes, = 2 in regression/one class svm */
- int l; /* total #SV */
- struct svm_node **SV; /* SVs (SV[l]) */
- double **sv_coef; /* coefficients for SVs in decision functions (sv_coef[k-1][l]) */
- double *rho; /* constants in decision functions (rho[k*(k-1)/2]) */
- double *probA; /* pairwise probability information */
- double *probB;
- int *sv_indices; /* sv_indices[0,...,nSV-1] are values in [1,...,num_traning_data] to indicate SVs in the training set */
-
- /* for classification only */
-
- int *label; /* label of each class (label[k]) */
- int *nSV; /* number of SVs for each class (nSV[k]) */
- /* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
- /* XXX */
- int free_sv; /* 1 if svm_model is created by svm_load_model*/
- /* 0 if svm_model is created by svm_train */
- };
-
- param describes the parameters used to obtain the model.
-
- nr_class is the number of classes. It is 2 for regression and one-class SVM.
-
- l is the number of support vectors. SV and sv_coef are support
- vectors and the corresponding coefficients, respectively. Assume there are
- k classes. For data in class j, the corresponding sv_coef includes (k-1) y*alpha vectors,
- where alpha's are solutions of the following two class problems:
- 1 vs j, 2 vs j, ..., j-1 vs j, j vs j+1, j vs j+2, ..., j vs k
- and y=1 for the first j-1 vectors, while y=-1 for the remaining k-j
- vectors. For example, if there are 4 classes, sv_coef and SV are like:
-
- +-+-+-+--------------------+
- |1|1|1| |
- |v|v|v| SVs from class 1 |
- |2|3|4| |
- +-+-+-+--------------------+
- |1|2|2| |
- |v|v|v| SVs from class 2 |
- |2|3|4| |
- +-+-+-+--------------------+
- |1|2|3| |
- |v|v|v| SVs from class 3 |
- |3|3|4| |
- +-+-+-+--------------------+
- |1|2|3| |
- |v|v|v| SVs from class 4 |
- |4|4|4| |
- +-+-+-+--------------------+
-
- See svm_train() for an example of assigning values to sv_coef.
-
- rho is the bias term (-b). probA and probB are parameters used in
- probability outputs. If there are k classes, there are k*(k-1)/2
- binary problems as well as rho, probA, and probB values. They are
- aligned in the order of binary problems:
- 1 vs 2, 1 vs 3, ..., 1 vs k, 2 vs 3, ..., 2 vs k, ..., k-1 vs k.
-
- sv_indices[0,...,nSV-1] are values in [1,...,num_traning_data] to
- indicate support vectors in the training set.
-
- label contains labels in the training data.
-
- nSV is the number of support vectors in each class.
-
- free_sv is a flag used to determine whether the space of SV should
- be released in free_model_content(struct svm_model*) and
- free_and_destroy_model(struct svm_model**). If the model is
- generated by svm_train(), then SV points to data in svm_problem
- and should not be removed. For example, free_sv is 0 if svm_model
- is created by svm_train, but is 1 if created by svm_load_model.
-
-- Function: double svm_predict(const struct svm_model *model,
- const struct svm_node *x);
-
- This function does classification or regression on a test vector x
- given a model.
-
- For a classification model, the predicted class for x is returned.
- For a regression model, the function value of x calculated using
- the model is returned. For an one-class model, +1 or -1 is
- returned.
-
-- Function: void svm_cross_validation(const struct svm_problem *prob,
- const struct svm_parameter *param, int nr_fold, double *target);
-
- This function conducts cross validation. Data are separated to
- nr_fold folds. Under given parameters, sequentially each fold is
- validated using the model from training the remaining. Predicted
- labels (of all prob's instances) in the validation process are
- stored in the array called target.
-
- The format of svm_prob is same as that for svm_train().
-
-- Function: int svm_get_svm_type(const struct svm_model *model);
-
- This function gives svm_type of the model. Possible values of
- svm_type are defined in svm.h.
-
-- Function: int svm_get_nr_class(const svm_model *model);
-
- For a classification model, this function gives the number of
- classes. For a regression or an one-class model, 2 is returned.
-
-- Function: void svm_get_labels(const svm_model *model, int* label)
-
- For a classification model, this function outputs the name of
- labels into an array called label. For regression and one-class
- models, label is unchanged.
-
-- Function: void svm_get_sv_indices(const struct svm_model *model, int *sv_indices)
-
- This function outputs indices of support vectors into an array called sv_indices.
- The size of sv_indices is the number of support vectors and can be obtained by calling svm_get_nr_sv.
- Each sv_indices[i] is in the range of [1, ..., num_traning_data].
-
-- Function: int svm_get_nr_sv(const struct svm_model *model)
-
- This function gives the number of total support vector.
-
-- Function: double svm_get_svr_probability(const struct svm_model *model);
-
- For a regression model with probability information, this function
- outputs a value sigma > 0. For test data, we consider the
- probability model: target value = predicted value + z, z: Laplace
- distribution e^(-|z|/sigma)/(2sigma)
-
- If the model is not for svr or does not contain required
- information, 0 is returned.
-
-- Function: double svm_predict_values(const svm_model *model,
- const svm_node *x, double* dec_values)
-
- This function gives decision values on a test vector x given a
- model, and return the predicted label (classification) or
- the function value (regression).
-
- For a classification model with nr_class classes, this function
- gives nr_class*(nr_class-1)/2 decision values in the array
- dec_values, where nr_class can be obtained from the function
- svm_get_nr_class. The order is label[0] vs. label[1], ...,
- label[0] vs. label[nr_class-1], label[1] vs. label[2], ...,
- label[nr_class-2] vs. label[nr_class-1], where label can be
- obtained from the function svm_get_labels. The returned value is
- the predicted class for x. Note that when nr_class = 1, this
- function does not give any decision value.
-
- For a regression model, dec_values[0] and the returned value are
- both the function value of x calculated using the model. For a
- one-class model, dec_values[0] is the decision value of x, while
- the returned value is +1/-1.
-
-- Function: double svm_predict_probability(const struct svm_model *model,
- const struct svm_node *x, double* prob_estimates);
-
- This function does classification or regression on a test vector x
- given a model with probability information.
-
- For a classification model with probability information, this
- function gives nr_class probability estimates in the array
- prob_estimates. nr_class can be obtained from the function
- svm_get_nr_class. The class with the highest probability is
- returned. For regression/one-class SVM, the array prob_estimates
- is unchanged and the returned value is the same as that of
- svm_predict.
-
-- Function: const char *svm_check_parameter(const struct svm_problem *prob,
- const struct svm_parameter *param);
-
- This function checks whether the parameters are within the feasible
- range of the problem. This function should be called before calling
- svm_train() and svm_cross_validation(). It returns NULL if the
- parameters are feasible, otherwise an error message is returned.
-
-- Function: int svm_check_probability_model(const struct svm_model *model);
-
- This function checks whether the model contains required
- information to do probability estimates. If so, it returns
- +1. Otherwise, 0 is returned. This function should be called
- before calling svm_get_svr_probability and
- svm_predict_probability.
-
-- Function: int svm_save_model(const char *model_file_name,
- const struct svm_model *model);
-
- This function saves a model to a file; returns 0 on success, or -1
- if an error occurs.
-
-- Function: struct svm_model *svm_load_model(const char *model_file_name);
-
- This function returns a pointer to the model read from the file,
- or a null pointer if the model could not be loaded.
-
-- Function: void svm_free_model_content(struct svm_model *model_ptr);
-
- This function frees the memory used by the entries in a model structure.
-
-- Function: void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);
-
- This function frees the memory used by a model and destroys the model
- structure. It is equivalent to svm_destroy_model, which
- is deprecated after version 3.0.
-
-- Function: void svm_destroy_param(struct svm_parameter *param);
-
- This function frees the memory used by a parameter set.
-
-- Function: void svm_set_print_string_function(void (*print_func)(const char *));
-
- Users can specify their output format by a function. Use
- svm_set_print_string_function(NULL);
- for default printing to stdout.
-
-Java Version
-============
-
-The pre-compiled java class archive `libsvm.jar' and its source files are
-in the java directory. To run the programs, use
-
-java -classpath libsvm.jar svm_train <arguments>
-java -classpath libsvm.jar svm_predict <arguments>
-java -classpath libsvm.jar svm_toy
-java -classpath libsvm.jar svm_scale <arguments>
-
-Note that you need Java 1.5 (5.0) or above to run it.
-
-You may need to add Java runtime library (like classes.zip) to the classpath.
-You may need to increase maximum Java heap size.
-
-Library usages are similar to the C version. These functions are available:
-
-public class svm {
- public static final int LIBSVM_VERSION=318;
- public static svm_model svm_train(svm_problem prob, svm_parameter param);
- public static void svm_cross_validation(svm_problem prob, svm_parameter param, int nr_fold, double[] target);
- public static int svm_get_svm_type(svm_model model);
- public static int svm_get_nr_class(svm_model model);
- public static void svm_get_labels(svm_model model, int[] label);
- public static void svm_get_sv_indices(svm_model model, int[] indices);
- public static int svm_get_nr_sv(svm_model model);
- public static double svm_get_svr_probability(svm_model model);
- public static double svm_predict_values(svm_model model, svm_node[] x, double[] dec_values);
- public static double svm_predict(svm_model model, svm_node[] x);
- public static double svm_predict_probability(svm_model model, svm_node[] x, double[] prob_estimates);
- public static void svm_save_model(String model_file_name, svm_model model) throws IOException
- public static svm_model svm_load_model(String model_file_name) throws IOException
- public static String svm_check_parameter(svm_problem prob, svm_parameter param);
- public static int svm_check_probability_model(svm_model model);
- public static void svm_set_print_string_function(svm_print_interface print_func);
-}
-
-The library is in the "libsvm" package.
-Note that in Java version, svm_node[] is not ended with a node whose index = -1.
-
-Users can specify their output format by
-
- your_print_func = new svm_print_interface()
- {
- public void print(String s)
- {
- // your own format
- }
- };
- svm.svm_set_print_string_function(your_print_func);
-
-Building Windows Binaries
-=========================
-
-Windows binaries are in the directory `windows'. To build them via
-Visual C++, use the following steps:
-
-1. Open a DOS command box (or Visual Studio Command Prompt) and change
-to libsvm directory. If environment variables of VC++ have not been
-set, type
-
-"C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
-
-You may have to modify the above command according which version of
-VC++ or where it is installed.
-
-2. Type
-
-nmake -f Makefile.win clean all
-
-3. (optional) To build shared library libsvm.dll, type
-
-nmake -f Makefile.win lib
-
-4. (optional) To build 64-bit windows binaries, you must
- (1) Run vcvars64.bat instead of vcvars32.bat. Note that
- vcvars64.bat is located at "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64\"
- (2) Change CFLAGS in Makefile.win: /D _WIN32 to /D _WIN64
-
-Another way is to build them from Visual C++ environment. See details
-in libsvm FAQ.
-
-- Additional Tools: Sub-sampling, Parameter Selection, Format checking, etc.
-============================================================================
-
-See the README file in the tools directory.
-
-MATLAB/OCTAVE Interface
-=======================
-
-Please check the file README in the directory `matlab'.
-
-Python Interface
-================
-
-See the README file in python directory.
-
-Additional Information
-======================
-
-If you find LIBSVM helpful, please cite it as
-
-Chih-Chung Chang and Chih-Jen Lin, LIBSVM : a library for support
-vector machines. ACM Transactions on Intelligent Systems and
-Technology, 2:27:1--27:27, 2011. Software available at
-http://www.csie.ntu.edu.tw/~cjlin/libsvm
-
-LIBSVM implementation document is available at
-http://www.csie.ntu.edu.tw/~cjlin/papers/libsvm.pdf
-
-For any questions and comments, please email cjlin@csie.ntu.edu.tw
-
-Acknowledgments:
-This work was supported in part by the National Science
-Council of Taiwan via the grant NSC 89-2213-E-002-013.
-The authors thank their group members and users
-for many helpful discussions and comments. They are listed in
-http://www.csie.ntu.edu.tw/~cjlin/libsvm/acknowledgements
-
diff --git a/Modules/Classification/CLLibSVM/licence/README.weight b/Modules/Classification/CLLibSVM/licence/README.weight
deleted file mode 100644
index 0e5f458bf1..0000000000
--- a/Modules/Classification/CLLibSVM/licence/README.weight
+++ /dev/null
@@ -1,7 +0,0 @@
-Usage:
- use '-W weight_file' to assign weights for each instance.
- Please make sure all weights are non-negative.
-
-Example:
- $ ./svm-train -W heart_scale.wgt heart_scale
-
diff --git a/Modules/Classification/CLLibSVM/licence/heart_scale b/Modules/Classification/CLLibSVM/licence/heart_scale
deleted file mode 100644
index 62f8f3ed7f..0000000000
--- a/Modules/Classification/CLLibSVM/licence/heart_scale
+++ /dev/null
@@ -1,270 +0,0 @@
-+1 1:0.708333 2:1 3:1 4:-0.320755 5:-0.105023 6:-1 7:1 8:-0.419847 9:-1 10:-0.225806 12:1 13:-1
--1 1:0.583333 2:-1 3:0.333333 4:-0.603774 5:1 6:-1 7:1 8:0.358779 9:-1 10:-0.483871 12:-1 13:1
-+1 1:0.166667 2:1 3:-0.333333 4:-0.433962 5:-0.383562 6:-1 7:-1 8:0.0687023 9:-1 10:-0.903226 11:-1 12:-1 13:1
--1 1:0.458333 2:1 3:1 4:-0.358491 5:-0.374429 6:-1 7:-1 8:-0.480916 9:1 10:-0.935484 12:-0.333333 13:1
--1 1:0.875 2:-1 3:-0.333333 4:-0.509434 5:-0.347032 6:-1 7:1 8:-0.236641 9:1 10:-0.935484 11:-1 12:-0.333333 13:-1
--1 1:0.5 2:1 3:1 4:-0.509434 5:-0.767123 6:-1 7:-1 8:0.0534351 9:-1 10:-0.870968 11:-1 12:-1 13:1
-+1 1:0.125 2:1 3:0.333333 4:-0.320755 5:-0.406393 6:1 7:1 8:0.0839695 9:1 10:-0.806452 12:-0.333333 13:0.5
-+1 1:0.25 2:1 3:1 4:-0.698113 5:-0.484018 6:-1 7:1 8:0.0839695 9:1 10:-0.612903 12:-0.333333 13:1
-+1 1:0.291667 2:1 3:1 4:-0.132075 5:-0.237443 6:-1 7:1 8:0.51145 9:-1 10:-0.612903 12:0.333333 13:1
-+1 1:0.416667 2:-1 3:1 4:0.0566038 5:0.283105 6:-1 7:1 8:0.267176 9:-1 10:0.290323 12:1 13:1
--1 1:0.25 2:1 3:1 4:-0.226415 5:-0.506849 6:-1 7:-1 8:0.374046 9:-1 10:-0.83871 12:-1 13:1
--1 2:1 3:1 4:-0.0943396 5:-0.543379 6:-1 7:1 8:-0.389313 9:1 10:-1 11:-1 12:-1 13:1
--1 1:-0.375 2:1 3:0.333333 4:-0.132075 5:-0.502283 6:-1 7:1 8:0.664122 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.333333 2:1 3:-1 4:-0.245283 5:-0.506849 6:-1 7:-1 8:0.129771 9:-1 10:-0.16129 12:0.333333 13:-1
--1 1:0.166667 2:-1 3:1 4:-0.358491 5:-0.191781 6:-1 7:1 8:0.343511 9:-1 10:-1 11:-1 12:-0.333333 13:-1
--1 1:0.75 2:-1 3:1 4:-0.660377 5:-0.894977 6:-1 7:-1 8:-0.175573 9:-1 10:-0.483871 12:-1 13:-1
-+1 1:-0.291667 2:1 3:1 4:-0.132075 5:-0.155251 6:-1 7:-1 8:-0.251908 9:1 10:-0.419355 12:0.333333 13:1
-+1 2:1 3:1 4:-0.132075 5:-0.648402 6:1 7:1 8:0.282443 9:1 11:1 12:-1 13:1
--1 1:0.458333 2:1 3:-1 4:-0.698113 5:-0.611872 6:-1 7:1 8:0.114504 9:1 10:-0.419355 12:-1 13:-1
--1 1:-0.541667 2:1 3:-1 4:-0.132075 5:-0.666667 6:-1 7:-1 8:0.633588 9:1 10:-0.548387 11:-1 12:-1 13:1
-+1 1:0.583333 2:1 3:1 4:-0.509434 5:-0.52968 6:-1 7:1 8:-0.114504 9:1 10:-0.16129 12:0.333333 13:1
--1 1:-0.208333 2:1 3:-0.333333 4:-0.320755 5:-0.456621 6:-1 7:1 8:0.664122 9:-1 10:-0.935484 12:-1 13:-1
--1 1:-0.416667 2:1 3:1 4:-0.603774 5:-0.191781 6:-1 7:-1 8:0.679389 9:-1 10:-0.612903 12:-1 13:-1
--1 1:-0.25 2:1 3:1 4:-0.660377 5:-0.643836 6:-1 7:-1 8:0.0992366 9:-1 10:-0.967742 11:-1 12:-1 13:-1
--1 1:0.0416667 2:-1 3:-0.333333 4:-0.283019 5:-0.260274 6:1 7:1 8:0.343511 9:1 10:-1 11:-1 12:-0.333333 13:-1
--1 1:-0.208333 2:-1 3:0.333333 4:-0.320755 5:-0.319635 6:-1 7:-1 8:0.0381679 9:-1 10:-0.935484 11:-1 12:-1 13:-1
--1 1:-0.291667 2:-1 3:1 4:-0.169811 5:-0.465753 6:-1 7:1 8:0.236641 9:1 10:-1 12:-1 13:-1
--1 1:-0.0833333 2:-1 3:0.333333 4:-0.509434 5:-0.228311 6:-1 7:1 8:0.312977 9:-1 10:-0.806452 11:-1 12:-1 13:-1
-+1 1:0.208333 2:1 3:0.333333 4:-0.660377 5:-0.525114 6:-1 7:1 8:0.435115 9:-1 10:-0.193548 12:-0.333333 13:1
--1 1:0.75 2:-1 3:0.333333 4:-0.698113 5:-0.365297 6:1 7:1 8:-0.0992366 9:-1 10:-1 11:-1 12:-0.333333 13:-1
-+1 1:0.166667 2:1 3:0.333333 4:-0.358491 5:-0.52968 6:-1 7:1 8:0.206107 9:-1 10:-0.870968 12:-0.333333 13:1
--1 1:0.541667 2:1 3:1 4:0.245283 5:-0.534247 6:-1 7:1 8:0.0229008 9:-1 10:-0.258065 11:-1 12:-1 13:0.5
--1 1:-0.666667 2:-1 3:0.333333 4:-0.509434 5:-0.593607 6:-1 7:-1 8:0.51145 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.25 2:1 3:1 4:0.433962 5:-0.086758 6:-1 7:1 8:0.0534351 9:1 10:0.0967742 11:1 12:-1 13:1
-+1 1:-0.125 2:1 3:1 4:-0.0566038 5:-0.6621 6:-1 7:1 8:-0.160305 9:1 10:-0.709677 12:-1 13:1
-+1 1:-0.208333 2:1 3:1 4:-0.320755 5:-0.406393 6:1 7:1 8:0.206107 9:1 10:-1 11:-1 12:0.333333 13:1
-+1 1:0.333333 2:1 3:1 4:-0.132075 5:-0.630137 6:-1 7:1 8:0.0229008 9:1 10:-0.387097 11:-1 12:-0.333333 13:1
-+1 1:0.25 2:1 3:-1 4:0.245283 5:-0.328767 6:-1 7:1 8:-0.175573 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.458333 2:1 3:0.333333 4:-0.320755 5:-0.753425 6:-1 7:-1 8:0.206107 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.208333 2:1 3:1 4:-0.471698 5:-0.561644 6:-1 7:1 8:0.755725 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:-0.541667 2:1 3:1 4:0.0943396 5:-0.557078 6:-1 7:-1 8:0.679389 9:-1 10:-1 11:-1 12:-1 13:1
--1 1:0.375 2:-1 3:1 4:-0.433962 5:-0.621005 6:-1 7:-1 8:0.40458 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.375 2:1 3:0.333333 4:-0.320755 5:-0.511416 6:-1 7:-1 8:0.648855 9:1 10:-0.870968 11:-1 12:-1 13:-1
--1 1:-0.291667 2:1 3:-0.333333 4:-0.867925 5:-0.675799 6:1 7:-1 8:0.29771 9:-1 10:-1 11:-1 12:-1 13:1
-+1 1:0.25 2:1 3:0.333333 4:-0.396226 5:-0.579909 6:1 7:-1 8:-0.0381679 9:-1 10:-0.290323 12:-0.333333 13:0.5
--1 1:0.208333 2:1 3:0.333333 4:-0.132075 5:-0.611872 6:1 7:1 8:0.435115 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:-0.166667 2:1 3:0.333333 4:-0.54717 5:-0.894977 6:-1 7:1 8:-0.160305 9:-1 10:-0.741935 11:-1 12:1 13:-1
-+1 1:-0.375 2:1 3:1 4:-0.698113 5:-0.675799 6:-1 7:1 8:0.618321 9:-1 10:-1 11:-1 12:-0.333333 13:-1
-+1 1:0.541667 2:1 3:-0.333333 4:0.245283 5:-0.452055 6:-1 7:-1 8:-0.251908 9:1 10:-1 12:1 13:0.5
-+1 1:0.5 2:-1 3:1 4:0.0566038 5:-0.547945 6:-1 7:1 8:-0.343511 9:-1 10:-0.677419 12:1 13:1
-+1 1:-0.458333 2:1 3:1 4:-0.207547 5:-0.136986 6:-1 7:-1 8:-0.175573 9:1 10:-0.419355 12:-1 13:0.5
--1 1:-0.0416667 2:1 3:-0.333333 4:-0.358491 5:-0.639269 6:1 7:-1 8:0.725191 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:0.5 2:-1 3:0.333333 4:-0.132075 5:0.328767 6:1 7:1 8:0.312977 9:-1 10:-0.741935 11:-1 12:-0.333333 13:-1
--1 1:0.416667 2:-1 3:-0.333333 4:-0.132075 5:-0.684932 6:-1 7:-1 8:0.648855 9:-1 10:-1 11:-1 12:0.333333 13:-1
--1 1:-0.333333 2:-1 3:-0.333333 4:-0.320755 5:-0.506849 6:-1 7:1 8:0.587786 9:-1 10:-0.806452 12:-1 13:-1
--1 1:-0.5 2:-1 3:-0.333333 4:-0.792453 5:-0.671233 6:-1 7:-1 8:0.480916 9:-1 10:-1 11:-1 12:-0.333333 13:-1
-+1 1:0.333333 2:1 3:1 4:-0.169811 5:-0.817352 6:-1 7:1 8:-0.175573 9:1 10:0.16129 12:-0.333333 13:-1
--1 1:0.291667 2:-1 3:0.333333 4:-0.509434 5:-0.762557 6:1 7:-1 8:-0.618321 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.25 2:-1 3:1 4:0.509434 5:-0.438356 6:-1 7:-1 8:0.0992366 9:1 10:-1 12:-1 13:-1
-+1 1:0.375 2:1 3:-0.333333 4:-0.509434 5:-0.292237 6:-1 7:1 8:-0.51145 9:-1 10:-0.548387 12:-0.333333 13:1
--1 1:0.166667 2:1 3:0.333333 4:0.0566038 5:-1 6:1 7:-1 8:0.557252 9:-1 10:-0.935484 11:-1 12:-0.333333 13:1
-+1 1:-0.0833333 2:-1 3:1 4:-0.320755 5:-0.182648 6:-1 7:-1 8:0.0839695 9:1 10:-0.612903 12:-1 13:1
--1 1:-0.375 2:1 3:0.333333 4:-0.509434 5:-0.543379 6:-1 7:-1 8:0.496183 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:0.291667 2:-1 3:-1 4:0.0566038 5:-0.479452 6:-1 7:-1 8:0.526718 9:-1 10:-0.709677 11:-1 12:-1 13:-1
--1 1:0.416667 2:1 3:-1 4:-0.0377358 5:-0.511416 6:1 7:1 8:0.206107 9:-1 10:-0.258065 11:1 12:-1 13:0.5
-+1 1:0.166667 2:1 3:1 4:0.0566038 5:-0.315068 6:-1 7:1 8:-0.374046 9:1 10:-0.806452 12:-0.333333 13:0.5
--1 1:-0.0833333 2:1 3:1 4:-0.132075 5:-0.383562 6:-1 7:1 8:0.755725 9:1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.208333 2:-1 3:-0.333333 4:-0.207547 5:-0.118721 6:1 7:1 8:0.236641 9:-1 10:-1 11:-1 12:0.333333 13:-1
--1 1:-0.375 2:-1 3:0.333333 4:-0.54717 5:-0.47032 6:-1 7:-1 8:0.19084 9:-1 10:-0.903226 12:-0.333333 13:-1
-+1 1:-0.25 2:1 3:0.333333 4:-0.735849 5:-0.465753 6:-1 7:-1 8:0.236641 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.333333 2:1 3:1 4:-0.509434 5:-0.388128 6:-1 7:-1 8:0.0534351 9:1 10:0.16129 12:-0.333333 13:1
--1 1:0.166667 2:-1 3:1 4:-0.509434 5:0.0410959 6:-1 7:-1 8:0.40458 9:1 10:-0.806452 11:-1 12:-1 13:-1
--1 1:0.708333 2:1 3:-0.333333 4:0.169811 5:-0.456621 6:-1 7:1 8:0.0992366 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:0.958333 2:-1 3:0.333333 4:-0.132075 5:-0.675799 6:-1 8:-0.312977 9:-1 10:-0.645161 12:-1 13:-1
--1 1:0.583333 2:-1 3:1 4:-0.773585 5:-0.557078 6:-1 7:-1 8:0.0839695 9:-1 10:-0.903226 11:-1 12:0.333333 13:-1
-+1 1:-0.333333 2:1 3:1 4:-0.0943396 5:-0.164384 6:-1 7:1 8:0.160305 9:1 10:-1 12:1 13:1
--1 1:-0.333333 2:1 3:1 4:-0.811321 5:-0.625571 6:-1 7:1 8:0.175573 9:1 10:-0.0322581 12:-1 13:-1
--1 1:-0.583333 2:-1 3:0.333333 4:-1 5:-0.666667 6:-1 7:-1 8:0.648855 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.458333 2:-1 3:0.333333 4:-0.509434 5:-0.621005 6:-1 7:-1 8:0.557252 9:-1 10:-1 12:-1 13:-1
--1 1:0.125 2:1 3:-0.333333 4:-0.509434 5:-0.497717 6:-1 7:-1 8:0.633588 9:-1 10:-0.741935 11:-1 12:-1 13:-1
-+1 1:0.208333 2:1 3:1 4:-0.0188679 5:-0.579909 6:-1 7:-1 8:-0.480916 9:-1 10:-0.354839 12:-0.333333 13:1
-+1 1:-0.75 2:1 3:1 4:-0.509434 5:-0.671233 6:-1 7:-1 8:-0.0992366 9:1 10:-0.483871 12:-1 13:1
-+1 1:0.208333 2:1 3:1 4:0.0566038 5:-0.342466 6:-1 7:1 8:-0.389313 9:1 10:-0.741935 11:-1 12:-1 13:1
--1 1:-0.5 2:1 3:0.333333 4:-0.320755 5:-0.598174 6:-1 7:1 8:0.480916 9:-1 10:-0.354839 12:-1 13:-1
--1 1:0.166667 2:1 3:1 4:-0.698113 5:-0.657534 6:-1 7:-1 8:-0.160305 9:1 10:-0.516129 12:-1 13:0.5
--1 1:-0.458333 2:1 3:-1 4:0.0188679 5:-0.461187 6:-1 7:1 8:0.633588 9:-1 10:-0.741935 11:-1 12:0.333333 13:-1
--1 1:0.375 2:1 3:-0.333333 4:-0.358491 5:-0.625571 6:1 7:1 8:0.0534351 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:0.25 2:1 3:-1 4:0.584906 5:-0.342466 6:-1 7:1 8:0.129771 9:-1 10:0.354839 11:1 12:-1 13:1
--1 1:-0.5 2:-1 3:-0.333333 4:-0.396226 5:-0.178082 6:-1 7:-1 8:0.40458 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:-0.125 2:1 3:1 4:0.0566038 5:-0.465753 6:-1 7:1 8:-0.129771 9:-1 10:-0.16129 12:-1 13:1
--1 1:0.25 2:1 3:-0.333333 4:-0.132075 5:-0.56621 6:-1 7:-1 8:0.419847 9:1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.333333 2:-1 3:1 4:-0.320755 5:-0.0684932 6:-1 7:1 8:0.496183 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.0416667 2:1 3:1 4:-0.433962 5:-0.360731 6:-1 7:1 8:-0.419847 9:1 10:-0.290323 12:-0.333333 13:1
-+1 1:0.0416667 2:1 3:1 4:-0.698113 5:-0.634703 6:-1 7:1 8:-0.435115 9:1 10:-1 12:-0.333333 13:-1
-+1 1:-0.0416667 2:1 3:1 4:-0.415094 5:-0.607306 6:-1 7:-1 8:0.480916 9:-1 10:-0.677419 11:-1 12:0.333333 13:1
-+1 1:-0.25 2:1 3:1 4:-0.698113 5:-0.319635 6:-1 7:1 8:-0.282443 9:1 10:-0.677419 12:-0.333333 13:-1
--1 1:0.541667 2:1 3:1 4:-0.509434 5:-0.196347 6:-1 7:1 8:0.221374 9:-1 10:-0.870968 12:-1 13:-1
-+1 1:0.208333 2:1 3:1 4:-0.886792 5:-0.506849 6:-1 7:-1 8:0.29771 9:-1 10:-0.967742 11:-1 12:-0.333333 13:1
--1 1:0.458333 2:-1 3:0.333333 4:-0.132075 5:-0.146119 6:-1 7:-1 8:-0.0534351 9:-1 10:-0.935484 11:-1 12:-1 13:1
--1 1:-0.125 2:-1 3:-0.333333 4:-0.509434 5:-0.461187 6:-1 7:-1 8:0.389313 9:-1 10:-0.645161 11:-1 12:-1 13:-1
--1 1:-0.375 2:-1 3:0.333333 4:-0.735849 5:-0.931507 6:-1 7:-1 8:0.587786 9:-1 10:-0.806452 12:-1 13:-1
-+1 1:0.583333 2:1 3:1 4:-0.509434 5:-0.493151 6:-1 7:-1 8:-1 9:-1 10:-0.677419 12:-1 13:-1
--1 1:-0.166667 2:-1 3:1 4:-0.320755 5:-0.347032 6:-1 7:-1 8:0.40458 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.166667 2:1 3:1 4:0.339623 5:-0.255708 6:1 7:1 8:-0.19084 9:-1 10:-0.677419 12:1 13:1
-+1 1:0.416667 2:1 3:1 4:-0.320755 5:-0.415525 6:-1 7:1 8:0.160305 9:-1 10:-0.548387 12:-0.333333 13:1
-+1 1:-0.208333 2:1 3:1 4:-0.433962 5:-0.324201 6:-1 7:1 8:0.450382 9:-1 10:-0.83871 12:-1 13:1
--1 1:-0.0833333 2:1 3:0.333333 4:-0.886792 5:-0.561644 6:-1 7:-1 8:0.0992366 9:1 10:-0.612903 12:-1 13:-1
-+1 1:0.291667 2:-1 3:1 4:0.0566038 5:-0.39726 6:-1 7:1 8:0.312977 9:-1 10:-0.16129 12:0.333333 13:1
-+1 1:0.25 2:1 3:1 4:-0.132075 5:-0.767123 6:-1 7:-1 8:0.389313 9:1 10:-1 11:-1 12:-0.333333 13:1
--1 1:-0.333333 2:-1 3:-0.333333 4:-0.660377 5:-0.844749 6:-1 7:-1 8:0.0229008 9:-1 10:-1 12:-1 13:-1
-+1 1:0.0833333 2:-1 3:1 4:0.622642 5:-0.0821918 6:-1 8:-0.29771 9:1 10:0.0967742 12:-1 13:-1
--1 1:-0.5 2:1 3:-0.333333 4:-0.698113 5:-0.502283 6:-1 7:-1 8:0.251908 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.291667 2:-1 3:1 4:0.207547 5:-0.182648 6:-1 7:1 8:0.374046 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:0.0416667 2:-1 3:0.333333 4:-0.226415 5:-0.187215 6:1 7:-1 8:0.51145 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.458333 2:1 3:-0.333333 4:-0.509434 5:-0.228311 6:-1 7:-1 8:0.389313 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.166667 2:-1 3:-0.333333 4:-0.245283 5:-0.3379 6:-1 7:-1 8:0.389313 9:-1 10:-1 12:-1 13:-1
-+1 1:-0.291667 2:1 3:1 4:-0.509434 5:-0.438356 6:-1 7:1 8:0.114504 9:-1 10:-0.741935 11:-1 12:-1 13:1
-+1 1:0.125 2:-1 3:1 4:1 5:-0.260274 6:1 7:1 8:-0.0534351 9:1 10:0.290323 11:1 12:0.333333 13:1
--1 1:0.541667 2:-1 3:-1 4:0.0566038 5:-0.543379 6:-1 7:-1 8:-0.343511 9:-1 10:-0.16129 11:1 12:-1 13:-1
-+1 1:0.125 2:1 3:1 4:-0.320755 5:-0.283105 6:1 7:1 8:-0.51145 9:1 10:-0.483871 11:1 12:-1 13:1
-+1 1:-0.166667 2:1 3:0.333333 4:-0.509434 5:-0.716895 6:-1 7:-1 8:0.0381679 9:-1 10:-0.354839 12:1 13:1
-+1 1:0.0416667 2:1 3:1 4:-0.471698 5:-0.269406 6:-1 7:1 8:-0.312977 9:1 10:0.0322581 12:0.333333 13:-1
-+1 1:0.166667 2:1 3:1 4:0.0943396 5:-0.324201 6:-1 7:-1 8:-0.740458 9:1 10:-0.612903 12:-0.333333 13:1
--1 1:0.5 2:-1 3:0.333333 4:0.245283 5:0.0684932 6:-1 7:1 8:0.221374 9:-1 10:-0.741935 11:-1 12:-1 13:-1
--1 1:0.0416667 2:1 3:0.333333 4:-0.415094 5:-0.328767 6:-1 7:1 8:0.236641 9:-1 10:-0.83871 11:1 12:-0.333333 13:-1
--1 1:0.0416667 2:-1 3:0.333333 4:0.245283 5:-0.657534 6:-1 7:-1 8:0.40458 9:-1 10:-1 11:-1 12:-0.333333 13:-1
-+1 1:0.375 2:1 3:1 4:-0.509434 5:-0.356164 6:-1 7:-1 8:-0.572519 9:1 10:-0.419355 12:0.333333 13:1
--1 1:-0.0416667 2:-1 3:0.333333 4:-0.207547 5:-0.680365 6:-1 7:1 8:0.496183 9:-1 10:-0.967742 12:-1 13:-1
--1 1:-0.0416667 2:1 3:-0.333333 4:-0.245283 5:-0.657534 6:-1 7:-1 8:0.328244 9:-1 10:-0.741935 11:-1 12:-0.333333 13:-1
-+1 1:0.291667 2:1 3:1 4:-0.566038 5:-0.525114 6:1 7:-1 8:0.358779 9:1 10:-0.548387 11:-1 12:0.333333 13:1
-+1 1:0.416667 2:-1 3:1 4:-0.735849 5:-0.347032 6:-1 7:-1 8:0.496183 9:1 10:-0.419355 12:0.333333 13:-1
-+1 1:0.541667 2:1 3:1 4:-0.660377 5:-0.607306 6:-1 7:1 8:-0.0687023 9:1 10:-0.967742 11:-1 12:-0.333333 13:-1
--1 1:-0.458333 2:1 3:1 4:-0.132075 5:-0.543379 6:-1 7:-1 8:0.633588 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.458333 2:1 3:1 4:-0.509434 5:-0.452055 6:-1 7:1 8:-0.618321 9:1 10:-0.290323 11:1 12:-0.333333 13:-1
--1 1:0.0416667 2:1 3:0.333333 4:0.0566038 5:-0.515982 6:-1 7:1 8:0.435115 9:-1 10:-0.483871 11:-1 12:-1 13:1
--1 1:-0.291667 2:-1 3:0.333333 4:-0.0943396 5:-0.767123 6:-1 7:1 8:0.358779 9:1 10:-0.548387 11:1 12:-1 13:-1
--1 1:0.583333 2:-1 3:0.333333 4:0.0943396 5:-0.310502 6:-1 7:-1 8:0.541985 9:-1 10:-1 11:-1 12:-0.333333 13:-1
-+1 1:0.125 2:1 3:1 4:-0.415094 5:-0.438356 6:1 7:1 8:0.114504 9:1 10:-0.612903 12:-0.333333 13:-1
--1 1:-0.791667 2:-1 3:-0.333333 4:-0.54717 5:-0.616438 6:-1 7:-1 8:0.847328 9:-1 10:-0.774194 11:-1 12:-1 13:-1
--1 1:0.166667 2:1 3:1 4:-0.283019 5:-0.630137 6:-1 7:-1 8:0.480916 9:1 10:-1 11:-1 12:-1 13:1
-+1 1:0.458333 2:1 3:1 4:-0.0377358 5:-0.607306 6:-1 7:1 8:-0.0687023 9:-1 10:-0.354839 12:0.333333 13:0.5
--1 1:0.25 2:1 3:1 4:-0.169811 5:-0.3379 6:-1 7:1 8:0.694656 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:-0.125 2:1 3:0.333333 4:-0.132075 5:-0.511416 6:-1 7:-1 8:0.40458 9:-1 10:-0.806452 12:-0.333333 13:1
--1 1:-0.0833333 2:1 3:-1 4:-0.415094 5:-0.60274 6:-1 7:1 8:-0.175573 9:1 10:-0.548387 11:-1 12:-0.333333 13:-1
-+1 1:0.0416667 2:1 3:-0.333333 4:0.849057 5:-0.283105 6:-1 7:1 8:0.89313 9:-1 10:-1 11:-1 12:-0.333333 13:1
-+1 2:1 3:1 4:-0.45283 5:-0.287671 6:-1 7:-1 8:-0.633588 9:1 10:-0.354839 12:0.333333 13:1
-+1 1:-0.0416667 2:1 3:1 4:-0.660377 5:-0.525114 6:-1 7:-1 8:0.358779 9:-1 10:-1 11:-1 12:-0.333333 13:-1
-+1 1:-0.541667 2:1 3:1 4:-0.698113 5:-0.812785 6:-1 7:1 8:-0.343511 9:1 10:-0.354839 12:-1 13:1
-+1 1:0.208333 2:1 3:0.333333 4:-0.283019 5:-0.552511 6:-1 7:1 8:0.557252 9:-1 10:0.0322581 11:-1 12:0.333333 13:1
--1 1:-0.5 2:-1 3:0.333333 4:-0.660377 5:-0.351598 6:-1 7:1 8:0.541985 9:1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.5 2:1 3:0.333333 4:-0.660377 5:-0.43379 6:-1 7:-1 8:0.648855 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.125 2:-1 3:0.333333 4:-0.509434 5:-0.575342 6:-1 7:-1 8:0.328244 9:-1 10:-0.483871 12:-1 13:-1
--1 1:0.0416667 2:-1 3:0.333333 4:-0.735849 5:-0.356164 6:-1 7:1 8:0.465649 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:0.458333 2:-1 3:1 4:-0.320755 5:-0.191781 6:-1 7:-1 8:-0.221374 9:-1 10:-0.354839 12:0.333333 13:-1
--1 1:-0.0833333 2:-1 3:0.333333 4:-0.320755 5:-0.406393 6:-1 7:1 8:0.19084 9:-1 10:-0.83871 11:-1 12:-1 13:-1
--1 1:-0.291667 2:-1 3:-0.333333 4:-0.792453 5:-0.643836 6:-1 7:-1 8:0.541985 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.0833333 2:1 3:1 4:-0.132075 5:-0.584475 6:-1 7:-1 8:-0.389313 9:1 10:0.806452 11:1 12:-1 13:1
--1 1:-0.333333 2:1 3:-0.333333 4:-0.358491 5:-0.16895 6:-1 7:1 8:0.51145 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:0.125 2:1 3:-1 4:-0.509434 5:-0.694064 6:-1 7:1 8:0.389313 9:-1 10:-0.387097 12:-1 13:1
-+1 1:0.541667 2:-1 3:1 4:0.584906 5:-0.534247 6:1 7:-1 8:0.435115 9:1 10:-0.677419 12:0.333333 13:1
-+1 1:-0.625 2:1 3:-1 4:-0.509434 5:-0.520548 6:-1 7:-1 8:0.694656 9:1 10:0.225806 12:-1 13:1
-+1 1:0.375 2:-1 3:1 4:0.0566038 5:-0.461187 6:-1 7:-1 8:0.267176 9:1 10:-0.548387 12:-1 13:-1
--1 1:0.0833333 2:1 3:-0.333333 4:-0.320755 5:-0.378995 6:-1 7:-1 8:0.282443 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.208333 2:1 3:1 4:-0.358491 5:-0.392694 6:-1 7:1 8:-0.0992366 9:1 10:-0.0322581 12:0.333333 13:1
--1 1:-0.416667 2:1 3:1 4:-0.698113 5:-0.611872 6:-1 7:-1 8:0.374046 9:-1 10:-1 11:-1 12:-1 13:1
--1 1:0.458333 2:-1 3:1 4:0.622642 5:-0.0913242 6:-1 7:-1 8:0.267176 9:1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.125 2:-1 3:1 4:-0.698113 5:-0.415525 6:-1 7:1 8:0.343511 9:-1 10:-1 11:-1 12:-1 13:-1
--1 2:1 3:0.333333 4:-0.320755 5:-0.675799 6:1 7:1 8:0.236641 9:-1 10:-0.612903 11:1 12:-1 13:-1
--1 1:-0.333333 2:-1 3:1 4:-0.169811 5:-0.497717 6:-1 7:1 8:0.236641 9:1 10:-0.935484 12:-1 13:-1
-+1 1:0.5 2:1 3:-1 4:-0.169811 5:-0.287671 6:1 7:1 8:0.572519 9:-1 10:-0.548387 12:-0.333333 13:-1
--1 1:0.666667 2:1 3:-1 4:0.245283 5:-0.506849 6:1 7:1 8:-0.0839695 9:-1 10:-0.967742 12:-0.333333 13:-1
-+1 1:0.666667 2:1 3:0.333333 4:-0.132075 5:-0.415525 6:-1 7:1 8:0.145038 9:-1 10:-0.354839 12:1 13:1
-+1 1:0.583333 2:1 3:1 4:-0.886792 5:-0.210046 6:-1 7:1 8:-0.175573 9:1 10:-0.709677 12:0.333333 13:-1
--1 1:0.625 2:-1 3:0.333333 4:-0.509434 5:-0.611872 6:-1 7:1 8:-0.328244 9:-1 10:-0.516129 12:-1 13:-1
--1 1:-0.791667 2:1 3:-1 4:-0.54717 5:-0.744292 6:-1 7:1 8:0.572519 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.375 2:-1 3:1 4:-0.169811 5:-0.232877 6:1 7:-1 8:-0.465649 9:-1 10:-0.387097 12:1 13:-1
-+1 1:-0.0833333 2:1 3:1 4:-0.132075 5:-0.214612 6:-1 7:-1 8:-0.221374 9:1 10:0.354839 12:1 13:1
-+1 1:-0.291667 2:1 3:0.333333 4:0.0566038 5:-0.520548 6:-1 7:-1 8:0.160305 9:-1 10:0.16129 12:-1 13:-1
-+1 1:0.583333 2:1 3:1 4:-0.415094 5:-0.415525 6:1 7:-1 8:0.40458 9:-1 10:-0.935484 12:0.333333 13:1
--1 1:-0.125 2:1 3:0.333333 4:-0.339623 5:-0.680365 6:-1 7:-1 8:0.40458 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.458333 2:1 3:0.333333 4:-0.509434 5:-0.479452 6:1 7:-1 8:0.877863 9:-1 10:-0.741935 11:1 12:-1 13:1
-+1 1:0.125 2:-1 3:1 4:-0.245283 5:0.292237 6:-1 7:1 8:0.206107 9:1 10:-0.387097 12:0.333333 13:1
-+1 1:-0.5 2:1 3:1 4:-0.698113 5:-0.789954 6:-1 7:1 8:0.328244 9:-1 10:-1 11:-1 12:-1 13:1
--1 1:-0.458333 2:-1 3:1 4:-0.849057 5:-0.365297 6:-1 7:1 8:-0.221374 9:-1 10:-0.806452 12:-1 13:-1
--1 2:1 3:0.333333 4:-0.320755 5:-0.452055 6:1 7:1 8:0.557252 9:-1 10:-1 11:-1 12:1 13:-1
--1 1:-0.416667 2:1 3:0.333333 4:-0.320755 5:-0.136986 6:-1 7:-1 8:0.389313 9:-1 10:-0.387097 11:-1 12:-0.333333 13:-1
-+1 1:0.125 2:1 3:1 4:-0.283019 5:-0.73516 6:-1 7:1 8:-0.480916 9:1 10:-0.322581 12:-0.333333 13:0.5
--1 1:-0.0416667 2:1 3:1 4:-0.735849 5:-0.511416 6:1 7:-1 8:0.160305 9:-1 10:-0.967742 11:-1 12:1 13:1
--1 1:0.375 2:-1 3:1 4:-0.132075 5:0.223744 6:-1 7:1 8:0.312977 9:-1 10:-0.612903 12:-1 13:-1
-+1 1:0.708333 2:1 3:0.333333 4:0.245283 5:-0.347032 6:-1 7:-1 8:-0.374046 9:1 10:-0.0645161 12:-0.333333 13:1
--1 1:0.0416667 2:1 3:1 4:-0.132075 5:-0.484018 6:-1 7:-1 8:0.358779 9:-1 10:-0.612903 11:-1 12:-1 13:-1
-+1 1:0.708333 2:1 3:1 4:-0.0377358 5:-0.780822 6:-1 7:-1 8:-0.175573 9:1 10:-0.16129 11:1 12:-1 13:1
--1 1:0.0416667 2:1 3:-0.333333 4:-0.735849 5:-0.164384 6:-1 7:-1 8:0.29771 9:-1 10:-1 11:-1 12:-1 13:1
-+1 1:-0.75 2:1 3:1 4:-0.396226 5:-0.287671 6:-1 7:1 8:0.29771 9:1 10:-1 11:-1 12:-1 13:1
--1 1:-0.208333 2:1 3:0.333333 4:-0.433962 5:-0.410959 6:1 7:-1 8:0.587786 9:-1 10:-1 11:-1 12:0.333333 13:-1
--1 1:0.0833333 2:-1 3:-0.333333 4:-0.226415 5:-0.43379 6:-1 7:1 8:0.374046 9:-1 10:-0.548387 12:-1 13:-1
--1 1:0.208333 2:-1 3:1 4:-0.886792 5:-0.442922 6:-1 7:1 8:-0.221374 9:-1 10:-0.677419 12:-1 13:-1
--1 1:0.0416667 2:-1 3:0.333333 4:-0.698113 5:-0.598174 6:-1 7:-1 8:0.328244 9:-1 10:-0.483871 12:-1 13:-1
--1 1:0.666667 2:-1 3:-1 4:-0.132075 5:-0.484018 6:-1 7:-1 8:0.221374 9:-1 10:-0.419355 11:-1 12:0.333333 13:-1
-+1 1:1 2:1 3:1 4:-0.415094 5:-0.187215 6:-1 7:1 8:0.389313 9:1 10:-1 11:-1 12:1 13:-1
--1 1:0.625 2:1 3:0.333333 4:-0.54717 5:-0.310502 6:-1 7:-1 8:0.221374 9:-1 10:-0.677419 11:-1 12:-0.333333 13:1
-+1 1:0.208333 2:1 3:1 4:-0.415094 5:-0.205479 6:-1 7:1 8:0.526718 9:-1 10:-1 11:-1 12:0.333333 13:1
-+1 1:0.291667 2:1 3:1 4:-0.415094 5:-0.39726 6:-1 7:1 8:0.0687023 9:1 10:-0.0967742 12:-0.333333 13:1
-+1 1:-0.0833333 2:1 3:1 4:-0.132075 5:-0.210046 6:-1 7:-1 8:0.557252 9:1 10:-0.483871 11:-1 12:-1 13:1
-+1 1:0.0833333 2:1 3:1 4:0.245283 5:-0.255708 6:-1 7:1 8:0.129771 9:1 10:-0.741935 12:-0.333333 13:1
--1 1:-0.0416667 2:1 3:-1 4:0.0943396 5:-0.214612 6:1 7:-1 8:0.633588 9:-1 10:-0.612903 12:-1 13:1
--1 1:0.291667 2:-1 3:0.333333 4:-0.849057 5:-0.123288 6:-1 7:-1 8:0.358779 9:-1 10:-1 11:-1 12:-0.333333 13:-1
--1 1:0.208333 2:1 3:0.333333 4:-0.792453 5:-0.479452 6:-1 7:1 8:0.267176 9:1 10:-0.806452 12:-1 13:1
-+1 1:0.458333 2:1 3:0.333333 4:-0.415094 5:-0.164384 6:-1 7:-1 8:-0.0839695 9:1 10:-0.419355 12:-1 13:1
--1 1:-0.666667 2:1 3:0.333333 4:-0.320755 5:-0.43379 6:-1 7:-1 8:0.770992 9:-1 10:0.129032 11:1 12:-1 13:-1
-+1 1:0.25 2:1 3:-1 4:0.433962 5:-0.260274 6:-1 7:1 8:0.343511 9:-1 10:-0.935484 12:-1 13:1
--1 1:-0.0833333 2:1 3:0.333333 4:-0.415094 5:-0.456621 6:1 7:1 8:0.450382 9:-1 10:-0.225806 12:-1 13:-1
--1 1:-0.416667 2:-1 3:0.333333 4:-0.471698 5:-0.60274 6:-1 7:-1 8:0.435115 9:-1 10:-0.935484 12:-1 13:-1
-+1 1:0.208333 2:1 3:1 4:-0.358491 5:-0.589041 6:-1 7:1 8:-0.0839695 9:1 10:-0.290323 12:1 13:1
--1 1:-1 2:1 3:-0.333333 4:-0.320755 5:-0.643836 6:-1 7:1 8:1 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.5 2:-1 3:-0.333333 4:-0.320755 5:-0.643836 6:-1 7:1 8:0.541985 9:-1 10:-0.548387 11:-1 12:-1 13:-1
--1 1:0.416667 2:-1 3:0.333333 4:-0.226415 5:-0.424658 6:-1 7:1 8:0.541985 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.0833333 2:1 3:0.333333 4:-1 5:-0.538813 6:-1 7:-1 8:0.267176 9:1 10:-1 11:-1 12:-0.333333 13:1
--1 1:0.0416667 2:1 3:0.333333 4:-0.509434 5:-0.39726 6:-1 7:1 8:0.160305 9:-1 10:-0.870968 12:-1 13:1
--1 1:-0.375 2:1 3:-0.333333 4:-0.509434 5:-0.570776 6:-1 7:-1 8:0.51145 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.0416667 2:1 3:1 4:-0.698113 5:-0.484018 6:-1 7:-1 8:-0.160305 9:1 10:-0.0967742 12:-0.333333 13:1
-+1 1:0.5 2:1 3:1 4:-0.226415 5:-0.415525 6:-1 7:1 8:-0.145038 9:-1 10:-0.0967742 12:-0.333333 13:1
--1 1:0.166667 2:1 3:0.333333 4:0.0566038 5:-0.808219 6:-1 7:-1 8:0.572519 9:-1 10:-0.483871 11:-1 12:-1 13:-1
-+1 1:0.416667 2:1 3:1 4:-0.320755 5:-0.0684932 6:1 7:1 8:-0.0687023 9:1 10:-0.419355 11:-1 12:1 13:1
--1 1:-0.75 2:-1 3:1 4:-0.169811 5:-0.739726 6:-1 7:-1 8:0.694656 9:-1 10:-0.548387 11:-1 12:-1 13:-1
--1 1:-0.5 2:1 3:-0.333333 4:-0.226415 5:-0.648402 6:-1 7:-1 8:-0.0687023 9:-1 10:-1 12:-1 13:0.5
-+1 1:0.375 2:-1 3:0.333333 4:-0.320755 5:-0.374429 6:-1 7:-1 8:-0.603053 9:-1 10:-0.612903 12:-0.333333 13:1
-+1 1:-0.416667 2:-1 3:1 4:-0.283019 5:-0.0182648 6:1 7:1 8:-0.00763359 9:1 10:-0.0322581 12:-1 13:1
--1 1:0.208333 2:-1 3:-1 4:0.0566038 5:-0.283105 6:1 7:1 8:0.389313 9:-1 10:-0.677419 11:-1 12:-1 13:-1
--1 1:-0.0416667 2:1 3:-1 4:-0.54717 5:-0.726027 6:-1 7:1 8:0.816794 9:-1 10:-1 12:-1 13:0.5
-+1 1:0.333333 2:-1 3:1 4:-0.0377358 5:-0.173516 6:-1 7:1 8:0.145038 9:1 10:-0.677419 12:-1 13:1
-+1 1:-0.583333 2:1 3:1 4:-0.54717 5:-0.575342 6:-1 7:-1 8:0.0534351 9:-1 10:-0.612903 12:-1 13:1
--1 1:-0.333333 2:1 3:1 4:-0.603774 5:-0.388128 6:-1 7:1 8:0.740458 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:-0.0416667 2:1 3:1 4:-0.358491 5:-0.410959 6:-1 7:-1 8:0.374046 9:1 10:-1 11:-1 12:-0.333333 13:1
--1 1:0.375 2:1 3:0.333333 4:-0.320755 5:-0.520548 6:-1 7:-1 8:0.145038 9:-1 10:-0.419355 12:1 13:1
-+1 1:0.375 2:-1 3:1 4:0.245283 5:-0.826484 6:-1 7:1 8:0.129771 9:-1 10:1 11:1 12:1 13:1
--1 2:-1 3:1 4:-0.169811 5:-0.506849 6:-1 7:1 8:0.358779 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:-0.416667 2:1 3:1 4:-0.509434 5:-0.767123 6:-1 7:1 8:-0.251908 9:1 10:-0.193548 12:-1 13:1
--1 1:-0.25 2:1 3:0.333333 4:-0.169811 5:-0.401826 6:-1 7:1 8:0.29771 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.0416667 2:1 3:-0.333333 4:-0.509434 5:-0.0913242 6:-1 7:-1 8:0.541985 9:-1 10:-0.935484 11:-1 12:-1 13:-1
-+1 1:0.625 2:1 3:0.333333 4:0.622642 5:-0.324201 6:1 7:1 8:0.206107 9:1 10:-0.483871 12:-1 13:1
--1 1:-0.583333 2:1 3:0.333333 4:-0.132075 5:-0.109589 6:-1 7:1 8:0.694656 9:-1 10:-1 11:-1 12:-1 13:-1
--1 2:-1 3:1 4:-0.320755 5:-0.369863 6:-1 7:1 8:0.0992366 9:-1 10:-0.870968 12:-1 13:-1
-+1 1:0.375 2:-1 3:1 4:-0.132075 5:-0.351598 6:-1 7:1 8:0.358779 9:-1 10:0.16129 11:1 12:0.333333 13:-1
--1 1:-0.0833333 2:-1 3:0.333333 4:-0.132075 5:-0.16895 6:-1 7:1 8:0.0839695 9:-1 10:-0.516129 11:-1 12:-0.333333 13:-1
-+1 1:0.291667 2:1 3:1 4:-0.320755 5:-0.420091 6:-1 7:-1 8:0.114504 9:1 10:-0.548387 11:-1 12:-0.333333 13:1
-+1 1:0.5 2:1 3:1 4:-0.698113 5:-0.442922 6:-1 7:1 8:0.328244 9:-1 10:-0.806452 11:-1 12:0.333333 13:0.5
--1 1:0.5 2:-1 3:0.333333 4:0.150943 5:-0.347032 6:-1 7:-1 8:0.175573 9:-1 10:-0.741935 11:-1 12:-1 13:-1
-+1 1:0.291667 2:1 3:0.333333 4:-0.132075 5:-0.730594 6:-1 7:1 8:0.282443 9:-1 10:-0.0322581 12:-1 13:-1
-+1 1:0.291667 2:1 3:1 4:-0.0377358 5:-0.287671 6:-1 7:1 8:0.0839695 9:1 10:-0.0967742 12:0.333333 13:1
-+1 1:0.0416667 2:1 3:1 4:-0.509434 5:-0.716895 6:-1 7:-1 8:-0.358779 9:-1 10:-0.548387 12:-0.333333 13:1
--1 1:-0.375 2:1 3:-0.333333 4:-0.320755 5:-0.575342 6:-1 7:1 8:0.78626 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:-0.375 2:1 3:1 4:-0.660377 5:-0.251142 6:-1 7:1 8:0.251908 9:-1 10:-1 11:-1 12:-0.333333 13:-1
--1 1:-0.0833333 2:1 3:0.333333 4:-0.698113 5:-0.776256 6:-1 7:-1 8:-0.206107 9:-1 10:-0.806452 11:-1 12:-1 13:-1
--1 1:0.25 2:1 3:0.333333 4:0.0566038 5:-0.607306 6:1 7:-1 8:0.312977 9:-1 10:-0.483871 11:-1 12:-1 13:-1
--1 1:0.75 2:-1 3:-0.333333 4:0.245283 5:-0.196347 6:-1 7:-1 8:0.389313 9:-1 10:-0.870968 11:-1 12:0.333333 13:-1
--1 1:0.333333 2:1 3:0.333333 4:0.0566038 5:-0.465753 6:1 7:-1 8:0.00763359 9:1 10:-0.677419 12:-1 13:-1
-+1 1:0.0833333 2:1 3:1 4:-0.283019 5:0.0365297 6:-1 7:-1 8:-0.0687023 9:1 10:-0.612903 12:-0.333333 13:1
-+1 1:0.458333 2:1 3:0.333333 4:-0.132075 5:-0.0456621 6:-1 7:-1 8:0.328244 9:-1 10:-1 11:-1 12:-1 13:-1
--1 1:-0.416667 2:1 3:1 4:0.0566038 5:-0.447489 6:-1 7:-1 8:0.526718 9:-1 10:-0.516129 11:-1 12:-1 13:-1
--1 1:0.208333 2:-1 3:0.333333 4:-0.509434 5:-0.0228311 6:-1 7:-1 8:0.541985 9:-1 10:-1 11:-1 12:-1 13:-1
-+1 1:0.291667 2:1 3:1 4:-0.320755 5:-0.634703 6:-1 7:1 8:-0.0687023 9:1 10:-0.225806 12:0.333333 13:1
-+1 1:0.208333 2:1 3:-0.333333 4:-0.509434 5:-0.278539 6:-1 7:1 8:0.358779 9:-1 10:-0.419355 12:-1 13:-1
--1 1:-0.166667 2:1 3:-0.333333 4:-0.320755 5:-0.360731 6:-1 7:-1 8:0.526718 9:-1 10:-0.806452 11:-1 12:-1 13:-1
-+1 1:-0.208333 2:1 3:-0.333333 4:-0.698113 5:-0.52968 6:-1 7:-1 8:0.480916 9:-1 10:-0.677419 11:1 12:-1 13:1
--1 1:-0.0416667 2:1 3:0.333333 4:0.471698 5:-0.666667 6:1 7:-1 8:0.389313 9:-1 10:-0.83871 11:-1 12:-1 13:1
--1 1:-0.375 2:1 3:-0.333333 4:-0.509434 5:-0.374429 6:-1 7:-1 8:0.557252 9:-1 10:-1 11:-1 12:-1 13:1
--1 1:0.125 2:-1 3:-0.333333 4:-0.132075 5:-0.232877 6:-1 7:1 8:0.251908 9:-1 10:-0.580645 12:-1 13:-1
--1 1:0.166667 2:1 3:1 4:-0.132075 5:-0.69863 6:-1 7:-1 8:0.175573 9:-1 10:-0.870968 12:-1 13:0.5
-+1 1:0.583333 2:1 3:1 4:0.245283 5:-0.269406 6:-1 7:1 8:-0.435115 9:1 10:-0.516129 12:1 13:-1
diff --git a/Modules/Classification/CLLibSVM/licence/heart_scale.wgt b/Modules/Classification/CLLibSVM/licence/heart_scale.wgt
deleted file mode 100644
index 5aed1f67ae..0000000000
--- a/Modules/Classification/CLLibSVM/licence/heart_scale.wgt
+++ /dev/null
@@ -1,270 +0,0 @@
-20
-10
-5.5
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
diff --git a/Modules/Classification/CLLibSVM/src/mitkLibSVMClassifier.cpp b/Modules/Classification/CLLibSVM/src/mitkLibSVMClassifier.cpp
deleted file mode 100644
index 67f335c458..0000000000
--- a/Modules/Classification/CLLibSVM/src/mitkLibSVMClassifier.cpp
+++ /dev/null
@@ -1,336 +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 <mitkLibSVMClassifier.h>
-
-#include <mitkConfigurationHolder.h>
-#include <svm.h>
-#include <mitkExceptionMacro.h>
-
-mitk::LibSVMClassifier::LibSVMClassifier():
- m_Model(nullptr),m_Parameter(nullptr)
-{
- this->m_Parameter = new svm_parameter();
-}
-
-mitk::LibSVMClassifier::~LibSVMClassifier()
-{
- if (m_Model)
- {
- svm_free_and_destroy_model(&m_Model);
- }
- if( m_Parameter)
- svm_destroy_param(m_Parameter);
-}
-
-void mitk::LibSVMClassifier::Train(const Eigen::MatrixXd &X, const Eigen::MatrixXi &Y)
-{
- this->SetPointWiseWeight(Eigen::MatrixXd(Y.rows(),1));
- this->UsePointWiseWeight(false);
-
- svm_node *xSpace;
- svm_problem problem;
-
- ConvertParameter();
- ReadYValues(&problem, Y);
- ReadXValues(&problem, &xSpace,X);
- ReadWValues(&problem);
-
- const char * error_msg = nullptr;
- error_msg = svm_check_parameter(&problem, m_Parameter);
- if (error_msg)
- {
- svm_destroy_param(m_Parameter);
- free(problem.y);
- free(problem.x);
- free(xSpace);
- mitkThrow() << "Error: " << error_msg;
- }
-
- m_Model = svm_train(&problem, m_Parameter);
-
- // free(problem.y);
- // free(problem.x);
- // free(xSpace);
-}
-
-Eigen::MatrixXi mitk::LibSVMClassifier::Predict(const Eigen::MatrixXd &X)
-{
- if ( ! m_Model)
- {
- mitkThrow() << "No Model is trained. Train or load a model before predicting new values.";
- }
- auto noOfPoints = static_cast<int>(X.rows());
- auto noOfFeatures = static_cast<int>(X.cols());
-
- Eigen::MatrixXi result(noOfPoints,1);
-
- auto * xVector = static_cast<svm_node *>(malloc(sizeof(svm_node) * (noOfFeatures+1)));
- for (int point = 0; point < noOfPoints; ++point)
- {
- for (int feature = 0; feature < noOfFeatures; ++feature)
- {
- xVector[feature].index = feature+1;
- xVector[feature].value = X(point, feature);
- }
- xVector[noOfFeatures].index = -1;
- result(point,0) = svm_predict(m_Model,xVector);
- }
-
- free(xVector);
- return result;
-}
-
-void mitk::LibSVMClassifier::ConvertParameter()
-{
- // Get the proerty // Some defaults
- if(!this->GetPropertyList()->Get("classifier.svm.svm-type",this->m_Parameter->svm_type)) this->m_Parameter->svm_type = 0;
- if(!this->GetPropertyList()->Get("classifier.svm.kernel-type",this->m_Parameter->kernel_type)) this->m_Parameter->kernel_type = 2;
- if(!this->GetPropertyList()->Get("classifier.svm.degree",this->m_Parameter->degree)) this->m_Parameter->degree = 3;
- if(!this->GetPropertyList()->Get("classifier.svm.gamma",this->m_Parameter->gamma)) this->m_Parameter->gamma = 0; // 1/n_features;
- if(!this->GetPropertyList()->Get("classifier.svm.coef0",this->m_Parameter->coef0)) this->m_Parameter->coef0 = 0;
- if(!this->GetPropertyList()->Get("classifier.svm.nu",this->m_Parameter->nu)) this->m_Parameter->nu = 0.5;
- if(!this->GetPropertyList()->Get("classifier.svm.cache-size",this->m_Parameter->cache_size)) this->m_Parameter->cache_size = 100.0;
- if(!this->GetPropertyList()->Get("classifier.svm.c",this->m_Parameter->C)) this->m_Parameter->C = 1.0;
- if(!this->GetPropertyList()->Get("classifier.svm.eps",this->m_Parameter->eps)) this->m_Parameter->eps = 1e-3;
- if(!this->GetPropertyList()->Get("classifier.svm.p",this->m_Parameter->p)) this->m_Parameter->p = 0.1;
- if(!this->GetPropertyList()->Get("classifier.svm.shrinking",this->m_Parameter->shrinking)) this->m_Parameter->shrinking = 1;
- if(!this->GetPropertyList()->Get("classifier.svm.probability",this->m_Parameter->probability)) this->m_Parameter->probability = 0;
- if(!this->GetPropertyList()->Get("classifier.svm.nr-weight",this->m_Parameter->nr_weight)) this->m_Parameter->nr_weight = 0;
-
- //options:
- //-s svm_type : set type of SVM (default 0)
- // 0 -- C-SVC
- // 1 -- nu-SVC
- // 2 -- one-class SVM
- // 3 -- epsilon-SVR
- // 4 -- nu-SVR
- //-t kernel_type : set type of kernel function (default 2)
- // 0 -- linear: u'*v
- // 1 -- polynomial: (gamma*u'*v + coef0)^degree
- // 2 -- radial basis function: exp(-gamma*|u-v|^2)
- // 3 -- sigmoid: tanh(gamma*u'*v + coef0)
- //-d degree : set degree in kernel function (default 3)
- //-g gamma : set gamma in kernel function (default 1/num_features)
- //-r coef0 : set coef0 in kernel function (default 0)
- //-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
- //-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
- //-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
- //-m cachesize : set cache memory size in MB (default 100)
- //-e epsilon : set tolerance of termination criterion (default 0.001)
- //-h shrinking: whether to use the shrinking heuristics, 0 or 1 (default 1)
- //-b probability_estimates: whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)
- //-wiweight: set the parameter C of class i to weight*C, for C-SVC (default 1)
-
- // this->m_Parameter->weight_label = nullptr;
- // this->m_Parameter->weight = 1;
-}
-
-/* these are for training only */
-//int *weight_label; /* for C_SVC */
-//double* weight; /* for C_SVC */
-
-void mitk::LibSVMClassifier::SetProbability(int val)
-{
- this->GetPropertyList()->SetIntProperty("classifier.svm.probability",val);
-}
-
-void mitk::LibSVMClassifier::SetShrinking(int val)
-{
- this->GetPropertyList()->SetIntProperty("classifier.svm.shrinking",val);
-}
-
-void mitk::LibSVMClassifier::SetNrWeight(int val)
-{
- this->GetPropertyList()->SetIntProperty("classifier.svm.nr_weight",val);
-}
-
-void mitk::LibSVMClassifier::SetNu(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("classifier.svm.nu",val);
-}
-
-void mitk::LibSVMClassifier::SetP(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("classifier.svm.p",val);
-}
-
-void mitk::LibSVMClassifier::SetEps(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("classifier.svm.eps",val);
-}
-
-void mitk::LibSVMClassifier::SetC(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("classifier.svm.c",val);
-}
-
-void mitk::LibSVMClassifier::SetCacheSize(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("classifier.svm.cache-size",val);
-}
-
-void mitk::LibSVMClassifier::SetSvmType(int val)
-{
- this->GetPropertyList()->SetIntProperty("classifier.svm.svm-type",val);
-}
-
-void mitk::LibSVMClassifier::SetKernelType(int val)
-{
- this->GetPropertyList()->SetIntProperty("classifier.svm.kernel-type",val);
-}
-
-void mitk::LibSVMClassifier::SetDegree(int val)
-{
- this->GetPropertyList()->SetIntProperty("classifier.svm.degree",val);
-}
-
-void mitk::LibSVMClassifier::SetGamma(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("classifier.svm.gamma",val);
-}
-
-void mitk::LibSVMClassifier::SetCoef0(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("classifier.svm.coef0",val);
-}
-
-void mitk::LibSVMClassifier::PrintParameter(std::ostream & str)
-{
- if(this->m_Parameter == nullptr)
- {
- MITK_WARN("LibSVMClassifier") << "Parameters are not initialized. Please call ConvertParameter() first!";
- return;
- }
-
- this->ConvertParameter();
-
- // Get the proerty // Some defaults
- if(!this->GetPropertyList()->Get("classifier.svm.svm-type",this->m_Parameter->svm_type))
- str << "classifier.svm.svm-type\tNOT SET (default " << this->m_Parameter->svm_type << ")" << "\n";
- else
- str << "classifier.svm.svm-type\t" << this->m_Parameter->svm_type << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.kernel-type",this->m_Parameter->kernel_type))
- str << "classifier.svm.kernel-type\tNOT SET (default " << this->m_Parameter->kernel_type << ")" << "\n";
- else
- str << "classifier.svm.kernel-type\t" << this->m_Parameter->kernel_type << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.degree",this->m_Parameter->degree))
- str << "classifier.svm.degree\t\tNOT SET (default " << this->m_Parameter->degree << ")" << "\n";
- else
- str << "classifier.svm.degree\t\t" << this->m_Parameter->degree << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.gamma",this->m_Parameter->gamma))
- str << "classifier.svm.gamma\t\tNOT SET (default " << this->m_Parameter->gamma << ")" << "\n";
- else
- str << "classifier.svm.gamma\t\t" << this->m_Parameter->gamma << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.coef0",this->m_Parameter->coef0))
- str << "classifier.svm.coef0\t\tNOT SET (default " << this->m_Parameter->coef0 << ")" << "\n";
- else
- str << "classifier.svm.coef0\t\t" << this->m_Parameter->coef0 << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.nu",this->m_Parameter->nu))
- str << "classifier.svm.nu\t\tNOT SET (default " << this->m_Parameter->nu << ")" << "\n";
- else
- str << "classifier.svm.nu\t\t" << this->m_Parameter->nu << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.cache-size",this->m_Parameter->cache_size))
- str << "classifier.svm.cache-size\tNOT SET (default " << this->m_Parameter->cache_size << ")" << "\n";
- else
- str << "classifier.svm.cache-size\t" << this->m_Parameter->cache_size << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.c",this->m_Parameter->C))
- str << "classifier.svm.c\t\tNOT SET (default " << this->m_Parameter->C << ")" << "\n";
- else
- str << "classifier.svm.c\t\t" << this->m_Parameter->C << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.eps",this->m_Parameter->eps))
- str << "classifier.svm.eps\t\tNOT SET (default " << this->m_Parameter->eps << ")" << "\n";
- else
- str << "classifier.svm.eps\t\t" << this->m_Parameter->eps << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.p",this->m_Parameter->p))
- str << "classifier.svm.p\t\tNOT SET (default " << this->m_Parameter->p << ")" << "\n";
- else
- str << "classifier.svm.p\t\t" << this->m_Parameter->p << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.shrinking",this->m_Parameter->shrinking))
- str << "classifier.svm.shrinking\tNOT SET (default " << this->m_Parameter->shrinking << ")" << "\n";
- else
- str << "classifier.svm.shrinking\t" << this->m_Parameter->shrinking << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.probability",this->m_Parameter->probability))
- str << "classifier.svm.probability\tNOT SET (default " << this->m_Parameter->probability << ")" << "\n";
- else
- str << "classifier.svm.probability\t" << this->m_Parameter->probability << "\n";
-
- if(!this->GetPropertyList()->Get("classifier.svm.nr-weight",this->m_Parameter->nr_weight))
- str << "classifier.svm.nr-weight\tNOT SET (default " << this->m_Parameter->nr_weight << ")" << "\n";
- else
- str << "classifier.svm.nr-weight\t" << this->m_Parameter->nr_weight << "\n";
-}
-
-// Trying to assign from matrix to noOfPoints
-void mitk::LibSVMClassifier::ReadXValues(svm_problem * problem, svm_node** xSpace, const Eigen::MatrixXd &X)
-{
- auto noOfPoints = static_cast<int>(X.rows());
- auto features = static_cast<int>(X.cols());
-
- problem->x = static_cast<svm_node **>(malloc(sizeof(svm_node *) * noOfPoints));
- (*xSpace) = static_cast<svm_node *> (malloc(sizeof(svm_node) * noOfPoints * (features+1)));
-
- for (int row = 0; row < noOfPoints; ++row)
- {
- for (int col = 0; col < features; ++col)
- {
- (*xSpace)[row*features + col].index = col;
- (*xSpace)[row*features + col].value = X(row,col);
- }
- (*xSpace)[row*features + features].index = -1;
-
- problem->x[row] = &((*xSpace)[row*features]);
- }
-}
-
-void mitk::LibSVMClassifier::ReadYValues(svm_problem * problem, const Eigen::MatrixXi &Y)
-{
- problem->l = static_cast<int>(Y.rows());
- problem->y = static_cast<double *>(malloc(sizeof(double) * problem->l));
-
- for (int i = 0; i < problem->l; ++i)
- {
- problem->y[i] = Y(i,0);
- }
-}
-
-void mitk::LibSVMClassifier::ReadWValues(svm_problem * problem)
-{
- Eigen::MatrixXd & W = this->GetPointWiseWeight();
- int noOfPoints = problem->l;
- problem->W = static_cast<double *>(malloc(sizeof(double) * noOfPoints));
-
- if (IsUsingPointWiseWeight())
- {
- for (int i = 0; i < noOfPoints; ++i)
- {
- problem->W[i] = W(i,0);
- }
- } else
- {
- for (int i = 0; i < noOfPoints; ++i)
- {
- problem->W[i] = 1;
- }
- }
-}
diff --git a/Modules/Classification/CLLibSVM/src/svm-predict.c b/Modules/Classification/CLLibSVM/src/svm-predict.c
deleted file mode 100644
index 7b46f31e28..0000000000
--- a/Modules/Classification/CLLibSVM/src/svm-predict.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*============================================================================
-
-libsvm
-
-Copyright (c) 2000-2019 Chih-Chung Chang and Chih-Jen Lin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-3. Neither name of copyright holders nor the names of its contributors
-may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-============================================================================*/
-
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include "svm.h"
-
-int print_null(const char */*s*/,...) {return 0;}
-
-static int (*info)(const char *fmt,...) = &printf;
-
-struct svm_node *x;
-int max_nr_attr = 64;
-
-struct svm_model* model;
-int predict_probability=0;
-
-static char *line = NULL;
-static int max_line_len;
-
-static char* readline(FILE *input)
-{
- int len;
-
- if(fgets(line,max_line_len,input) == NULL)
- return NULL;
-
- while(strrchr(line,'\n') == NULL)
- {
- max_line_len *= 2;
- line = (char *) realloc(line,max_line_len);
- len = (int) strlen(line);
- if(fgets(line+len,max_line_len-len,input) == NULL)
- break;
- }
- return line;
-}
-
-void exit_input_error(int line_num)
-{
- fprintf(stderr,"Wrong input format at line %d\n", line_num);
- exit(1);
-}
-
-void predict(FILE *input, FILE *output)
-{
- int correct = 0;
- int total = 0;
- double error = 0;
- double sump = 0, sumt = 0, sumpp = 0, sumtt = 0, sumpt = 0;
-
- int svm_type=svm_get_svm_type(model);
- int nr_class=svm_get_nr_class(model);
- double *prob_estimates=NULL;
- int j;
-
- if(predict_probability)
- {
- if (svm_type==NU_SVR || svm_type==EPSILON_SVR)
- info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=%g\n",svm_get_svr_probability(model));
- else
- {
- int *labels=(int *) malloc(nr_class*sizeof(int));
- svm_get_labels(model,labels);
- prob_estimates = (double *) malloc(nr_class*sizeof(double));
- fprintf(output,"labels");
- for(j=0;j<nr_class;j++)
- fprintf(output," %d",labels[j]);
- fprintf(output,"\n");
- free(labels);
- }
- }
-
- max_line_len = 1024;
- line = (char *)malloc(max_line_len*sizeof(char));
- while(readline(input) != NULL)
- {
- int i = 0;
- double target_label, predict_label;
- char *idx, *val, *label, *endptr;
- int inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0
-
- label = strtok(line," \t\n");
- if(label == NULL) // empty line
- exit_input_error(total+1);
-
- target_label = strtod(label,&endptr);
- if(endptr == label || *endptr != '\0')
- exit_input_error(total+1);
-
- while(1)
- {
- if(i>=max_nr_attr-1) // need one more for index = -1
- {
- max_nr_attr *= 2;
- x = (struct svm_node *) realloc(x,max_nr_attr*sizeof(struct svm_node));
- }
-
- idx = strtok(NULL,":");
- val = strtok(NULL," \t");
-
- if(val == NULL)
- break;
- errno = 0;
- x[i].index = (int) strtol(idx,&endptr,10);
- if(endptr == idx || errno != 0 || *endptr != '\0' || x[i].index <= inst_max_index)
- exit_input_error(total+1);
- else
- inst_max_index = x[i].index;
-
- errno = 0;
- x[i].value = strtod(val,&endptr);
- if(endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
- exit_input_error(total+1);
-
- ++i;
- }
- x[i].index = -1;
-
- if (predict_probability && (svm_type==C_SVC || svm_type==NU_SVC))
- {
- predict_label = svm_predict_probability(model,x,prob_estimates);
- fprintf(output,"%g",predict_label);
- for(j=0;j<nr_class;j++)
- fprintf(output," %g",prob_estimates[j]);
- fprintf(output,"\n");
- }
- else
- {
- predict_label = svm_predict(model,x);
- fprintf(output,"%g\n",predict_label);
- }
-
- if(predict_label == target_label)
- ++correct;
- error += (predict_label-target_label)*(predict_label-target_label);
- sump += predict_label;
- sumt += target_label;
- sumpp += predict_label*predict_label;
- sumtt += target_label*target_label;
- sumpt += predict_label*target_label;
- ++total;
- }
- if (svm_type==NU_SVR || svm_type==EPSILON_SVR)
- {
- info("Mean squared error = %g (regression)\n",error/total);
- info("Squared correlation coefficient = %g (regression)\n",
- ((total*sumpt-sump*sumt)*(total*sumpt-sump*sumt))/
- ((total*sumpp-sump*sump)*(total*sumtt-sumt*sumt))
- );
- }
- else
- info("Accuracy = %g%% (%d/%d) (classification)\n",
- (double)correct/total*100,correct,total);
- if(predict_probability)
- free(prob_estimates);
-}
-
-void exit_with_help()
-{
- printf(
- "Usage: svm-predict [options] test_file model_file output_file\n"
- "options:\n"
- "-b probability_estimates: whether to predict probability estimates, 0 or 1 (default 0); for one-class SVM only 0 is supported\n"
- "-q : quiet mode (no outputs)\n"
- );
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- FILE *input, *output;
- int i;
- // parse options
- for(i=1;i<argc;i++)
- {
- if(argv[i][0] != '-') break;
- ++i;
- switch(argv[i-1][1])
- {
- case 'b':
- predict_probability = atoi(argv[i]);
- break;
- case 'q':
- info = &print_null;
- i--;
- break;
- default:
- fprintf(stderr,"Unknown option: -%c\n", argv[i-1][1]);
- exit_with_help();
- }
- }
-
- if(i>=argc-2)
- exit_with_help();
-
- input = fopen(argv[i],"r");
- if(input == NULL)
- {
- fprintf(stderr,"can't open input file %s\n",argv[i]);
- exit(1);
- }
-
- output = fopen(argv[i+2],"w");
- if(output == NULL)
- {
- fprintf(stderr,"can't open output file %s\n",argv[i+2]);
- exit(1);
- }
-
- if((model=svm_load_model(argv[i+1]))==0)
- {
- fprintf(stderr,"can't open model file %s\n",argv[i+1]);
- exit(1);
- }
-
- x = (struct svm_node *) malloc(max_nr_attr*sizeof(struct svm_node));
- if(predict_probability)
- {
- if(svm_check_probability_model(model)==0)
- {
- fprintf(stderr,"Model does not support probabiliy estimates\n");
- exit(1);
- }
- }
- else
- {
- if(svm_check_probability_model(model)!=0)
- info("Model supports probability estimates, but disabled in prediction.\n");
- }
-
- predict(input,output);
- svm_free_and_destroy_model(&model);
- free(x);
- free(line);
- fclose(input);
- fclose(output);
- return 0;
-}
diff --git a/Modules/Classification/CLLibSVM/src/svm-scale.c b/Modules/Classification/CLLibSVM/src/svm-scale.c
deleted file mode 100644
index 6aab28a322..0000000000
--- a/Modules/Classification/CLLibSVM/src/svm-scale.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*============================================================================
-
-libsvm
-
-Copyright (c) 2000-2019 Chih-Chung Chang and Chih-Jen Lin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-3. Neither name of copyright holders nor the names of its contributors
-may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-============================================================================*/
-
-#include <float.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-void exit_with_help()
-{
- printf(
- "Usage: svm-scale [options] data_filename\n"
- "options:\n"
- "-l lower : x scaling lower limit (default -1)\n"
- "-u upper : x scaling upper limit (default +1)\n"
- "-y y_lower y_upper : y scaling limits (default: no y scaling)\n"
- "-s save_filename : save scaling parameters to save_filename\n"
- "-r restore_filename : restore scaling parameters from restore_filename\n"
- );
- exit(1);
-}
-
-char *line = NULL;
-int max_line_len = 1024;
-double lower=-1.0,upper=1.0,y_lower,y_upper;
-int y_scaling = 0;
-double *feature_max;
-double *feature_min;
-double y_max = -DBL_MAX;
-double y_min = DBL_MAX;
-int max_index;
-int min_index;
-long int num_nonzeros = 0;
-long int new_num_nonzeros = 0;
-
-#define max(x,y) (((x)>(y))?(x):(y))
-#define min(x,y) (((x)<(y))?(x):(y))
-
-void output_target(double value);
-void output(int index, double value);
-char* readline(FILE *input);
-int clean_up(FILE *fp_restore, FILE *fp, const char *msg);
-
-int main(int argc,char **argv)
-{
- int i,index;
- FILE *fp, *fp_restore = NULL;
- char *save_filename = NULL;
- char *restore_filename = NULL;
-
- for(i=1;i<argc;i++)
- {
- if(argv[i][0] != '-') break;
- ++i;
- switch(argv[i-1][1])
- {
- case 'l': lower = atof(argv[i]); break;
- case 'u': upper = atof(argv[i]); break;
- case 'y':
- y_lower = atof(argv[i]);
- ++i;
- y_upper = atof(argv[i]);
- y_scaling = 1;
- break;
- case 's': save_filename = argv[i]; break;
- case 'r': restore_filename = argv[i]; break;
- default:
- fprintf(stderr,"unknown option\n");
- exit_with_help();
- }
- }
-
- if(!(upper > lower) || (y_scaling && !(y_upper > y_lower)))
- {
- fprintf(stderr,"inconsistent lower/upper specification\n");
- exit(1);
- }
-
- if(restore_filename && save_filename)
- {
- fprintf(stderr,"cannot use -r and -s simultaneously\n");
- exit(1);
- }
-
- if(argc != i+1)
- exit_with_help();
-
- fp=fopen(argv[i],"r");
-
- if(fp==NULL)
- {
- fprintf(stderr,"can't open file %s\n", argv[i]);
- exit(1);
- }
-
- line = (char *) malloc(max_line_len*sizeof(char));
-
-#define SKIP_TARGET\
- while(isspace(*p)) ++p;\
- while(!isspace(*p)) ++p;
-
-#define SKIP_ELEMENT\
- while(*p!=':') ++p;\
- ++p;\
- while(isspace(*p)) ++p;\
- while(*p && !isspace(*p)) ++p;
-
- /* assumption: min index of attributes is 1 */
- /* pass 1: find out max index of attributes */
- max_index = 0;
- min_index = 1;
-
- if(restore_filename)
- {
- int idx, c;
-
- fp_restore = fopen(restore_filename,"r");
- if(fp_restore==NULL)
- {
- fprintf(stderr,"can't open file %s\n", restore_filename);
- exit(1);
- }
-
- c = fgetc(fp_restore);
- if(c == 'y')
- {
- readline(fp_restore);
- readline(fp_restore);
- readline(fp_restore);
- }
- readline(fp_restore);
- readline(fp_restore);
-
- while(fscanf(fp_restore,"%d %*f %*f\n",&idx) == 1)
- max_index = max(idx,max_index);
- rewind(fp_restore);
- }
-
- while(readline(fp)!=NULL)
- {
- char *p=line;
-
- SKIP_TARGET
-
- while(sscanf(p,"%d:%*f",&index)==1)
- {
- max_index = max(max_index, index);
- min_index = min(min_index, index);
- SKIP_ELEMENT
- num_nonzeros++;
- }
- }
-
- if(min_index < 1)
- fprintf(stderr,
- "WARNING: minimal feature index is %d, but indices should start from 1\n", min_index);
-
- rewind(fp);
-
- feature_max = (double *)malloc((max_index+1)* sizeof(double));
- feature_min = (double *)malloc((max_index+1)* sizeof(double));
-
- if(feature_max == NULL || feature_min == NULL)
- {
- fprintf(stderr,"can't allocate enough memory\n");
- exit(1);
- }
-
- for(i=0;i<=max_index;i++)
- {
- feature_max[i]=-DBL_MAX;
- feature_min[i]=DBL_MAX;
- }
-
- /* pass 2: find out min/max value */
- while(readline(fp)!=NULL)
- {
- char *p=line;
- int next_index=1;
- double target;
- double value;
-
- if (sscanf(p,"%lf",&target) != 1)
- return clean_up(fp_restore, fp, "ERROR: failed to read labels\n");
- y_max = max(y_max,target);
- y_min = min(y_min,target);
-
- SKIP_TARGET
-
- while(sscanf(p,"%d:%lf",&index,&value)==2)
- {
- for(i=next_index;i<index;i++)
- {
- feature_max[i]=max(feature_max[i],0);
- feature_min[i]=min(feature_min[i],0);
- }
-
- feature_max[index]=max(feature_max[index],value);
- feature_min[index]=min(feature_min[index],value);
-
- SKIP_ELEMENT
- next_index=index+1;
- }
-
- for(i=next_index;i<=max_index;i++)
- {
- feature_max[i]=max(feature_max[i],0);
- feature_min[i]=min(feature_min[i],0);
- }
- }
-
- rewind(fp);
-
- /* pass 2.5: save/restore feature_min/feature_max */
-
- if(restore_filename)
- {
- /* fp_restore rewinded in finding max_index */
- int idx, c;
- double fmin, fmax;
- int next_index = 1;
-
- if((c = fgetc(fp_restore)) == 'y')
- {
- if(fscanf(fp_restore, "%lf %lf\n", &y_lower, &y_upper) != 2 ||
- fscanf(fp_restore, "%lf %lf\n", &y_min, &y_max) != 2)
- return clean_up(fp_restore, fp, "ERROR: failed to read scaling parameters\n");
- y_scaling = 1;
- }
- else
- ungetc(c, fp_restore);
-
- if (fgetc(fp_restore) == 'x')
- {
- if(fscanf(fp_restore, "%lf %lf\n", &lower, &upper) != 2)
- return clean_up(fp_restore, fp, "ERROR: failed to read scaling parameters\n");
- while(fscanf(fp_restore,"%d %lf %lf\n",&idx,&fmin,&fmax)==3)
- {
- for(i = next_index;i<idx;i++)
- if(feature_min[i] != feature_max[i])
- fprintf(stderr,
- "WARNING: feature index %d appeared in file %s was not seen in the scaling factor file %s.\n",
- i, argv[argc-1], restore_filename);
-
- feature_min[idx] = fmin;
- feature_max[idx] = fmax;
-
- next_index = idx + 1;
- }
-
- for(i=next_index;i<=max_index;i++)
- if(feature_min[i] != feature_max[i])
- fprintf(stderr,
- "WARNING: feature index %d appeared in file %s was not seen in the scaling factor file %s.\n",
- i, argv[argc-1], restore_filename);
- }
- fclose(fp_restore);
- }
-
- if(save_filename)
- {
- FILE *fp_save = fopen(save_filename,"w");
- if(fp_save==NULL)
- {
- fprintf(stderr,"can't open file %s\n", save_filename);
- exit(1);
- }
- if(y_scaling)
- {
- fprintf(fp_save, "y\n");
- fprintf(fp_save, "%.16g %.16g\n", y_lower, y_upper);
- fprintf(fp_save, "%.16g %.16g\n", y_min, y_max);
- }
- fprintf(fp_save, "x\n");
- fprintf(fp_save, "%.16g %.16g\n", lower, upper);
- for(i=1;i<=max_index;i++)
- {
- if(feature_min[i]!=feature_max[i])
- fprintf(fp_save,"%d %.16g %.16g\n",i,feature_min[i],feature_max[i]);
- }
-
- if(min_index < 1)
- fprintf(stderr,
- "WARNING: scaling factors with indices smaller than 1 are not stored to the file %s.\n", save_filename);
-
- fclose(fp_save);
- }
-
- /* pass 3: scale */
- while(readline(fp)!=NULL)
- {
- char *p=line;
- int next_index=1;
- double target;
- double value;
-
- if (sscanf(p,"%lf",&target) != 1)
- return clean_up(NULL, fp, "ERROR: failed to read labels\n");
- output_target(target);
-
- SKIP_TARGET
-
- while(sscanf(p,"%d:%lf",&index,&value)==2)
- {
- for(i=next_index;i<index;i++)
- output(i,0);
-
- output(index,value);
-
- SKIP_ELEMENT
- next_index=index+1;
- }
-
- for(i=next_index;i<=max_index;i++)
- output(i,0);
-
- printf("\n");
- }
-
- if (new_num_nonzeros > num_nonzeros)
- fprintf(stderr,
- "WARNING: original #nonzeros %ld\n"
- " new #nonzeros %ld\n"
- "Use -l 0 if many original feature values are zeros\n",
- num_nonzeros, new_num_nonzeros);
-
- free(line);
- free(feature_max);
- free(feature_min);
- fclose(fp);
- return 0;
-}
-
-char* readline(FILE *input)
-{
- int len;
-
- if(fgets(line,max_line_len,input) == NULL)
- return NULL;
-
- while(strrchr(line,'\n') == NULL)
- {
- max_line_len *= 2;
- line = (char *) realloc(line, max_line_len);
- len = (int) strlen(line);
- if(fgets(line+len,max_line_len-len,input) == NULL)
- break;
- }
- return line;
-}
-
-void output_target(double value)
-{
- if(y_scaling)
- {
- if(value == y_min)
- value = y_lower;
- else if(value == y_max)
- value = y_upper;
- else value = y_lower + (y_upper-y_lower) *
- (value - y_min)/(y_max-y_min);
- }
- printf("%g ",value);
-}
-
-void output(int index, double value)
-{
- /* skip single-valued attribute */
- if(feature_max[index] == feature_min[index])
- return;
-
- if(value == feature_min[index])
- value = lower;
- else if(value == feature_max[index])
- value = upper;
- else
- value = lower + (upper-lower) *
- (value-feature_min[index])/
- (feature_max[index]-feature_min[index]);
-
- if(value != 0)
- {
- printf("%d:%g ",index, value);
- new_num_nonzeros++;
- }
-}
-
-int clean_up(FILE *fp_restore, FILE *fp, const char* msg)
-{
- fprintf(stderr, "%s", msg);
- free(line);
- free(feature_max);
- free(feature_min);
- fclose(fp);
- if (fp_restore)
- fclose(fp_restore);
- return -1;
-}
-
diff --git a/Modules/Classification/CLLibSVM/src/svm-train.c b/Modules/Classification/CLLibSVM/src/svm-train.c
deleted file mode 100644
index 43c2c5a48c..0000000000
--- a/Modules/Classification/CLLibSVM/src/svm-train.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*============================================================================
-
-libsvm
-
-Copyright (c) 2000-2019 Chih-Chung Chang and Chih-Jen Lin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-3. Neither name of copyright holders nor the names of its contributors
-may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-============================================================================*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include "svm.h"
-#define Malloc(type,n) (type *)malloc((n)*sizeof(type))
-
-void print_null(const char *s) {}
-
-void exit_with_help()
-{
- printf(
- "Usage: svm-train [options] training_set_file [model_file]\n"
- "options:\n"
- "-s svm_type : set type of SVM (default 0)\n"
- " 0 -- C-SVC (multi-class classification)\n"
- " 1 -- nu-SVC (multi-class classification)\n"
- " 2 -- one-class SVM\n"
- " 3 -- epsilon-SVR (regression)\n"
- " 4 -- nu-SVR (regression)\n"
- "-t kernel_type : set type of kernel function (default 2)\n"
- " 0 -- linear: u'*v\n"
- " 1 -- polynomial: (gamma*u'*v + coef0)^degree\n"
- " 2 -- radial basis function: exp(-gamma*|u-v|^2)\n"
- " 3 -- sigmoid: tanh(gamma*u'*v + coef0)\n"
- " 4 -- precomputed kernel (kernel values in training_set_file)\n"
- "-d degree : set degree in kernel function (default 3)\n"
- "-g gamma : set gamma in kernel function (default 1/num_features)\n"
- "-r coef0 : set coef0 in kernel function (default 0)\n"
- "-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)\n"
- "-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)\n"
- "-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)\n"
- "-m cachesize : set cache memory size in MB (default 100)\n"
- "-e epsilon : set tolerance of termination criterion (default 0.001)\n"
- "-h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1)\n"
- "-b probability_estimates : whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)\n"
- "-wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1)\n"
- "-v n: n-fold cross validation mode\n"
- "-q : quiet mode (no outputs)\n"
- "-W weight_file: set weight file\n"
- );
- exit(1);
-}
-
-void exit_input_error(int line_num)
-{
- fprintf(stderr,"Wrong input format at line %d\n", line_num);
- exit(1);
-}
-
-void parse_command_line(int argc, char **argv, char *input_file_name, char *model_file_name);
-void read_problem(const char *filename);
-void do_cross_validation();
-
-struct svm_parameter param; // set by parse_command_line
-struct svm_problem prob; // set by read_problem
-struct svm_model *model;
-struct svm_node *x_space;
-char *weight_file;
-int cross_validation;
-int nr_fold;
-
-static char *line = NULL;
-static int max_line_len;
-
-static char* readline(FILE *input)
-{
- int len;
-
- if(fgets(line,max_line_len,input) == NULL)
- return NULL;
-
- while(strrchr(line,'\n') == NULL)
- {
- max_line_len *= 2;
- line = (char *) realloc(line,max_line_len);
- len = (int) strlen(line);
- if(fgets(line+len,max_line_len-len,input) == NULL)
- break;
- }
- return line;
-}
-
-int main(int argc, char **argv)
-{
- char input_file_name[1024];
- char model_file_name[1024];
- const char *error_msg;
-
- parse_command_line(argc, argv, input_file_name, model_file_name);
- read_problem(input_file_name);
- error_msg = svm_check_parameter(&prob,&param);
-
- if(error_msg)
- {
- fprintf(stderr,"ERROR: %s\n",error_msg);
- exit(1);
- }
-
- if(cross_validation)
- {
- do_cross_validation();
- }
- else
- {
- model = svm_train(&prob,&param);
- if(svm_save_model(model_file_name,model))
- {
- fprintf(stderr, "can't save model to file %s\n", model_file_name);
- exit(1);
- }
- svm_free_and_destroy_model(&model);
- }
- svm_destroy_param(&param);
- free(prob.y);
- free(prob.x);
- free(x_space);
- free(line);
-
- return 0;
-}
-
-void do_cross_validation()
-{
- int i;
- int total_correct = 0;
- double total_error = 0;
- double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
- double *target = Malloc(double,prob.l);
-
- svm_cross_validation(&prob,&param,nr_fold,target);
- if(param.svm_type == EPSILON_SVR ||
- param.svm_type == NU_SVR)
- {
- for(i=0;i<prob.l;i++)
- {
- double y = prob.y[i];
- double v = target[i];
- total_error += (v-y)*(v-y);
- sumv += v;
- sumy += y;
- sumvv += v*v;
- sumyy += y*y;
- sumvy += v*y;
- }
- printf("Cross Validation Mean squared error = %g\n",total_error/prob.l);
- printf("Cross Validation Squared correlation coefficient = %g\n",
- ((prob.l*sumvy-sumv*sumy)*(prob.l*sumvy-sumv*sumy))/
- ((prob.l*sumvv-sumv*sumv)*(prob.l*sumyy-sumy*sumy))
- );
- }
- else
- {
- for(i=0;i<prob.l;i++)
- if(target[i] == prob.y[i])
- ++total_correct;
- printf("Cross Validation Accuracy = %g%%\n",100.0*total_correct/prob.l);
- }
- free(target);
-}
-
-void parse_command_line(int argc, char **argv, char *input_file_name, char *model_file_name)
-{
- int i;
- void (*print_func)(const char*) = NULL; // default printing to stdout
-
- // default values
- param.svm_type = C_SVC;
- param.kernel_type = RBF;
- param.degree = 3;
- param.gamma = 0; // 1/num_features
- param.coef0 = 0;
- param.nu = 0.5;
- param.cache_size = 100;
- param.C = 1;
- param.eps = 1e-3;
- param.p = 0.1;
- param.shrinking = 1;
- param.probability = 0;
- param.nr_weight = 0;
- param.weight_label = NULL;
- param.weight = NULL;
- cross_validation = 0;
-
- // parse options
- for(i=1;i<argc;i++)
- {
- if(argv[i][0] != '-') break;
- if(++i>=argc)
- exit_with_help();
- switch(argv[i-1][1])
- {
- case 's':
- param.svm_type = atoi(argv[i]);
- break;
- case 't':
- param.kernel_type = atoi(argv[i]);
- break;
- case 'd':
- param.degree = atoi(argv[i]);
- break;
- case 'g':
- param.gamma = atof(argv[i]);
- break;
- case 'r':
- param.coef0 = atof(argv[i]);
- break;
- case 'n':
- param.nu = atof(argv[i]);
- break;
- case 'm':
- param.cache_size = atof(argv[i]);
- break;
- case 'c':
- param.C = atof(argv[i]);
- break;
- case 'e':
- param.eps = atof(argv[i]);
- break;
- case 'p':
- param.p = atof(argv[i]);
- break;
- case 'h':
- param.shrinking = atoi(argv[i]);
- break;
- case 'b':
- param.probability = atoi(argv[i]);
- break;
- case 'q':
- print_func = &print_null;
- i--;
- break;
- case 'v':
- cross_validation = 1;
- nr_fold = atoi(argv[i]);
- if(nr_fold < 2)
- {
- fprintf(stderr,"n-fold cross validation: n must >= 2\n");
- exit_with_help();
- }
- break;
- case 'w':
- ++param.nr_weight;
- param.weight_label = (int *)realloc(param.weight_label,sizeof(int)*param.nr_weight);
- param.weight = (double *)realloc(param.weight,sizeof(double)*param.nr_weight);
- param.weight_label[param.nr_weight-1] = atoi(&argv[i-1][2]);
- param.weight[param.nr_weight-1] = atof(argv[i]);
- break;
- case 'W':
- weight_file = argv[i];
- break;
- default:
- fprintf(stderr,"Unknown option: -%c\n", argv[i-1][1]);
- exit_with_help();
- }
- }
-
- svm_set_print_string_function(print_func);
-
- // determine filenames
-
- if(i>=argc)
- exit_with_help();
-
- strcpy(input_file_name, argv[i]);
-
- if(i<argc-1)
- strcpy(model_file_name,argv[i+1]);
- else
- {
- char *p = strrchr(argv[i],'/');
- if(p==NULL)
- p = argv[i];
- else
- ++p;
- sprintf(model_file_name,"%s.model",p);
- }
-}
-
-// read in a problem (in svmlight format)
-
-void read_problem(const char *filename)
-{
- int elements, max_index, inst_max_index, i, j;
- FILE *fp = fopen(filename,"r");
- char *endptr;
- char *idx, *val, *label;
-
- if(fp == NULL)
- {
- fprintf(stderr,"can't open input file %s\n",filename);
- exit(1);
- }
-
- prob.l = 0;
- elements = 0;
-
- max_line_len = 1024;
- line = Malloc(char,max_line_len);
- while(readline(fp)!=NULL)
- {
- char *p = strtok(line," \t"); // label
-
- // features
- while(1)
- {
- p = strtok(NULL," \t");
- if(p == NULL || *p == '\n') // check '\n' as ' ' may be after the last feature
- break;
- ++elements;
- }
- ++elements;
- ++prob.l;
- }
- rewind(fp);
-
- prob.y = Malloc(double,prob.l);
- prob.x = Malloc(struct svm_node *,prob.l);
- prob.W = Malloc(double,prob.l);
- x_space = Malloc(struct svm_node,elements);
-
- max_index = 0;
- j=0;
- for(i=0;i<prob.l;i++)
- {
- inst_max_index = -1; // strtol gives 0 if wrong format, and precomputed kernel has <index> start from 0
- readline(fp);
- prob.x[i] = &x_space[j];
- label = strtok(line," \t\n");
- if(label == NULL) // empty line
- exit_input_error(i+1);
-
- prob.y[i] = strtod(label,&endptr);
- if(endptr == label || *endptr != '\0')
- exit_input_error(i+1);
- prob.W[i] = 1;
-
- while(1)
- {
- idx = strtok(NULL,":");
- val = strtok(NULL," \t");
-
- if(val == NULL)
- break;
-
- errno = 0;
- x_space[j].index = (int) strtol(idx,&endptr,10);
- if(endptr == idx || errno != 0 || *endptr != '\0' || x_space[j].index <= inst_max_index)
- exit_input_error(i+1);
- else
- inst_max_index = x_space[j].index;
-
- errno = 0;
- x_space[j].value = strtod(val,&endptr);
- if(endptr == val || errno != 0 || (*endptr != '\0' && !isspace(*endptr)))
- exit_input_error(i+1);
-
- ++j;
- }
-
- if(inst_max_index > max_index)
- max_index = inst_max_index;
- x_space[j++].index = -1;
- }
-
- if(param.gamma == 0 && max_index > 0)
- param.gamma = 1.0/max_index;
-
- if(param.kernel_type == PRECOMPUTED)
- for(i=0;i<prob.l;i++)
- {
- if (prob.x[i][0].index != 0)
- {
- fprintf(stderr,"Wrong input format: first column must be 0:sample_serial_number\n");
- exit(1);
- }
- if ((int)prob.x[i][0].value <= 0 || (int)prob.x[i][0].value > max_index)
- {
- fprintf(stderr,"Wrong input format: sample_serial_number out of range\n");
- exit(1);
- }
- }
-
- fclose(fp);
-
- if(weight_file)
- {
- fp = fopen(weight_file,"r");
- for(i=0;i<prob.l;i++)
- fscanf(fp,"%lf",&prob.W[i]);
- fclose(fp);
- }
-}
diff --git a/Modules/Classification/CLLibSVM/src/svm.cpp b/Modules/Classification/CLLibSVM/src/svm.cpp
deleted file mode 100644
index d820dc2df2..0000000000
--- a/Modules/Classification/CLLibSVM/src/svm.cpp
+++ /dev/null
@@ -1,3291 +0,0 @@
-/*============================================================================
-
-libsvm
-
-Copyright (c) 2000-2019 Chih-Chung Chang and Chih-Jen Lin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-3. Neither name of copyright holders nor the names of its contributors
-may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-============================================================================*/
-
-#include <cmath>
-#include <cstdio>
-#include <cstdlib>
-#include <cctype>
-#include <cfloat>
-#include <cstring>
-#include <cstdarg>
-#include <climits>
-#include <clocale>
-#include <mitkLocaleSwitch.h>
-#include "svm.h"
-int libsvm_version = LIBSVM_VERSION;
-typedef float Qfloat;
-typedef signed char schar;
-#ifndef min
-template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }
-#endif
-#ifndef max
-template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }
-#endif
-template <class T> static inline void swap(T& x, T& y) { T t=x; x=y; y=t; }
-template <class S, class T> static inline void clone(T*& dst, S* src, int n)
-{
- dst = new T[n];
- memcpy((void *)dst,(void *)src,sizeof(T)*n);
-}
-static inline double powi(double base, int times)
-{
- double tmp = base, ret = 1.0;
-
- for(int t=times; t>0; t/=2)
- {
- if(t%2==1) ret*=tmp;
- tmp = tmp * tmp;
- }
- return ret;
-}
-#define INF HUGE_VAL
-#define TAU 1e-12
-#define Malloc(type,n) (type *)malloc((n)*sizeof(type))
-
-static void print_string_stdout(const char *s)
-{
- fputs(s,stdout);
- fflush(stdout);
-}
-static void (*svm_print_string) (const char *) = &print_string_stdout;
-#if 1
-static void info(const char *fmt,...)
-{
- char buf[BUFSIZ];
- va_list ap;
- va_start(ap,fmt);
- vsprintf(buf,fmt,ap);
- va_end(ap);
- (*svm_print_string)(buf);
-}
-#else
-static void info(const char *fmt,...) {}
-#endif
-
-//
-// Kernel Cache
-//
-// l is the number of total data items
-// size is the cache size limit in bytes
-//
-class Cache
-{
-public:
- Cache(int l,long int size);
- ~Cache();
-
- // request data [0,len)
- // return some position p where [p,len) need to be filled
- // (p >= len if nothing needs to be filled)
- int get_data(const int index, Qfloat **data, int len);
- void swap_index(int i, int j);
-private:
- int l;
- long int size;
- struct head_t
- {
- head_t *prev, *next; // a circular list
- Qfloat *data;
- int len; // data[0,len) is cached in this entry
- };
-
- head_t *head;
- head_t lru_head;
- void lru_delete(head_t *h);
- void lru_insert(head_t *h);
-};
-
-Cache::Cache(int l_,long int size_):l(l_),size(size_)
-{
- head = (head_t *)calloc(l,sizeof(head_t)); // initialized to 0
- size /= sizeof(Qfloat);
- size -= l * sizeof(head_t) / sizeof(Qfloat);
- size = max(size, 2 * (long int) l); // cache must be large enough for two columns
- lru_head.next = lru_head.prev = &lru_head;
-}
-
-Cache::~Cache()
-{
- for(head_t *h = lru_head.next; h != &lru_head; h=h->next)
- free(h->data);
- free(head);
-}
-
-void Cache::lru_delete(head_t *h)
-{
- // delete from current location
- h->prev->next = h->next;
- h->next->prev = h->prev;
-}
-
-void Cache::lru_insert(head_t *h)
-{
- // insert to last position
- h->next = &lru_head;
- h->prev = lru_head.prev;
- h->prev->next = h;
- h->next->prev = h;
-}
-
-int Cache::get_data(const int index, Qfloat **data, int len)
-{
- head_t *h = &head[index];
- if(h->len) lru_delete(h);
- int more = len - h->len;
-
- if(more > 0)
- {
- // free old space
- while(size < more)
- {
- head_t *old = lru_head.next;
- lru_delete(old);
- free(old->data);
- size += old->len;
- old->data = nullptr;
- old->len = 0;
- }
-
- // allocate new space
- h->data = (Qfloat *)realloc(h->data,sizeof(Qfloat)*len);
- size -= more;
- swap(h->len,len);
- }
-
- lru_insert(h);
- *data = h->data;
- return len;
-}
-
-void Cache::swap_index(int i, int j)
-{
- if(i==j) return;
-
- if(head[i].len) lru_delete(&head[i]);
- if(head[j].len) lru_delete(&head[j]);
- swap(head[i].data,head[j].data);
- swap(head[i].len,head[j].len);
- if(head[i].len) lru_insert(&head[i]);
- if(head[j].len) lru_insert(&head[j]);
-
- if(i>j) swap(i,j);
- for(head_t *h = lru_head.next; h!=&lru_head; h=h->next)
- {
- if(h->len > i)
- {
- if(h->len > j)
- swap(h->data[i],h->data[j]);
- else
- {
- // give up
- lru_delete(h);
- free(h->data);
- size += h->len;
- h->data = nullptr;
- h->len = 0;
- }
- }
- }
-}
-
-//
-// Kernel evaluation
-//
-// the static method k_function is for doing single kernel evaluation
-// the constructor of Kernel prepares to calculate the l*l kernel matrix
-// the member function get_Q is for getting one column from the Q Matrix
-//
-class QMatrix {
-public:
- virtual Qfloat *get_Q(int column, int len) const = 0;
- virtual double *get_QD() const = 0;
- virtual void swap_index(int i, int j) const = 0;
- virtual ~QMatrix() {}
-};
-
-class Kernel: public QMatrix {
-public:
- Kernel(int l, svm_node * const * x, const svm_parameter& param);
- ~Kernel() override;
-
- static double k_function(const svm_node *x, const svm_node *y,
- const svm_parameter& param);
- Qfloat *get_Q(int column, int len) const override = 0;
- double *get_QD() const override = 0;
- void swap_index(int i, int j) const override // no so const...
- {
- swap(x[i],x[j]);
- if(x_square) swap(x_square[i],x_square[j]);
- }
-protected:
-
- double (Kernel::*kernel_function)(int i, int j) const;
-
-private:
- const svm_node **x;
- double *x_square;
-
- // svm_parameter
- const int kernel_type;
- const int degree;
- const double gamma;
- const double coef0;
-
- static double dot(const svm_node *px, const svm_node *py);
- double kernel_linear(int i, int j) const
- {
- return dot(x[i],x[j]);
- }
- double kernel_poly(int i, int j) const
- {
- return powi(gamma*dot(x[i],x[j])+coef0,degree);
- }
- double kernel_rbf(int i, int j) const
- {
- return exp(-gamma*(x_square[i]+x_square[j]-2*dot(x[i],x[j])));
- }
- double kernel_sigmoid(int i, int j) const
- {
- return tanh(gamma*dot(x[i],x[j])+coef0);
- }
- double kernel_precomputed(int i, int j) const
- {
- return x[i][(int)(x[j][0].value)].value;
- }
-};
-
-Kernel::Kernel(int l, svm_node * const * x_, const svm_parameter& param)
- :kernel_type(param.kernel_type), degree(param.degree),
- gamma(param.gamma), coef0(param.coef0)
-{
- switch(kernel_type)
- {
- case LINEAR:
- kernel_function = &Kernel::kernel_linear;
- break;
- case POLY:
- kernel_function = &Kernel::kernel_poly;
- break;
- case RBF:
- kernel_function = &Kernel::kernel_rbf;
- break;
- case SIGMOID:
- kernel_function = &Kernel::kernel_sigmoid;
- break;
- case PRECOMPUTED:
- kernel_function = &Kernel::kernel_precomputed;
- break;
- }
-
- clone(x,x_,l);
-
- if(kernel_type == RBF)
- {
- x_square = new double[l];
- for(int i=0;i<l;i++)
- x_square[i] = dot(x[i],x[i]);
- }
- else
- x_square = nullptr;
-}
-
-Kernel::~Kernel()
-{
- delete[] x;
- delete[] x_square;
-}
-
-double Kernel::dot(const svm_node *px, const svm_node *py)
-{
- double sum = 0;
- while(px->index != -1 && py->index != -1)
- {
- if(px->index == py->index)
- {
- sum += px->value * py->value;
- ++px;
- ++py;
- }
- else
- {
- if(px->index > py->index)
- ++py;
- else
- ++px;
- }
- }
- return sum;
-}
-
-double Kernel::k_function(const svm_node *x, const svm_node *y,
- const svm_parameter& param)
-{
- switch(param.kernel_type)
- {
- case LINEAR:
- return dot(x,y);
- case POLY:
- return powi(param.gamma*dot(x,y)+param.coef0,param.degree);
- case RBF:
- {
- double sum = 0;
- while(x->index != -1 && y->index !=-1)
- {
- if(x->index == y->index)
- {
- double d = x->value - y->value;
- sum += d*d;
- ++x;
- ++y;
- }
- else
- {
- if(x->index > y->index)
- {
- sum += y->value * y->value;
- ++y;
- }
- else
- {
- sum += x->value * x->value;
- ++x;
- }
- }
- }
-
- while(x->index != -1)
- {
- sum += x->value * x->value;
- ++x;
- }
-
- while(y->index != -1)
- {
- sum += y->value * y->value;
- ++y;
- }
-
- return exp(-param.gamma*sum);
- }
- case SIGMOID:
- return tanh(param.gamma*dot(x,y)+param.coef0);
- case PRECOMPUTED: //x: test (validation), y: SV
- return x[(int)(y->value)].value;
- default:
- return 0; // Unreachable
- }
-}
-
-// An SMO algorithm in Fan et al., JMLR 6(2005), p. 1889--1918
-// Solves:
-//
-// min 0.5(\alpha^T Q \alpha) + p^T \alpha
-//
-// y^T \alpha = \delta
-// y_i = +1 or -1
-// 0 <= alpha_i <= Cp for y_i = 1
-// 0 <= alpha_i <= Cn for y_i = -1
-//
-// Given:
-//
-// Q, p, y, Cp, Cn, and an initial feasible point \alpha
-// l is the size of vectors and matrices
-// eps is the stopping tolerance
-//
-// solution will be put in \alpha, objective value will be put in obj
-//
-class Solver {
-public:
- Solver() {};
- virtual ~Solver() {};
-
- struct SolutionInfo {
- double obj;
- double rho;
- double *upper_bound;
- double r; // for Solver_NU
- };
-
- void Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
- double *alpha_, const double* C_, double eps,
- SolutionInfo* si, int shrinking);
-protected:
- int active_size;
- schar *y;
- double *G; // gradient of objective function
- enum { LOWER_BOUND, UPPER_BOUND, FREE };
- char *alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE
- double *alpha;
- const QMatrix *Q;
- const double *QD;
- double eps;
- double Cp,Cn;
- double *C;
- double *p;
- int *active_set;
- double *G_bar; // gradient, if we treat free variables as 0
- int l;
- bool unshrink; // XXX
-
- double get_C(int i)
- {
- return C[i];
- }
- void update_alpha_status(int i)
- {
- if(alpha[i] >= get_C(i))
- alpha_status[i] = UPPER_BOUND;
- else if(alpha[i] <= 0)
- alpha_status[i] = LOWER_BOUND;
- else alpha_status[i] = FREE;
- }
- bool is_upper_bound(int i) { return alpha_status[i] == UPPER_BOUND; }
- bool is_lower_bound(int i) { return alpha_status[i] == LOWER_BOUND; }
- bool is_free(int i) { return alpha_status[i] == FREE; }
- void swap_index(int i, int j);
- void reconstruct_gradient();
- virtual int select_working_set(int &i, int &j);
- virtual double calculate_rho();
- virtual void do_shrinking();
-private:
- bool be_shrunk(int i, double Gmax1, double Gmax2);
-};
-
-void Solver::swap_index(int i, int j)
-{
- Q->swap_index(i,j);
- swap(y[i],y[j]);
- swap(G[i],G[j]);
- swap(alpha_status[i],alpha_status[j]);
- swap(alpha[i],alpha[j]);
- swap(p[i],p[j]);
- swap(active_set[i],active_set[j]);
- swap(G_bar[i],G_bar[j]);
- swap(C[i],C[j]);
-}
-
-void Solver::reconstruct_gradient()
-{
- // reconstruct inactive elements of G from G_bar and free variables
-
- if(active_size == l) return;
-
- int i,j;
- int nr_free = 0;
-
- for(j=active_size;j<l;j++)
- G[j] = G_bar[j] + p[j];
-
- for(j=0;j<active_size;j++)
- if(is_free(j))
- nr_free++;
-
- if(2*nr_free < active_size)
- info("\nWARNING: using -h 0 may be faster\n");
-
- if (nr_free*l > 2*active_size*(l-active_size))
- {
- for(i=active_size;i<l;i++)
- {
- const Qfloat *Q_i = Q->get_Q(i,active_size);
- for(j=0;j<active_size;j++)
- if(is_free(j))
- G[i] += alpha[j] * Q_i[j];
- }
- }
- else
- {
- for(i=0;i<active_size;i++)
- if(is_free(i))
- {
- const Qfloat *Q_i = Q->get_Q(i,l);
- double alpha_i = alpha[i];
- for(j=active_size;j<l;j++)
- G[j] += alpha_i * Q_i[j];
- }
- }
-}
-
-void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
- double *alpha_, const double* C_, double eps,
- SolutionInfo* si, int shrinking)
-{
- this->l = l;
- this->Q = &Q;
- QD=Q.get_QD();
- clone(p, p_,l);
- clone(y, y_,l);
- clone(alpha,alpha_,l);
- clone(C,C_,l);
- this->eps = eps;
- unshrink = false;
-
- // initialize alpha_status
- {
- alpha_status = new char[l];
- for(int i=0;i<l;i++)
- update_alpha_status(i);
- }
-
- // initialize active set (for shrinking)
- {
- active_set = new int[l];
- for(int i=0;i<l;i++)
- active_set[i] = i;
- active_size = l;
- }
-
- // initialize gradient
- {
- G = new double[l];
- G_bar = new double[l];
- int i;
- for(i=0;i<l;i++)
- {
- G[i] = p[i];
- G_bar[i] = 0;
- }
- for(i=0;i<l;i++)
- if(!is_lower_bound(i))
- {
- const Qfloat *Q_i = Q.get_Q(i,l);
- double alpha_i = alpha[i];
- int j;
- for(j=0;j<l;j++)
- G[j] += alpha_i*Q_i[j];
- if(is_upper_bound(i))
- for(j=0;j<l;j++)
- G_bar[j] += get_C(i) * Q_i[j];
- }
- }
-
- // optimization step
-
- int iter = 0;
- int max_iter = max(10000000, l>INT_MAX/100 ? INT_MAX : 100*l);
- int counter = min(l,1000)+1;
-
- while(iter < max_iter)
- {
- // show progress and do shrinking
-
- if(--counter == 0)
- {
- counter = min(l,1000);
- if(shrinking) do_shrinking();
- info(".");
- }
-
- int i,j;
- if(select_working_set(i,j)!=0)
- {
- // reconstruct the whole gradient
- reconstruct_gradient();
- // reset active set size and check
- active_size = l;
- info("*");
- if(select_working_set(i,j)!=0)
- break;
- else
- counter = 1; // do shrinking next iteration
- }
-
- ++iter;
-
- // update alpha[i] and alpha[j], handle bounds carefully
-
- const Qfloat *Q_i = Q.get_Q(i,active_size);
- const Qfloat *Q_j = Q.get_Q(j,active_size);
-
- double C_i = get_C(i);
- double C_j = get_C(j);
-
- double old_alpha_i = alpha[i];
- double old_alpha_j = alpha[j];
-
- if(y[i]!=y[j])
- {
- double quad_coef = QD[i]+QD[j]+2*Q_i[j];
- if (quad_coef <= 0)
- quad_coef = TAU;
- double delta = (-G[i]-G[j])/quad_coef;
- double diff = alpha[i] - alpha[j];
- alpha[i] += delta;
- alpha[j] += delta;
-
- if(diff > 0)
- {
- if(alpha[j] < 0)
- {
- alpha[j] = 0;
- alpha[i] = diff;
- }
- }
- else
- {
- if(alpha[i] < 0)
- {
- alpha[i] = 0;
- alpha[j] = -diff;
- }
- }
- if(diff > C_i - C_j)
- {
- if(alpha[i] > C_i)
- {
- alpha[i] = C_i;
- alpha[j] = C_i - diff;
- }
- }
- else
- {
- if(alpha[j] > C_j)
- {
- alpha[j] = C_j;
- alpha[i] = C_j + diff;
- }
- }
- }
- else
- {
- double quad_coef = QD[i]+QD[j]-2*Q_i[j];
- if (quad_coef <= 0)
- quad_coef = TAU;
- double delta = (G[i]-G[j])/quad_coef;
- double sum = alpha[i] + alpha[j];
- alpha[i] -= delta;
- alpha[j] += delta;
-
- if(sum > C_i)
- {
- if(alpha[i] > C_i)
- {
- alpha[i] = C_i;
- alpha[j] = sum - C_i;
- }
- }
- else
- {
- if(alpha[j] < 0)
- {
- alpha[j] = 0;
- alpha[i] = sum;
- }
- }
- if(sum > C_j)
- {
- if(alpha[j] > C_j)
- {
- alpha[j] = C_j;
- alpha[i] = sum - C_j;
- }
- }
- else
- {
- if(alpha[i] < 0)
- {
- alpha[i] = 0;
- alpha[j] = sum;
- }
- }
- }
-
- // update G
-
- double delta_alpha_i = alpha[i] - old_alpha_i;
- double delta_alpha_j = alpha[j] - old_alpha_j;
-
- for(int k=0;k<active_size;k++)
- {
- G[k] += Q_i[k]*delta_alpha_i + Q_j[k]*delta_alpha_j;
- }
-
- // update alpha_status and G_bar
-
- {
- bool ui = is_upper_bound(i);
- bool uj = is_upper_bound(j);
- update_alpha_status(i);
- update_alpha_status(j);
- int k;
- if(ui != is_upper_bound(i))
- {
- Q_i = Q.get_Q(i,l);
- if(ui)
- for(k=0;k<l;k++)
- G_bar[k] -= C_i * Q_i[k];
- else
- for(k=0;k<l;k++)
- G_bar[k] += C_i * Q_i[k];
- }
-
- if(uj != is_upper_bound(j))
- {
- Q_j = Q.get_Q(j,l);
- if(uj)
- for(k=0;k<l;k++)
- G_bar[k] -= C_j * Q_j[k];
- else
- for(k=0;k<l;k++)
- G_bar[k] += C_j * Q_j[k];
- }
- }
- }
-
- if(iter >= max_iter)
- {
- if(active_size < l)
- {
- // reconstruct the whole gradient to calculate objective value
- reconstruct_gradient();
- active_size = l;
- info("*");
- }
- fprintf(stderr,"\nWARNING: reaching max number of iterations\n");
- }
-
- // calculate rho
-
- si->rho = calculate_rho();
-
- // calculate objective value
- {
- double v = 0;
- int i;
- for(i=0;i<l;i++)
- v += alpha[i] * (G[i] + p[i]);
-
- si->obj = v/2;
- }
-
- // put back the solution
- {
- for(int i=0;i<l;i++)
- alpha_[active_set[i]] = alpha[i];
- }
-
- // juggle everything back
- /*{
- for(int i=0;i<l;i++)
- while(active_set[i] != i)
- swap_index(i,active_set[i]);
- // or Q.swap_index(i,active_set[i]);
- }*/
-
- for(int i=0;i<l;i++)
- si->upper_bound[i] = C[i];
-
- info("\noptimization finished, #iter = %d\n",iter);
-
- delete[] p;
- delete[] y;
- delete[] C;
- delete[] alpha;
- delete[] alpha_status;
- delete[] active_set;
- delete[] G;
- delete[] G_bar;
-}
-
-// return 1 if already optimal, return 0 otherwise
-int Solver::select_working_set(int &out_i, int &out_j)
-{
- // return i,j such that
- // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha)
- // j: minimizes the decrease of obj value
- // (if quadratic coefficeint <= 0, replace it with tau)
- // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
-
- double Gmax = -INF;
- double Gmax2 = -INF;
- int Gmax_idx = -1;
- int Gmin_idx = -1;
- double obj_diff_min = INF;
-
- for(int t=0;t<active_size;t++)
- if(y[t]==+1)
- {
- if(!is_upper_bound(t))
- if(-G[t] >= Gmax)
- {
- Gmax = -G[t];
- Gmax_idx = t;
- }
- }
- else
- {
- if(!is_lower_bound(t))
- if(G[t] >= Gmax)
- {
- Gmax = G[t];
- Gmax_idx = t;
- }
- }
-
- int i = Gmax_idx;
- const Qfloat *Q_i = nullptr;
- if(i != -1) // nullptr Q_i not accessed: Gmax=-INF if i=-1
- Q_i = Q->get_Q(i,active_size);
-
- for(int j=0;j<active_size;j++)
- {
- if(y[j]==+1)
- {
- if (!is_lower_bound(j))
- {
- double grad_diff=Gmax+G[j];
- if (G[j] >= Gmax2)
- Gmax2 = G[j];
- if (grad_diff > 0)
- {
- double obj_diff;
- double quad_coef = QD[i]+QD[j]-2.0*y[i]*Q_i[j];
- if (quad_coef > 0)
- obj_diff = -(grad_diff*grad_diff)/quad_coef;
- else
- obj_diff = -(grad_diff*grad_diff)/TAU;
-
- if (obj_diff <= obj_diff_min)
- {
- Gmin_idx=j;
- obj_diff_min = obj_diff;
- }
- }
- }
- }
- else
- {
- if (!is_upper_bound(j))
- {
- double grad_diff= Gmax-G[j];
- if (-G[j] >= Gmax2)
- Gmax2 = -G[j];
- if (grad_diff > 0)
- {
- double obj_diff;
- double quad_coef = QD[i]+QD[j]+2.0*y[i]*Q_i[j];
- if (quad_coef > 0)
- obj_diff = -(grad_diff*grad_diff)/quad_coef;
- else
- obj_diff = -(grad_diff*grad_diff)/TAU;
-
- if (obj_diff <= obj_diff_min)
- {
- Gmin_idx=j;
- obj_diff_min = obj_diff;
- }
- }
- }
- }
- }
-
- if(Gmax+Gmax2 < eps)
- return 1;
-
- out_i = Gmax_idx;
- out_j = Gmin_idx;
- return 0;
-}
-
-bool Solver::be_shrunk(int i, double Gmax1, double Gmax2)
-{
- if(is_upper_bound(i))
- {
- if(y[i]==+1)
- return(-G[i] > Gmax1);
- else
- return(-G[i] > Gmax2);
- }
- else if(is_lower_bound(i))
- {
- if(y[i]==+1)
- return(G[i] > Gmax2);
- else
- return(G[i] > Gmax1);
- }
- else
- return(false);
-}
-
-void Solver::do_shrinking()
-{
- int i;
- double Gmax1 = -INF; // max { -y_i * grad(f)_i | i in I_up(\alpha) }
- double Gmax2 = -INF; // max { y_i * grad(f)_i | i in I_low(\alpha) }
-
- // find maximal violating pair first
- for(i=0;i<active_size;i++)
- {
- if(y[i]==+1)
- {
- if(!is_upper_bound(i))
- {
- if(-G[i] >= Gmax1)
- Gmax1 = -G[i];
- }
- if(!is_lower_bound(i))
- {
- if(G[i] >= Gmax2)
- Gmax2 = G[i];
- }
- }
- else
- {
- if(!is_upper_bound(i))
- {
- if(-G[i] >= Gmax2)
- Gmax2 = -G[i];
- }
- if(!is_lower_bound(i))
- {
- if(G[i] >= Gmax1)
- Gmax1 = G[i];
- }
- }
- }
-
- if(unshrink == false && Gmax1 + Gmax2 <= eps*10)
- {
- unshrink = true;
- reconstruct_gradient();
- active_size = l;
- info("*");
- }
-
- for(i=0;i<active_size;i++)
- if (be_shrunk(i, Gmax1, Gmax2))
- {
- active_size--;
- while (active_size > i)
- {
- if (!be_shrunk(active_size, Gmax1, Gmax2))
- {
- swap_index(i,active_size);
- break;
- }
- active_size--;
- }
- }
-}
-
-double Solver::calculate_rho()
-{
- double r;
- int nr_free = 0;
- double ub = INF, lb = -INF, sum_free = 0;
- for(int i=0;i<active_size;i++)
- {
- double yG = y[i]*G[i];
-
- if(is_upper_bound(i))
- {
- if(y[i]==-1)
- ub = min(ub,yG);
- else
- lb = max(lb,yG);
- }
- else if(is_lower_bound(i))
- {
- if(y[i]==+1)
- ub = min(ub,yG);
- else
- lb = max(lb,yG);
- }
- else
- {
- ++nr_free;
- sum_free += yG;
- }
- }
-
- if(nr_free>0)
- r = sum_free/nr_free;
- else
- r = (ub+lb)/2;
-
- return r;
-}
-
-//
-// Solver for nu-svm classification and regression
-//
-// additional constraint: e^T \alpha = constant
-//
-class Solver_NU: public Solver
-{
-public:
- Solver_NU() {}
- void Solve(int l, const QMatrix& Q, const double *p, const schar *y,
- double *alpha, double* C_, double eps,
- SolutionInfo* si, int shrinking)
- {
- this->si = si;
- Solver::Solve(l,Q,p,y,alpha,C_,eps,si,shrinking);
- }
-private:
- SolutionInfo *si;
- int select_working_set(int &i, int &j) override;
- double calculate_rho() override;
- bool be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4);
- void do_shrinking() override;
-};
-
-// return 1 if already optimal, return 0 otherwise
-int Solver_NU::select_working_set(int &out_i, int &out_j)
-{
- // return i,j such that y_i = y_j and
- // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha)
- // j: minimizes the decrease of obj value
- // (if quadratic coefficeint <= 0, replace it with tau)
- // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
-
- double Gmaxp = -INF;
- double Gmaxp2 = -INF;
- int Gmaxp_idx = -1;
-
- double Gmaxn = -INF;
- double Gmaxn2 = -INF;
- int Gmaxn_idx = -1;
-
- int Gmin_idx = -1;
- double obj_diff_min = INF;
-
- for(int t=0;t<active_size;t++)
- if(y[t]==+1)
- {
- if(!is_upper_bound(t))
- if(-G[t] >= Gmaxp)
- {
- Gmaxp = -G[t];
- Gmaxp_idx = t;
- }
- }
- else
- {
- if(!is_lower_bound(t))
- if(G[t] >= Gmaxn)
- {
- Gmaxn = G[t];
- Gmaxn_idx = t;
- }
- }
-
- int ip = Gmaxp_idx;
- int in = Gmaxn_idx;
- const Qfloat *Q_ip = nullptr;
- const Qfloat *Q_in = nullptr;
- if(ip != -1) // nullptr Q_ip not accessed: Gmaxp=-INF if ip=-1
- Q_ip = Q->get_Q(ip,active_size);
- if(in != -1)
- Q_in = Q->get_Q(in,active_size);
-
- for(int j=0;j<active_size;j++)
- {
- if(y[j]==+1)
- {
- if (!is_lower_bound(j))
- {
- double grad_diff=Gmaxp+G[j];
- if (G[j] >= Gmaxp2)
- Gmaxp2 = G[j];
- if (grad_diff > 0)
- {
- double obj_diff;
- double quad_coef = QD[ip]+QD[j]-2*Q_ip[j];
- if (quad_coef > 0)
- obj_diff = -(grad_diff*grad_diff)/quad_coef;
- else
- obj_diff = -(grad_diff*grad_diff)/TAU;
-
- if (obj_diff <= obj_diff_min)
- {
- Gmin_idx=j;
- obj_diff_min = obj_diff;
- }
- }
- }
- }
- else
- {
- if (!is_upper_bound(j))
- {
- double grad_diff=Gmaxn-G[j];
- if (-G[j] >= Gmaxn2)
- Gmaxn2 = -G[j];
- if (grad_diff > 0)
- {
- double obj_diff;
- double quad_coef = QD[in]+QD[j]-2*Q_in[j];
- if (quad_coef > 0)
- obj_diff = -(grad_diff*grad_diff)/quad_coef;
- else
- obj_diff = -(grad_diff*grad_diff)/TAU;
-
- if (obj_diff <= obj_diff_min)
- {
- Gmin_idx=j;
- obj_diff_min = obj_diff;
- }
- }
- }
- }
- }
-
- if(max(Gmaxp+Gmaxp2,Gmaxn+Gmaxn2) < eps)
- return 1;
-
- if (y[Gmin_idx] == +1)
- out_i = Gmaxp_idx;
- else
- out_i = Gmaxn_idx;
- out_j = Gmin_idx;
-
- return 0;
-}
-
-bool Solver_NU::be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4)
-{
- if(is_upper_bound(i))
- {
- if(y[i]==+1)
- return(-G[i] > Gmax1);
- else
- return(-G[i] > Gmax4);
- }
- else if(is_lower_bound(i))
- {
- if(y[i]==+1)
- return(G[i] > Gmax2);
- else
- return(G[i] > Gmax3);
- }
- else
- return(false);
-}
-
-void Solver_NU::do_shrinking()
-{
- double Gmax1 = -INF; // max { -y_i * grad(f)_i | y_i = +1, i in I_up(\alpha) }
- double Gmax2 = -INF; // max { y_i * grad(f)_i | y_i = +1, i in I_low(\alpha) }
- double Gmax3 = -INF; // max { -y_i * grad(f)_i | y_i = -1, i in I_up(\alpha) }
- double Gmax4 = -INF; // max { y_i * grad(f)_i | y_i = -1, i in I_low(\alpha) }
-
- // find maximal violating pair first
- int i;
- for(i=0;i<active_size;i++)
- {
- if(!is_upper_bound(i))
- {
- if(y[i]==+1)
- {
- if(-G[i] > Gmax1) Gmax1 = -G[i];
- }
- else if(-G[i] > Gmax4) Gmax4 = -G[i];
- }
- if(!is_lower_bound(i))
- {
- if(y[i]==+1)
- {
- if(G[i] > Gmax2) Gmax2 = G[i];
- }
- else if(G[i] > Gmax3) Gmax3 = G[i];
- }
- }
-
- if(unshrink == false && max(Gmax1+Gmax2,Gmax3+Gmax4) <= eps*10)
- {
- unshrink = true;
- reconstruct_gradient();
- active_size = l;
- }
-
- for(i=0;i<active_size;i++)
- if (be_shrunk(i, Gmax1, Gmax2, Gmax3, Gmax4))
- {
- active_size--;
- while (active_size > i)
- {
- if (!be_shrunk(active_size, Gmax1, Gmax2, Gmax3, Gmax4))
- {
- swap_index(i,active_size);
- break;
- }
- active_size--;
- }
- }
-}
-
-double Solver_NU::calculate_rho()
-{
- int nr_free1 = 0,nr_free2 = 0;
- double ub1 = INF, ub2 = INF;
- double lb1 = -INF, lb2 = -INF;
- double sum_free1 = 0, sum_free2 = 0;
-
- for(int i=0;i<active_size;i++)
- {
- if(y[i]==+1)
- {
- if(is_upper_bound(i))
- lb1 = max(lb1,G[i]);
- else if(is_lower_bound(i))
- ub1 = min(ub1,G[i]);
- else
- {
- ++nr_free1;
- sum_free1 += G[i];
- }
- }
- else
- {
- if(is_upper_bound(i))
- lb2 = max(lb2,G[i]);
- else if(is_lower_bound(i))
- ub2 = min(ub2,G[i]);
- else
- {
- ++nr_free2;
- sum_free2 += G[i];
- }
- }
- }
-
- double r1,r2;
- if(nr_free1 > 0)
- r1 = sum_free1/nr_free1;
- else
- r1 = (ub1+lb1)/2;
-
- if(nr_free2 > 0)
- r2 = sum_free2/nr_free2;
- else
- r2 = (ub2+lb2)/2;
-
- si->r = (r1+r2)/2;
- return (r1-r2)/2;
-}
-
-//
-// Q matrices for various formulations
-//
-class SVC_Q: public Kernel
-{
-public:
- SVC_Q(const svm_problem& prob, const svm_parameter& param, const schar *y_)
- :Kernel(prob.l, prob.x, param)
- {
- clone(y,y_,prob.l);
- cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20)));
- QD = new double[prob.l];
- for(int i=0;i<prob.l;i++)
- QD[i] = (this->*kernel_function)(i,i);
- }
-
- Qfloat *get_Q(int i, int len) const override
- {
- Qfloat *data;
- int start, j;
- if((start = cache->get_data(i,&data,len)) < len)
- {
- for(j=start;j<len;j++)
- data[j] = (Qfloat)(y[i]*y[j]*(this->*kernel_function)(i,j));
- }
- return data;
- }
-
- double *get_QD() const override
- {
- return QD;
- }
-
- void swap_index(int i, int j) const override
- {
- cache->swap_index(i,j);
- Kernel::swap_index(i,j);
- swap(y[i],y[j]);
- swap(QD[i],QD[j]);
- }
-
- ~SVC_Q() override
- {
- delete[] y;
- delete cache;
- delete[] QD;
- }
-private:
- schar *y;
- Cache *cache;
- double *QD;
-};
-
-class ONE_CLASS_Q: public Kernel
-{
-public:
- ONE_CLASS_Q(const svm_problem& prob, const svm_parameter& param)
- :Kernel(prob.l, prob.x, param)
- {
- cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20)));
- QD = new double[prob.l];
- for(int i=0;i<prob.l;i++)
- QD[i] = (this->*kernel_function)(i,i);
- }
-
- Qfloat *get_Q(int i, int len) const override
- {
- Qfloat *data;
- int start, j;
- if((start = cache->get_data(i,&data,len)) < len)
- {
- for(j=start;j<len;j++)
- data[j] = (Qfloat)(this->*kernel_function)(i,j);
- }
- return data;
- }
-
- double *get_QD() const override
- {
- return QD;
- }
-
- void swap_index(int i, int j) const override
- {
- cache->swap_index(i,j);
- Kernel::swap_index(i,j);
- swap(QD[i],QD[j]);
- }
-
- ~ONE_CLASS_Q() override
- {
- delete cache;
- delete[] QD;
- }
-private:
- Cache *cache;
- double *QD;
-};
-
-class SVR_Q: public Kernel
-{
-public:
- SVR_Q(const svm_problem& prob, const svm_parameter& param)
- :Kernel(prob.l, prob.x, param)
- {
- l = prob.l;
- cache = new Cache(l,(long int)(param.cache_size*(1<<20)));
- QD = new double[2*l];
- sign = new schar[2*l];
- index = new int[2*l];
- for(int k=0;k<l;k++)
- {
- sign[k] = 1;
- sign[k+l] = -1;
- index[k] = k;
- index[k+l] = k;
- QD[k] = (this->*kernel_function)(k,k);
- QD[k+l] = QD[k];
- }
- buffer[0] = new Qfloat[2*l];
- buffer[1] = new Qfloat[2*l];
- next_buffer = 0;
- }
-
- void swap_index(int i, int j) const override
- {
- swap(sign[i],sign[j]);
- swap(index[i],index[j]);
- swap(QD[i],QD[j]);
- }
-
- Qfloat *get_Q(int i, int len) const override
- {
- Qfloat *data;
- int j, real_i = index[i];
- if(cache->get_data(real_i,&data,l) < l)
- {
- for(j=0;j<l;j++)
- data[j] = (Qfloat)(this->*kernel_function)(real_i,j);
- }
-
- // reorder and copy
- Qfloat *buf = buffer[next_buffer];
- next_buffer = 1 - next_buffer;
- schar si = sign[i];
- for(j=0;j<len;j++)
- buf[j] = (Qfloat) si * (Qfloat) sign[j] * data[index[j]];
- return buf;
- }
-
- double *get_QD() const override
- {
- return QD;
- }
-
- ~SVR_Q() override
- {
- delete cache;
- delete[] sign;
- delete[] index;
- delete[] buffer[0];
- delete[] buffer[1];
- delete[] QD;
- }
-private:
- int l;
- Cache *cache;
- schar *sign;
- int *index;
- mutable int next_buffer;
- Qfloat *buffer[2];
- double *QD;
-};
-
-//
-// construct and solve various formulations
-//
-static void solve_c_svc(
- const svm_problem *prob, const svm_parameter* param,
- double *alpha, Solver::SolutionInfo* si, double Cp, double Cn)
-{
- int l = prob->l;
- auto *minus_ones = new double[l];
- auto *y = new schar[l];
- auto *C = new double[l];
-
- int i;
-
- for(i=0;i<l;i++)
- {
- alpha[i] = 0;
- minus_ones[i] = -1;
- if(prob->y[i] > 0)
- {
- y[i] = +1;
- C[i] = prob->W[i]*Cp;
- }
- else
- {
- y[i] = -1;
- C[i] = prob->W[i]*Cn;
- }
- }
-
- Solver s;
- s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y,
- alpha, C, param->eps, si, param->shrinking);
-
- /*
- double sum_alpha=0;
- for(i=0;i<l;i++)
- sum_alpha += alpha[i];
- if (Cp==Cn)
- info("nu = %f\n", sum_alpha/(Cp*prob->l));
- */
-
- for(i=0;i<l;i++)
- alpha[i] *= y[i];
-
- delete[] C;
- delete[] minus_ones;
- delete[] y;
-}
-
-static void solve_nu_svc(
- const svm_problem *prob, const svm_parameter *param,
- double *alpha, Solver::SolutionInfo* si)
-{
- int i;
- int l = prob->l;
- double nu = param->nu;
-
- auto *y = new schar[l];
- auto *C = new double[l];
-
- for(i=0;i<l;i++)
- {
- if(prob->y[i]>0)
- y[i] = +1;
- else
- y[i] = -1;
- C[i] = prob->W[i];
- }
-
- double nu_l = 0;
- for(i=0;i<l;i++) nu_l += nu*C[i];
- double sum_pos = nu_l/2;
- double sum_neg = nu_l/2;
-
- for(i=0;i<l;i++)
- if(y[i] == +1)
- {
- alpha[i] = min(C[i],sum_pos);
- sum_pos -= alpha[i];
- }
- else
- {
- alpha[i] = min(C[i],sum_neg);
- sum_neg -= alpha[i];
- }
-
- auto *zeros = new double[l];
-
- for(i=0;i<l;i++)
- zeros[i] = 0;
-
- Solver_NU s;
- s.Solve(l, SVC_Q(*prob,*param,y), zeros, y,
- alpha, C, param->eps, si, param->shrinking);
- double r = si->r;
-
- info("C = %f\n",1/r);
-
- for(i=0;i<l;i++)
- {
- alpha[i] *= y[i]/r;
- si->upper_bound[i] /= r;
- }
-
- si->rho /= r;
- si->obj /= (r*r);
-
- delete[] C;
- delete[] y;
- delete[] zeros;
-}
-
-static void solve_one_class(
- const svm_problem *prob, const svm_parameter *param,
- double *alpha, Solver::SolutionInfo* si)
-{
- int l = prob->l;
- auto *zeros = new double[l];
- auto *ones = new schar[l];
- auto *C = new double[l];
- int i;
-
- double nu_l = 0;
-
- for(i=0;i<l;i++)
- {
- C[i] = prob->W[i];
- nu_l += C[i] * param->nu;
- }
-
- i = 0;
- while(nu_l > 0)
- {
- alpha[i] = min(C[i],nu_l);
- nu_l -= alpha[i];
- ++i;
- }
- for(;i<l;i++)
- alpha[i] = 0;
-
- for(i=0;i<l;i++)
- {
- zeros[i] = 0;
- ones[i] = 1;
- }
-
- Solver s;
- s.Solve(l, ONE_CLASS_Q(*prob,*param), zeros, ones,
- alpha, C, param->eps, si, param->shrinking);
-
- delete[] C;
- delete[] zeros;
- delete[] ones;
-}
-
-static void solve_epsilon_svr(
- const svm_problem *prob, const svm_parameter *param,
- double *alpha, Solver::SolutionInfo* si)
-{
- int l = prob->l;
- auto *alpha2 = new double[2*l];
- auto *linear_term = new double[2*l];
- auto *C = new double[2*l];
- auto *y = new schar[2*l];
- int i;
-
- for(i=0;i<l;i++)
- {
- alpha2[i] = 0;
- linear_term[i] = param->p - prob->y[i];
- y[i] = 1;
- C[i] = prob->W[i]*param->C;
-
- alpha2[i+l] = 0;
- linear_term[i+l] = param->p + prob->y[i];
- y[i+l] = -1;
- C[i+l] = prob->W[i]*param->C;
- }
-
- Solver s;
- s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
- alpha2, C, param->eps, si, param->shrinking);
- for(i=0;i<l;i++)
- {
- alpha[i] = alpha2[i] - alpha2[i+l];
- }
- //info("nu = %f\n",sum_alpha/(param->C*l));
- delete[] alpha2;
- delete[] linear_term;
- delete[] C;
- delete[] y;
-}
-
-static void solve_nu_svr(
- const svm_problem *prob, const svm_parameter *param,
- double *alpha, Solver::SolutionInfo* si)
-{
- int l = prob->l;
- auto *C = new double[2*l];
- auto *alpha2 = new double[2*l];
- auto *linear_term = new double[2*l];
- auto *y = new schar[2*l];
- int i;
-
- double sum = 0;
- for(i=0;i<l;i++)
- {
- C[i] = C[i+l] = prob->W[i]*param->C;
- sum += C[i] * param->nu;
- }
- sum /= 2;
-
- for(i=0;i<l;i++)
- {
- alpha2[i] = alpha2[i+l] = min(sum,C[i]);
- sum -= alpha2[i];
-
- linear_term[i] = - prob->y[i];
- y[i] = 1;
-
- linear_term[i+l] = prob->y[i];
- y[i+l] = -1;
- }
-
- Solver_NU s;
- s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
- alpha2, C, param->eps, si, param->shrinking);
-
- info("epsilon = %f\n",-si->r);
-
- for(i=0;i<l;i++)
- alpha[i] = alpha2[i] - alpha2[i+l];
-
- delete[] alpha2;
- delete[] linear_term;
- delete[] C;
- delete[] y;
-}
-
-//
-// decision_function
-//
-struct decision_function
-{
- double *alpha;
- double rho;
-};
-
-static decision_function svm_train_one(
- const svm_problem *prob, const svm_parameter *param,
- double Cp, double Cn)
-{
- auto *alpha = Malloc(double,prob->l);
- Solver::SolutionInfo si;
- switch(param->svm_type)
- {
- case C_SVC:
- si.upper_bound = Malloc(double,prob->l);
- solve_c_svc(prob,param,alpha,&si,Cp,Cn);
- break;
- case NU_SVC:
- si.upper_bound = Malloc(double,prob->l);
- solve_nu_svc(prob,param,alpha,&si);
- break;
- case ONE_CLASS:
- si.upper_bound = Malloc(double,prob->l);
- solve_one_class(prob,param,alpha,&si);
- break;
- case EPSILON_SVR:
- si.upper_bound = Malloc(double,2*prob->l);
- solve_epsilon_svr(prob,param,alpha,&si);
- break;
- case NU_SVR:
- si.upper_bound = Malloc(double,2*prob->l);
- solve_nu_svr(prob,param,alpha,&si);
- break;
- }
-
- info("obj = %f, rho = %f\n",si.obj,si.rho);
-
- // output SVs
-
- int nSV = 0;
- int nBSV = 0;
- for(int i=0;i<prob->l;i++)
- {
- if(fabs(alpha[i]) > 0)
- {
- ++nSV;
- if(prob->y[i] > 0)
- {
- if(fabs(alpha[i]) >= si.upper_bound[i])
- ++nBSV;
- }
- else
- {
- if(fabs(alpha[i]) >= si.upper_bound[i])
- ++nBSV;
- }
- }
- }
-
- free(si.upper_bound);
-
- info("nSV = %d, nBSV = %d\n",nSV,nBSV);
-
- decision_function f;
- f.alpha = alpha;
- f.rho = si.rho;
- return f;
-}
-
-// Platt's binary SVM Probablistic Output: an improvement from Lin et al.
-static void sigmoid_train(
- int l, const double *dec_values, const double *labels,
- double& A, double& B)
-{
- double prior1=0, prior0 = 0;
- int i;
-
- for (i=0;i<l;i++)
- if (labels[i] > 0) prior1+=1;
- else prior0+=1;
-
- int max_iter=100; // Maximal number of iterations
- double min_step=1e-10; // Minimal step taken in line search
- double sigma=1e-12; // For numerically strict PD of Hessian
- double eps=1e-5;
- double hiTarget=(prior1+1.0)/(prior1+2.0);
- double loTarget=1/(prior0+2.0);
- auto *t=Malloc(double,l);
- double fApB,p,q,h11,h22,h21,g1,g2,det,dA,dB,gd,stepsize;
- double newA,newB,newf,d1,d2;
- int iter;
-
- // Initial Point and Initial Fun Value
- A=0.0; B=log((prior0+1.0)/(prior1+1.0));
- double fval = 0.0;
-
- for (i=0;i<l;i++)
- {
- if (labels[i]>0) t[i]=hiTarget;
- else t[i]=loTarget;
- fApB = dec_values[i]*A+B;
- if (fApB>=0)
- fval += t[i]*fApB + log(1+exp(-fApB));
- else
- fval += (t[i] - 1)*fApB +log(1+exp(fApB));
- }
- for (iter=0;iter<max_iter;iter++)
- {
- // Update Gradient and Hessian (use H' = H + sigma I)
- h11=sigma; // numerically ensures strict PD
- h22=sigma;
- h21=0.0;g1=0.0;g2=0.0;
- for (i=0;i<l;i++)
- {
- fApB = dec_values[i]*A+B;
- if (fApB >= 0)
- {
- p=exp(-fApB)/(1.0+exp(-fApB));
- q=1.0/(1.0+exp(-fApB));
- }
- else
- {
- p=1.0/(1.0+exp(fApB));
- q=exp(fApB)/(1.0+exp(fApB));
- }
- d2=p*q;
- h11+=dec_values[i]*dec_values[i]*d2;
- h22+=d2;
- h21+=dec_values[i]*d2;
- d1=t[i]-p;
- g1+=dec_values[i]*d1;
- g2+=d1;
- }
-
- // Stopping Criteria
- if (fabs(g1)<eps && fabs(g2)<eps)
- break;
-
- // Finding Newton direction: -inv(H') * g
- det=h11*h22-h21*h21;
- dA=-(h22*g1 - h21 * g2) / det;
- dB=-(-h21*g1+ h11 * g2) / det;
- gd=g1*dA+g2*dB;
-
-
- stepsize = 1; // Line Search
- while (stepsize >= min_step)
- {
- newA = A + stepsize * dA;
- newB = B + stepsize * dB;
-
- // New function value
- newf = 0.0;
- for (i=0;i<l;i++)
- {
- fApB = dec_values[i]*newA+newB;
- if (fApB >= 0)
- newf += t[i]*fApB + log(1+exp(-fApB));
- else
- newf += (t[i] - 1)*fApB +log(1+exp(fApB));
- }
- // Check sufficient decrease
- if (newf<fval+0.0001*stepsize*gd)
- {
- A=newA;B=newB;fval=newf;
- break;
- }
- else
- stepsize = stepsize / 2.0;
- }
-
- if (stepsize < min_step)
- {
- info("Line search fails in two-class probability estimates\n");
- break;
- }
- }
-
- if (iter>=max_iter)
- info("Reaching maximal iterations in two-class probability estimates\n");
- free(t);
-}
-
-static double sigmoid_predict(double decision_value, double A, double B)
-{
- double fApB = decision_value*A+B;
- // 1-p used later; avoid catastrophic cancellation
- if (fApB >= 0)
- return exp(-fApB)/(1.0+exp(-fApB));
- else
- return 1.0/(1+exp(fApB)) ;
-}
-
-// Method 2 from the multiclass_prob paper by Wu, Lin, and Weng
-static void multiclass_probability(int k, double **r, double *p)
-{
- int t,j;
- int iter = 0, max_iter=max(100,k);
- auto **Q=Malloc(double *,k);
- auto *Qp=Malloc(double,k);
- double pQp, eps=0.005/k;
-
- for (t=0;t<k;t++)
- {
- p[t]=1.0/k; // Valid if k = 1
- Q[t]=Malloc(double,k);
- Q[t][t]=0;
- for (j=0;j<t;j++)
- {
- Q[t][t]+=r[j][t]*r[j][t];
- Q[t][j]=Q[j][t];
- }
- for (j=t+1;j<k;j++)
- {
- Q[t][t]+=r[j][t]*r[j][t];
- Q[t][j]=-r[j][t]*r[t][j];
- }
- }
- for (iter=0;iter<max_iter;iter++)
- {
- // stopping condition, recalculate QP,pQP for numerical accuracy
- pQp=0;
- for (t=0;t<k;t++)
- {
- Qp[t]=0;
- for (j=0;j<k;j++)
- Qp[t]+=Q[t][j]*p[j];
- pQp+=p[t]*Qp[t];
- }
- double max_error=0;
- for (t=0;t<k;t++)
- {
- double error=fabs(Qp[t]-pQp);
- if (error>max_error)
- max_error=error;
- }
- if (max_error<eps) break;
-
- for (t=0;t<k;t++)
- {
- double diff=(-Qp[t]+pQp)/Q[t][t];
- p[t]+=diff;
- pQp=(pQp+diff*(diff*Q[t][t]+2*Qp[t]))/(1+diff)/(1+diff);
- for (j=0;j<k;j++)
- {
- Qp[j]=(Qp[j]+diff*Q[t][j])/(1+diff);
- p[j]/=(1+diff);
- }
- }
- }
- if (iter>=max_iter)
- info("Exceeds max_iter in multiclass_prob\n");
- for(t=0;t<k;t++) free(Q[t]);
- free(Q);
- free(Qp);
-}
-
-// Cross-validation decision values for probability estimates
-static void svm_binary_svc_probability(
- const svm_problem *prob, const svm_parameter *param,
- double Cp, double Cn, double& probA, double& probB)
-{
- int i;
- int nr_fold = 5;
- auto *perm = Malloc(int,prob->l);
- auto *dec_values = Malloc(double,prob->l);
-
- // random shuffle
- for(i=0;i<prob->l;i++) perm[i]=i;
- for(i=0;i<prob->l;i++)
- {
- int j = i+rand()%(prob->l-i);
- swap(perm[i],perm[j]);
- }
- for(i=0;i<nr_fold;i++)
- {
- int begin = i*prob->l/nr_fold;
- int end = (i+1)*prob->l/nr_fold;
- int j,k;
- struct svm_problem subprob;
-
- subprob.l = prob->l-(end-begin);
- subprob.x = Malloc(struct svm_node*,subprob.l);
- subprob.y = Malloc(double,subprob.l);
- subprob.W = Malloc(double,subprob.l);
-
- k=0;
- for(j=0;j<begin;j++)
- {
- subprob.x[k] = prob->x[perm[j]];
- subprob.y[k] = prob->y[perm[j]];
- subprob.W[k] = prob->W[perm[j]];
- ++k;
- }
- for(j=end;j<prob->l;j++)
- {
- subprob.x[k] = prob->x[perm[j]];
- subprob.y[k] = prob->y[perm[j]];
- subprob.W[k] = prob->W[perm[j]];
- ++k;
- }
- int p_count=0,n_count=0;
- for(j=0;j<k;j++)
- if(subprob.y[j]>0)
- p_count++;
- else
- n_count++;
-
- if(p_count==0 && n_count==0)
- for(j=begin;j<end;j++)
- dec_values[perm[j]] = 0;
- else if(p_count > 0 && n_count == 0)
- for(j=begin;j<end;j++)
- dec_values[perm[j]] = 1;
- else if(p_count == 0 && n_count > 0)
- for(j=begin;j<end;j++)
- dec_values[perm[j]] = -1;
- else
- {
- svm_parameter subparam = *param;
- subparam.probability=0;
- subparam.C=1.0;
- subparam.nr_weight=2;
- subparam.weight_label = Malloc(int,2);
- subparam.weight = Malloc(double,2);
- subparam.weight_label[0]=+1;
- subparam.weight_label[1]=-1;
- subparam.weight[0]=Cp;
- subparam.weight[1]=Cn;
- struct svm_model *submodel = svm_train(&subprob,&subparam);
- for(j=begin;j<end;j++)
- {
- svm_predict_values(submodel,prob->x[perm[j]],&(dec_values[perm[j]]));
- // ensure +1 -1 order; reason not using CV subroutine
- dec_values[perm[j]] *= submodel->label[0];
- }
- svm_free_and_destroy_model(&submodel);
- svm_destroy_param(&subparam);
- }
- free(subprob.x);
- free(subprob.y);
- free(subprob.W);
- }
- sigmoid_train(prob->l,dec_values,prob->y,probA,probB);
- free(dec_values);
- free(perm);
-}
-
-// Return parameter of a Laplace distribution
-static double svm_svr_probability(
- const svm_problem *prob, const svm_parameter *param)
-{
- int i;
- int nr_fold = 5;
- auto *ymv = Malloc(double,prob->l);
- double mae = 0;
-
- svm_parameter newparam = *param;
- newparam.probability = 0;
- svm_cross_validation(prob,&newparam,nr_fold,ymv);
- for(i=0;i<prob->l;i++)
- {
- ymv[i]=prob->y[i]-ymv[i];
- mae += fabs(ymv[i]);
- }
- mae /= prob->l;
- double std=sqrt(2*mae*mae);
- int count=0;
- mae=0;
- for(i=0;i<prob->l;i++)
- if (fabs(ymv[i]) > 5*std)
- count=count+1;
- else
- mae+=fabs(ymv[i]);
- mae /= (prob->l-count);
- info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma= %g\n",mae);
- free(ymv);
- return mae;
-}
-
-
-// label: label name, start: begin of each class, count: #data of classes, perm: indices to the original data
-// perm, length l, must be allocated before calling this subroutine
-static void svm_group_classes(const svm_problem *prob, int *nr_class_ret, int **label_ret, int **start_ret, int **count_ret, int *perm)
-{
- int l = prob->l;
- int max_nr_class = 16;
- int nr_class = 0;
- auto *label = Malloc(int,max_nr_class);
- auto *count = Malloc(int,max_nr_class);
- auto *data_label = Malloc(int,l);
- int i;
-
- for(i=0;i<l;i++)
- {
- auto this_label = (int)prob->y[i];
- int j;
- for(j=0;j<nr_class;j++)
- {
- if(this_label == label[j])
- {
- ++count[j];
- break;
- }
- }
- data_label[i] = j;
- if(j == nr_class)
- {
- if(nr_class == max_nr_class)
- {
- max_nr_class *= 2;
- label = (int *)realloc(label,max_nr_class*sizeof(int));
- count = (int *)realloc(count,max_nr_class*sizeof(int));
- }
- label[nr_class] = this_label;
- count[nr_class] = 1;
- ++nr_class;
- }
- }
-
- //
- // Labels are ordered by their first occurrence in the training set.
- // However, for two-class sets with -1/+1 labels and -1 appears first,
- // we swap labels to ensure that internally the binary SVM has positive data corresponding to the +1 instances.
- //
- if (nr_class == 2 && label[0] == -1 && label[1] == 1)
- {
- swap(label[0],label[1]);
- swap(count[0],count[1]);
- for(i=0;i<l;i++)
- {
- if(data_label[i] == 0)
- data_label[i] = 1;
- else
- data_label[i] = 0;
- }
- }
-
- auto *start = Malloc(int,nr_class);
- start[0] = 0;
- for(i=1;i<nr_class;i++)
- start[i] = start[i-1]+count[i-1];
- for(i=0;i<l;i++)
- {
- perm[start[data_label[i]]] = i;
- ++start[data_label[i]];
- }
- start[0] = 0;
- for(i=1;i<nr_class;i++)
- start[i] = start[i-1]+count[i-1];
-
- *nr_class_ret = nr_class;
- *label_ret = label;
- *start_ret = start;
- *count_ret = count;
- free(data_label);
-}
-
-//
-// Remove zero weighed data as libsvm and some liblinear solvers require C > 0.
-//
-static void remove_zero_weight(svm_problem *newprob, const svm_problem *prob)
-{
- int i;
- int l = 0;
- for(i=0;i<prob->l;i++)
- if(prob->W[i] > 0) l++;
- *newprob = *prob;
- newprob->l = l;
- newprob->x = Malloc(svm_node*,l);
- newprob->y = Malloc(double,l);
- newprob->W = Malloc(double,l);
-
- int j = 0;
- for(i=0;i<prob->l;i++)
- if(prob->W[i] > 0)
- {
- newprob->x[j] = prob->x[i];
- newprob->y[j] = prob->y[i];
- newprob->W[j] = prob->W[i];
- j++;
- }
-}
-
-//
-// Interface functions
-//
-svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
-{
- svm_problem newprob;
- remove_zero_weight(&newprob, prob);
- prob = &newprob;
-
- auto *model = Malloc(svm_model,1);
- model->param = *param;
- model->free_sv = 0; // XXX
-
- if(param->svm_type == ONE_CLASS ||
- param->svm_type == EPSILON_SVR ||
- param->svm_type == NU_SVR)
- {
- // regression or one-class-svm
- model->nr_class = 2;
- model->label = nullptr;
- model->nSV = nullptr;
- model->probA = nullptr; model->probB = nullptr;
- model->sv_coef = Malloc(double *,1);
-
- if(param->probability &&
- (param->svm_type == EPSILON_SVR ||
- param->svm_type == NU_SVR))
- {
- model->probA = Malloc(double,1);
- model->probA[0] = svm_svr_probability(prob,param);
- }
-
- decision_function f = svm_train_one(prob,param,0,0);
- model->rho = Malloc(double,1);
- model->rho[0] = f.rho;
-
- int nSV = 0;
- int i;
- for(i=0;i<prob->l;i++)
- if(fabs(f.alpha[i]) > 0) ++nSV;
- model->l = nSV;
- model->SV = Malloc(svm_node *,nSV);
- model->sv_coef[0] = Malloc(double,nSV);
- model->sv_indices = Malloc(int,nSV);
- int j = 0;
- for(i=0;i<prob->l;i++)
- if(fabs(f.alpha[i]) > 0)
- {
- model->SV[j] = prob->x[i];
- model->sv_coef[0][j] = f.alpha[i];
- model->sv_indices[j] = i+1;
- ++j;
- }
-
- free(f.alpha);
- }
- else
- {
- // classification
- int l = prob->l;
- int nr_class;
- int *label = nullptr;
- int *start = nullptr;
- int *count = nullptr;
- auto *perm = Malloc(int,l);
-
- // group training data of the same class
- svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
- if(nr_class == 1)
- info("WARNING: training data in only one class. See README for details.\n");
-
- auto **x = Malloc(svm_node *,l);
- double *W;
- W = Malloc(double,l);
-
- int i;
- for(i=0;i<l;i++)
- {
- x[i] = prob->x[perm[i]];
- W[i] = prob->W[perm[i]];
- }
-
- // calculate weighted C
-
- auto *weighted_C = Malloc(double, nr_class);
- for(i=0;i<nr_class;i++)
- weighted_C[i] = param->C;
- for(i=0;i<param->nr_weight;i++)
- {
- int j;
- for(j=0;j<nr_class;j++)
- if(param->weight_label[i] == label[j])
- break;
- if(j == nr_class)
- fprintf(stderr,"WARNING: class label %d specified in weight is not found\n", param->weight_label[i]);
- else
- weighted_C[j] *= param->weight[i];
- }
-
- // train k*(k-1)/2 models
-
- auto *nonzero = Malloc(bool,l);
- for(i=0;i<l;i++)
- nonzero[i] = false;
- auto *f = Malloc(decision_function,nr_class*(nr_class-1)/2);
-
- double *probA=nullptr,*probB=nullptr;
- if (param->probability)
- {
- probA=Malloc(double,nr_class*(nr_class-1)/2);
- probB=Malloc(double,nr_class*(nr_class-1)/2);
- }
-
- int p = 0;
- for(i=0;i<nr_class;i++)
- for(int j=i+1;j<nr_class;j++)
- {
- svm_problem sub_prob;
- int si = start[i], sj = start[j];
- int ci = count[i], cj = count[j];
- sub_prob.l = ci+cj;
- sub_prob.x = Malloc(svm_node *,sub_prob.l);
- sub_prob.y = Malloc(double,sub_prob.l);
- sub_prob.W = Malloc(double,sub_prob.l);
- int k;
- for(k=0;k<ci;k++)
- {
- sub_prob.x[k] = x[si+k];
- sub_prob.y[k] = +1;
- sub_prob.W[k] = W[si+k];
- }
- for(k=0;k<cj;k++)
- {
- sub_prob.x[ci+k] = x[sj+k];
- sub_prob.y[ci+k] = -1;
- sub_prob.W[ci+k] = W[sj+k];
- }
-
- if(param->probability)
- svm_binary_svc_probability(&sub_prob,param,weighted_C[i],weighted_C[j],probA[p],probB[p]);
-
- f[p] = svm_train_one(&sub_prob,param,weighted_C[i],weighted_C[j]);
- for(k=0;k<ci;k++)
- if(!nonzero[si+k] && fabs(f[p].alpha[k]) > 0)
- nonzero[si+k] = true;
- for(k=0;k<cj;k++)
- if(!nonzero[sj+k] && fabs(f[p].alpha[ci+k]) > 0)
- nonzero[sj+k] = true;
- free(sub_prob.x);
- free(sub_prob.y);
- free(sub_prob.W);
- ++p;
- }
-
- // build output
-
- model->nr_class = nr_class;
-
- model->label = Malloc(int,nr_class);
- for(i=0;i<nr_class;i++)
- model->label[i] = label[i];
-
- model->rho = Malloc(double,nr_class*(nr_class-1)/2);
- for(i=0;i<nr_class*(nr_class-1)/2;i++)
- model->rho[i] = f[i].rho;
-
- if(param->probability)
- {
- model->probA = Malloc(double,nr_class*(nr_class-1)/2);
- model->probB = Malloc(double,nr_class*(nr_class-1)/2);
- for(i=0;i<nr_class*(nr_class-1)/2;i++)
- {
- model->probA[i] = probA[i];
- model->probB[i] = probB[i];
- }
- }
- else
- {
- model->probA=nullptr;
- model->probB=nullptr;
- }
-
- int total_sv = 0;
- auto *nz_count = Malloc(int,nr_class);
- model->nSV = Malloc(int,nr_class);
- for(i=0;i<nr_class;i++)
- {
- int nSV = 0;
- for(int j=0;j<count[i];j++)
- if(nonzero[start[i]+j])
- {
- ++nSV;
- ++total_sv;
- }
- model->nSV[i] = nSV;
- nz_count[i] = nSV;
- }
-
- info("Total nSV = %d\n",total_sv);
-
- model->l = total_sv;
- model->SV = Malloc(svm_node *,total_sv);
- model->sv_indices = Malloc(int,total_sv);
- p = 0;
- for(i=0;i<l;i++)
- if(nonzero[i])
- {
- model->SV[p] = x[i];
- model->sv_indices[p++] = perm[i] + 1;
- }
-
- auto *nz_start = Malloc(int,nr_class);
- nz_start[0] = 0;
- for(i=1;i<nr_class;i++)
- nz_start[i] = nz_start[i-1]+nz_count[i-1];
-
- model->sv_coef = Malloc(double *,nr_class-1);
- for(i=0;i<nr_class-1;i++)
- model->sv_coef[i] = Malloc(double,total_sv);
-
- p = 0;
- for(i=0;i<nr_class;i++)
- for(int j=i+1;j<nr_class;j++)
- {
- // classifier (i,j): coefficients with
- // i are in sv_coef[j-1][nz_start[i]...],
- // j are in sv_coef[i][nz_start[j]...]
-
- int si = start[i];
- int sj = start[j];
- int ci = count[i];
- int cj = count[j];
-
- int q = nz_start[i];
- int k;
- for(k=0;k<ci;k++)
- if(nonzero[si+k])
- model->sv_coef[j-1][q++] = f[p].alpha[k];
- q = nz_start[j];
- for(k=0;k<cj;k++)
- if(nonzero[sj+k])
- model->sv_coef[i][q++] = f[p].alpha[ci+k];
- ++p;
- }
-
- free(label);
- free(probA);
- free(probB);
- free(count);
- free(perm);
- free(start);
- free(W);
- free(x);
- free(weighted_C);
- free(nonzero);
- for(i=0;i<nr_class*(nr_class-1)/2;i++)
- free(f[i].alpha);
- free(f);
- free(nz_count);
- free(nz_start);
- }
- free(newprob.x);
- free(newprob.y);
- free(newprob.W);
- return model;
-}
-
-// Stratified cross validation
-void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, int nr_fold, double *target)
-{
- int i;
- int *fold_start;
- int l = prob->l;
- auto *perm = Malloc(int,l);
- int nr_class;
- if (nr_fold > l)
- {
- nr_fold = l;
- fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n");
- }
- fold_start = Malloc(int,nr_fold+1);
- // stratified cv may not give leave-one-out rate
- // Each class to l folds -> some folds may have zero elements
- if((param->svm_type == C_SVC ||
- param->svm_type == NU_SVC) && nr_fold < l)
- {
- int *start = nullptr;
- int *label = nullptr;
- int *count = nullptr;
- svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
-
- // random shuffle and then data grouped by fold using the array perm
- auto *fold_count = Malloc(int,nr_fold);
- int c;
- auto *index = Malloc(int,l);
- for(i=0;i<l;i++)
- index[i]=perm[i];
- for (c=0; c<nr_class; c++)
- for(i=0;i<count[c];i++)
- {
- int j = i+rand()%(count[c]-i);
- swap(index[start[c]+j],index[start[c]+i]);
- }
- for(i=0;i<nr_fold;i++)
- {
- fold_count[i] = 0;
- for (c=0; c<nr_class;c++)
- fold_count[i]+=(i+1)*count[c]/nr_fold-i*count[c]/nr_fold;
- }
- fold_start[0]=0;
- for (i=1;i<=nr_fold;i++)
- fold_start[i] = fold_start[i-1]+fold_count[i-1];
- for (c=0; c<nr_class;c++)
- for(i=0;i<nr_fold;i++)
- {
- int begin = start[c]+i*count[c]/nr_fold;
- int end = start[c]+(i+1)*count[c]/nr_fold;
- for(int j=begin;j<end;j++)
- {
- perm[fold_start[i]] = index[j];
- fold_start[i]++;
- }
- }
- fold_start[0]=0;
- for (i=1;i<=nr_fold;i++)
- fold_start[i] = fold_start[i-1]+fold_count[i-1];
- free(start);
- free(label);
- free(count);
- free(index);
- free(fold_count);
- }
- else
- {
- for(i=0;i<l;i++) perm[i]=i;
- for(i=0;i<l;i++)
- {
- int j = i+rand()%(l-i);
- swap(perm[i],perm[j]);
- }
- for(i=0;i<=nr_fold;i++)
- fold_start[i]=i*l/nr_fold;
- }
-
- for(i=0;i<nr_fold;i++)
- {
- int begin = fold_start[i];
- int end = fold_start[i+1];
- int j,k;
- struct svm_problem subprob;
-
- subprob.l = l-(end-begin);
- subprob.x = Malloc(struct svm_node*,subprob.l);
- subprob.y = Malloc(double,subprob.l);
-
- subprob.W = Malloc(double,subprob.l);
- k=0;
- for(j=0;j<begin;j++)
- {
- subprob.x[k] = prob->x[perm[j]];
- subprob.y[k] = prob->y[perm[j]];
- subprob.W[k] = prob->W[perm[j]];
- ++k;
- }
- for(j=end;j<l;j++)
- {
- subprob.x[k] = prob->x[perm[j]];
- subprob.y[k] = prob->y[perm[j]];
- subprob.W[k] = prob->W[perm[j]];
- ++k;
- }
- struct svm_model *submodel = svm_train(&subprob,param);
- if(param->probability &&
- (param->svm_type == C_SVC || param->svm_type == NU_SVC))
- {
- auto *prob_estimates=Malloc(double,svm_get_nr_class(submodel));
- for(j=begin;j<end;j++)
- target[perm[j]] = svm_predict_probability(submodel,prob->x[perm[j]],prob_estimates);
- free(prob_estimates);
- }
- else
- for(j=begin;j<end;j++)
- target[perm[j]] = svm_predict(submodel,prob->x[perm[j]]);
- svm_free_and_destroy_model(&submodel);
- free(subprob.x);
- free(subprob.y);
- free(subprob.W);
- }
- free(fold_start);
- free(perm);
-}
-
-
-int svm_get_svm_type(const svm_model *model)
-{
- return model->param.svm_type;
-}
-
-int svm_get_nr_class(const svm_model *model)
-{
- return model->nr_class;
-}
-
-void svm_get_labels(const svm_model *model, int* label)
-{
- if (model->label != nullptr)
- for(int i=0;i<model->nr_class;i++)
- label[i] = model->label[i];
-}
-
-void svm_get_sv_indices(const svm_model *model, int* indices)
-{
- if (model->sv_indices != nullptr)
- for(int i=0;i<model->l;i++)
- indices[i] = model->sv_indices[i];
-}
-
-int svm_get_nr_sv(const svm_model *model)
-{
- return model->l;
-}
-
-double svm_get_svr_probability(const svm_model *model)
-{
- if ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) &&
- model->probA!=nullptr)
- return model->probA[0];
- else
- {
- fprintf(stderr,"Model doesn't contain information for SVR probability inference\n");
- return 0;
- }
-}
-
-double svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values)
-{
- int i;
- if(model->param.svm_type == ONE_CLASS ||
- model->param.svm_type == EPSILON_SVR ||
- model->param.svm_type == NU_SVR)
- {
- double *sv_coef = model->sv_coef[0];
- double sum = 0;
- for(i=0;i<model->l;i++)
- sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param);
- sum -= model->rho[0];
- *dec_values = sum;
-
- if(model->param.svm_type == ONE_CLASS)
- return (sum>0)?1:-1;
- else
- return sum;
- }
- else
- {
- int nr_class = model->nr_class;
- int l = model->l;
-
- auto *kvalue = Malloc(double,l);
- for(i=0;i<l;i++)
- kvalue[i] = Kernel::k_function(x,model->SV[i],model->param);
-
- auto *start = Malloc(int,nr_class);
- start[0] = 0;
- for(i=1;i<nr_class;i++)
- start[i] = start[i-1]+model->nSV[i-1];
-
- auto *vote = Malloc(int,nr_class);
- for(i=0;i<nr_class;i++)
- vote[i] = 0;
-
- int p=0;
- for(i=0;i<nr_class;i++)
- for(int j=i+1;j<nr_class;j++)
- {
- double sum = 0;
- int si = start[i];
- int sj = start[j];
- int ci = model->nSV[i];
- int cj = model->nSV[j];
-
- int k;
- double *coef1 = model->sv_coef[j-1];
- double *coef2 = model->sv_coef[i];
- for(k=0;k<ci;k++)
- sum += coef1[si+k] * kvalue[si+k];
- for(k=0;k<cj;k++)
- sum += coef2[sj+k] * kvalue[sj+k];
- sum -= model->rho[p];
- dec_values[p] = sum;
-
- if(dec_values[p] > 0)
- ++vote[i];
- else
- ++vote[j];
- p++;
- }
-
- int vote_max_idx = 0;
- for(i=1;i<nr_class;i++)
- if(vote[i] > vote[vote_max_idx])
- vote_max_idx = i;
-
- free(kvalue);
- free(start);
- free(vote);
- return model->label[vote_max_idx];
- }
-}
-
-double svm_predict(const svm_model *model, const svm_node *x)
-{
- int nr_class = model->nr_class;
- double *dec_values;
- if(model->param.svm_type == ONE_CLASS ||
- model->param.svm_type == EPSILON_SVR ||
- model->param.svm_type == NU_SVR)
- dec_values = Malloc(double, 1);
- else
- dec_values = Malloc(double, nr_class*(nr_class-1)/2);
- double pred_result = svm_predict_values(model, x, dec_values);
- free(dec_values);
- return pred_result;
-}
-
-double svm_predict_probability(
- const svm_model *model, const svm_node *x, double *prob_estimates)
-{
- if ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) &&
- model->probA!=nullptr && model->probB!=nullptr)
- {
- int i;
- int nr_class = model->nr_class;
- auto *dec_values = Malloc(double, nr_class*(nr_class-1)/2);
- svm_predict_values(model, x, dec_values);
-
- double min_prob=1e-7;
- auto **pairwise_prob=Malloc(double *,nr_class);
- for(i=0;i<nr_class;i++)
- pairwise_prob[i]=Malloc(double,nr_class);
- int k=0;
- for(i=0;i<nr_class;i++)
- for(int j=i+1;j<nr_class;j++)
- {
- pairwise_prob[i][j]=min(max(sigmoid_predict(dec_values[k],model->probA[k],model->probB[k]),min_prob),1-min_prob);
- pairwise_prob[j][i]=1-pairwise_prob[i][j];
- k++;
- }
- multiclass_probability(nr_class,pairwise_prob,prob_estimates);
-
- int prob_max_idx = 0;
- for(i=1;i<nr_class;i++)
- if(prob_estimates[i] > prob_estimates[prob_max_idx])
- prob_max_idx = i;
- for(i=0;i<nr_class;i++)
- free(pairwise_prob[i]);
- free(dec_values);
- free(pairwise_prob);
- return model->label[prob_max_idx];
- }
- else
- return svm_predict(model, x);
-}
-
-static const char *svm_type_table[] =
-{
- "c_svc","nu_svc","one_class","epsilon_svr","nu_svr",nullptr
-};
-
-static const char *kernel_type_table[]=
-{
- "linear","polynomial","rbf","sigmoid","precomputed",nullptr
-};
-
-int svm_save_model(const char *model_file_name, const svm_model *model)
-{
- FILE *fp = fopen(model_file_name,"w");
- if(fp==nullptr) return -1;
-
- mitk::LocaleSwitch localeSwitch("C");
-
- const svm_parameter& param = model->param;
-
- fprintf(fp,"svm_type %s\n", svm_type_table[param.svm_type]);
- fprintf(fp,"kernel_type %s\n", kernel_type_table[param.kernel_type]);
-
- if(param.kernel_type == POLY)
- fprintf(fp,"degree %d\n", param.degree);
-
- if(param.kernel_type == POLY || param.kernel_type == RBF || param.kernel_type == SIGMOID)
- fprintf(fp,"gamma %g\n", param.gamma);
-
- if(param.kernel_type == POLY || param.kernel_type == SIGMOID)
- fprintf(fp,"coef0 %g\n", param.coef0);
-
- int nr_class = model->nr_class;
- int l = model->l;
- fprintf(fp, "nr_class %d\n", nr_class);
- fprintf(fp, "total_sv %d\n",l);
-
- {
- fprintf(fp, "rho");
- for(int i=0;i<nr_class*(nr_class-1)/2;i++)
- fprintf(fp," %g",model->rho[i]);
- fprintf(fp, "\n");
- }
-
- if(model->label)
- {
- fprintf(fp, "label");
- for(int i=0;i<nr_class;i++)
- fprintf(fp," %d",model->label[i]);
- fprintf(fp, "\n");
- }
-
- if(model->probA) // regression has probA only
- {
- fprintf(fp, "probA");
- for(int i=0;i<nr_class*(nr_class-1)/2;i++)
- fprintf(fp," %g",model->probA[i]);
- fprintf(fp, "\n");
- }
- if(model->probB)
- {
- fprintf(fp, "probB");
- for(int i=0;i<nr_class*(nr_class-1)/2;i++)
- fprintf(fp," %g",model->probB[i]);
- fprintf(fp, "\n");
- }
-
- if(model->nSV)
- {
- fprintf(fp, "nr_sv");
- for(int i=0;i<nr_class;i++)
- fprintf(fp," %d",model->nSV[i]);
- fprintf(fp, "\n");
- }
-
- fprintf(fp, "SV\n");
- const double * const *sv_coef = model->sv_coef;
- const svm_node * const *SV = model->SV;
-
- for(int i=0;i<l;i++)
- {
- for(int j=0;j<nr_class-1;j++)
- fprintf(fp, "%.16g ",sv_coef[j][i]);
-
- const svm_node *p = SV[i];
-
- if(param.kernel_type == PRECOMPUTED)
- fprintf(fp,"0:%d ",(int)(p->value));
- else
- while(p->index != -1)
- {
- fprintf(fp,"%d:%.8g ",p->index,p->value);
- p++;
- }
- fprintf(fp, "\n");
- }
-
- if (ferror(fp) != 0 || fclose(fp) != 0) return -1;
- else return 0;
-}
-
-static char *line = nullptr;
-static int max_line_len;
-
-static char* readline(FILE *input)
-{
- int len;
-
- if(fgets(line,max_line_len,input) == nullptr)
- return nullptr;
-
- while(strrchr(line,'\n') == nullptr)
- {
- max_line_len *= 2;
- line = (char *) realloc(line,max_line_len);
- len = (int) strlen(line);
- if(fgets(line+len,max_line_len-len,input) == nullptr)
- break;
- }
- return line;
-}
-
-//
-// FSCANF helps to handle fscanf failures.
-// Its do-while block avoids the ambiguity when
-// if (...)
-// FSCANF();
-// is used
-//
-#define FSCANF(_stream, _format, _var) do{ if (fscanf(_stream, _format, _var) != 1) return false; }while(0)
-bool read_model_header(FILE *fp, svm_model* model)
-{
- svm_parameter& param = model->param;
- char cmd[81];
- while(true)
- {
- FSCANF(fp,"%80s",cmd);
-
- if(strcmp(cmd,"svm_type")==0)
- {
- FSCANF(fp,"%80s",cmd);
- int i;
- for(i=0;svm_type_table[i];i++)
- {
- if(strcmp(svm_type_table[i],cmd)==0)
- {
- param.svm_type=i;
- break;
- }
- }
- if(svm_type_table[i] == nullptr)
- {
- fprintf(stderr,"unknown svm type.\n");
- return false;
- }
- }
- else if(strcmp(cmd,"kernel_type")==0)
- {
- FSCANF(fp,"%80s",cmd);
- int i;
- for(i=0;kernel_type_table[i];i++)
- {
- if(strcmp(kernel_type_table[i],cmd)==0)
- {
- param.kernel_type=i;
- break;
- }
- }
- if(kernel_type_table[i] == nullptr)
- {
- fprintf(stderr,"unknown kernel function.\n");
- return false;
- }
- }
- else if(strcmp(cmd,"degree")==0)
- FSCANF(fp,"%d",&param.degree);
- else if(strcmp(cmd,"gamma")==0)
- FSCANF(fp,"%lf",&param.gamma);
- else if(strcmp(cmd,"coef0")==0)
- FSCANF(fp,"%lf",&param.coef0);
- else if(strcmp(cmd,"nr_class")==0)
- FSCANF(fp,"%d",&model->nr_class);
- else if(strcmp(cmd,"total_sv")==0)
- FSCANF(fp,"%d",&model->l);
- else if(strcmp(cmd,"rho")==0)
- {
- int n = model->nr_class * (model->nr_class-1)/2;
- model->rho = Malloc(double,n);
- for(int i=0;i<n;i++)
- FSCANF(fp,"%lf",&model->rho[i]);
- }
- else if(strcmp(cmd,"label")==0)
- {
- int n = model->nr_class;
- model->label = Malloc(int,n);
- for(int i=0;i<n;i++)
- FSCANF(fp,"%d",&model->label[i]);
- }
- else if(strcmp(cmd,"probA")==0)
- {
- int n = model->nr_class * (model->nr_class-1)/2;
- model->probA = Malloc(double,n);
- for(int i=0;i<n;i++)
- FSCANF(fp,"%lf",&model->probA[i]);
- }
- else if(strcmp(cmd,"probB")==0)
- {
- int n = model->nr_class * (model->nr_class-1)/2;
- model->probB = Malloc(double,n);
- for(int i=0;i<n;i++)
- FSCANF(fp,"%lf",&model->probB[i]);
- }
- else if(strcmp(cmd,"nr_sv")==0)
- {
- int n = model->nr_class;
- model->nSV = Malloc(int,n);
- for(int i=0;i<n;i++)
- FSCANF(fp,"%d",&model->nSV[i]);
- }
- else if(strcmp(cmd,"SV")==0)
- {
- while(true)
- {
- int c = getc(fp);
- if(c==EOF || c=='\n') break;
- }
- break;
- }
- else
- {
- fprintf(stderr,"unknown text in model file: [%s]\n",cmd);
- return false;
- }
- }
-
- return true;
-
-}
-
-svm_model *svm_load_model(const char *model_file_name)
-{
- FILE *fp = fopen(model_file_name,"rb");
- if(fp==nullptr) return nullptr;
-
- mitk::LocaleSwitch localeSwitch("C");
-
- // read parameters
-
- auto *model = Malloc(svm_model,1);
- model->rho = nullptr;
- model->probA = nullptr;
- model->probB = nullptr;
- model->sv_indices = nullptr;
- model->label = nullptr;
- model->nSV = nullptr;
-
- // read header
- if (!read_model_header(fp, model))
- {
- fprintf(stderr, "ERROR: fscanf failed to read model\n");
- free(model->rho);
- free(model->label);
- free(model->nSV);
- free(model);
- return nullptr;
- }
-
- // read sv_coef and SV
-
- int elements = 0;
- long pos = ftell(fp);
-
- max_line_len = 1024;
- line = Malloc(char,max_line_len);
- char *p,*endptr,*idx,*val;
-
- while(readline(fp)!=nullptr)
- {
- p = strtok(line,":");
- while(true)
- {
- p = strtok(nullptr,":");
- if(p == nullptr)
- break;
- ++elements;
- }
- }
- elements += model->l;
-
- fseek(fp,pos,SEEK_SET);
-
- int m = model->nr_class - 1;
- int l = model->l;
- model->sv_coef = Malloc(double *,m);
- int i;
- for(i=0;i<m;i++)
- model->sv_coef[i] = Malloc(double,l);
- model->SV = Malloc(svm_node*,l);
- svm_node *x_space = nullptr;
- if(l>0) x_space = Malloc(svm_node,elements);
-
- int j=0;
- for(i=0;i<l;i++)
- {
- readline(fp);
- model->SV[i] = &x_space[j];
-
- p = strtok(line, " \t");
- model->sv_coef[0][i] = strtod(p,&endptr);
- for(int k=1;k<m;k++)
- {
- p = strtok(nullptr, " \t");
- model->sv_coef[k][i] = strtod(p,&endptr);
- }
-
- while(true)
- {
- idx = strtok(nullptr, ":");
- val = strtok(nullptr, " \t");
-
- if(val == nullptr)
- break;
- x_space[j].index = (int) strtol(idx,&endptr,10);
- x_space[j].value = strtod(val,&endptr);
-
- ++j;
- }
- x_space[j++].index = -1;
- }
- free(line);
-
- if (ferror(fp) != 0 || fclose(fp) != 0)
- return nullptr;
-
- model->free_sv = 1; // XXX
- return model;
-}
-
-void svm_free_model_content(svm_model* model_ptr)
-{
- if(model_ptr->free_sv && model_ptr->l > 0 && model_ptr->SV != nullptr)
- free((void *)(model_ptr->SV[0]));
- if(model_ptr->sv_coef)
- {
- for(int i=0;i<model_ptr->nr_class-1;i++)
- free(model_ptr->sv_coef[i]);
- }
-
- free(model_ptr->SV);
- model_ptr->SV = nullptr;
-
- free(model_ptr->sv_coef);
- model_ptr->sv_coef = nullptr;
-
- free(model_ptr->rho);
- model_ptr->rho = nullptr;
-
- free(model_ptr->label);
- model_ptr->label= nullptr;
-
- free(model_ptr->probA);
- model_ptr->probA = nullptr;
-
- free(model_ptr->probB);
- model_ptr->probB= nullptr;
-
- free(model_ptr->sv_indices);
- model_ptr->sv_indices = nullptr;
-
- free(model_ptr->nSV);
- model_ptr->nSV = nullptr;
-}
-
-void svm_free_and_destroy_model(svm_model** model_ptr_ptr)
-{
- if(model_ptr_ptr != nullptr && *model_ptr_ptr != nullptr)
- {
- svm_free_model_content(*model_ptr_ptr);
- free(*model_ptr_ptr);
- *model_ptr_ptr = nullptr;
- }
-}
-
-void svm_destroy_param(svm_parameter* param)
-{
- free(param->weight_label);
- free(param->weight);
-}
-
-const char *svm_check_parameter(const svm_problem *prob, const svm_parameter *param)
-{
- // svm_type
-
- int svm_type = param->svm_type;
- if(svm_type != C_SVC &&
- svm_type != NU_SVC &&
- svm_type != ONE_CLASS &&
- svm_type != EPSILON_SVR &&
- svm_type != NU_SVR)
- return "unknown svm type";
-
- // kernel_type, degree
-
- int kernel_type = param->kernel_type;
- if(kernel_type != LINEAR &&
- kernel_type != POLY &&
- kernel_type != RBF &&
- kernel_type != SIGMOID &&
- kernel_type != PRECOMPUTED)
- return "unknown kernel type";
-
- if(param->gamma < 0)
- return "gamma < 0";
-
- if(param->degree < 0)
- return "degree of polynomial kernel < 0";
-
- // cache_size,eps,C,nu,p,shrinking
-
- if(param->cache_size <= 0)
- return "cache_size <= 0";
-
- if(param->eps <= 0)
- return "eps <= 0";
-
- if(svm_type == C_SVC ||
- svm_type == EPSILON_SVR ||
- svm_type == NU_SVR)
- if(param->C <= 0)
- return "C <= 0";
-
- if(svm_type == NU_SVC ||
- svm_type == ONE_CLASS ||
- svm_type == NU_SVR)
- if(param->nu <= 0 || param->nu > 1)
- return "nu <= 0 or nu > 1";
-
- if(svm_type == EPSILON_SVR)
- if(param->p < 0)
- return "p < 0";
-
- if(param->shrinking != 0 &&
- param->shrinking != 1)
- return "shrinking != 0 and shrinking != 1";
-
- if(param->probability != 0 &&
- param->probability != 1)
- return "probability != 0 and probability != 1";
-
- if(param->probability == 1 &&
- svm_type == ONE_CLASS)
- return "one-class SVM probability output not supported yet";
-
-
- // check whether nu-svc is feasible
-
- if(svm_type == NU_SVC)
- {
- int l = prob->l;
- int max_nr_class = 16;
- int nr_class = 0;
- auto *label = Malloc(int,max_nr_class);
- auto *count = Malloc(double,max_nr_class);
-
- int i;
- for(i=0;i<l;i++)
- {
- auto this_label = (int)prob->y[i];
- int j;
- for(j=0;j<nr_class;j++)
- if(this_label == label[j])
- {
- count[j] += prob->W[i];
- break;
- }
- if(j == nr_class)
- {
- if(nr_class == max_nr_class)
- {
- max_nr_class *= 2;
- label = (int *)realloc(label,max_nr_class*sizeof(int));
- count = (double *)realloc(count,max_nr_class*sizeof(double));
- }
- label[nr_class] = this_label;
- count[nr_class] = prob->W[i];
- ++nr_class;
- }
- }
-
- for(i=0;i<nr_class;i++)
- {
- double n1 = count[i];
- for(int j=i+1;j<nr_class;j++)
- {
- double n2 = count[j];
- if(param->nu*(n1+n2)/2 > min(n1,n2))
- {
- free(label);
- free(count);
- return "specified nu is infeasible";
- }
- }
- }
- free(label);
- free(count);
- }
-
- return nullptr;
-}
-
-int svm_check_probability_model(const svm_model *model)
-{
- return ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) &&
- model->probA!=nullptr && model->probB!=nullptr) ||
- ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) &&
- model->probA!=nullptr);
-}
-
-void svm_set_print_string_function(void (*print_func)(const char *))
-{
- if(print_func == nullptr)
- svm_print_string = &print_string_stdout;
- else
- svm_print_string = print_func;
-}
diff --git a/Modules/Classification/CLLibSVM/test/CMakeLists.txt b/Modules/Classification/CLLibSVM/test/CMakeLists.txt
deleted file mode 100644
index 5a6a2c1bf5..0000000000
--- a/Modules/Classification/CLLibSVM/test/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-MITK_CREATE_MODULE_TESTS()
-
-if(TARGET ${TESTDRIVER})
- mitk_use_modules(TARGET ${TESTDRIVER} PACKAGES ITK|IOCSV)
-endif()
diff --git a/Modules/Classification/CLLibSVM/test/files.cmake b/Modules/Classification/CLLibSVM/test/files.cmake
deleted file mode 100644
index 51f31d7be4..0000000000
--- a/Modules/Classification/CLLibSVM/test/files.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-set(MODULE_TESTS
- mitkLibSVMClassifierTest.cpp
-)
diff --git a/Modules/Classification/CLLibSVM/test/mitkLibSVMClassifierTest.cpp b/Modules/Classification/CLLibSVM/test/mitkLibSVMClassifierTest.cpp
deleted file mode 100644
index 25a7f021a9..0000000000
--- a/Modules/Classification/CLLibSVM/test/mitkLibSVMClassifierTest.cpp
+++ /dev/null
@@ -1,310 +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 <mitkTestingMacros.h>
-#include <mitkTestFixture.h>
-#include "mitkIOUtil.h"
-#include "itkArray2D.h"
-
-#include <mitkLibSVMClassifier.h>
-#include <itkLabelSampler.h>
-#include <mitkImageCast.h>
-#include <mitkStandaloneDataStorage.h>
-#include <itkCSVArray2DFileReader.h>
-#include <itkCSVArray2DDataObject.h>
-#include <itkCSVNumericObjectFileWriter.h>
-
-//#include <boost/algorithm/string.hpp>
-
-class mitkLibSVMClassifierTestSuite : public mitk::TestFixture
-{
- CPPUNIT_TEST_SUITE(mitkLibSVMClassifierTestSuite);
- MITK_TEST(TrainSVMClassifier_MatlabDataSet_shouldReturnTrue);
- MITK_TEST(TrainSVMClassifier_BreastCancerDataSet_shouldReturnTrue);
- CPPUNIT_TEST_SUITE_END();
-
-private:
-
- typedef Eigen::Matrix<double ,Eigen::Dynamic,Eigen::Dynamic> MatrixDoubleType;
- typedef Eigen::Matrix<int, Eigen::Dynamic,Eigen::Dynamic> MatrixIntType;
-
- Eigen::MatrixXd m_TrainingMatrixX;
- Eigen::MatrixXi m_TrainingLabelMatrixY;
- Eigen::MatrixXd m_TestXPredict;
- Eigen::MatrixXi m_TestYPredict;
-
- mitk::LibSVMClassifier::Pointer classifier;
-
-public:
-
- /*Reading an file, which includes the trainingdataset and the testdataset, and convert the
- content of the file into an 2dim matrixpair.
- There are an delimiter, which separates the matrix into an trainingmatrix and testmatrix */
- template<typename T>
- std::pair<Eigen::Matrix<T ,Eigen::Dynamic,Eigen::Dynamic>,Eigen::Matrix<T ,Eigen::Dynamic,Eigen::Dynamic> >convertCSVToMatrix(const std::string &path, char delimiter,double range, bool isXMatrix)
- {
- typename itk::CSVArray2DFileReader<T>::Pointer fr = itk::CSVArray2DFileReader<T>::New();
- fr->SetFileName(path);
- fr->SetFieldDelimiterCharacter(delimiter);
- fr->HasColumnHeadersOff();
- fr->HasRowHeadersOff();
- fr->Parse();
- try{
- fr->Update();
- }catch(itk::ExceptionObject& ex){
- cout << "Exception caught!" << std::endl;
- cout << ex << std::endl;
- }
-
- typename itk::CSVArray2DDataObject<T>::Pointer p = fr->GetOutput();
- unsigned int maxrowrange = p->GetMatrix().rows();
- unsigned int c = p->GetMatrix().cols();
- auto percentRange = (unsigned int)(maxrowrange*range);
-
- if(isXMatrix == true)
- {
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> trainMatrixX(percentRange,c);
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> testMatrixXPredict(maxrowrange-percentRange,c);
-
- for(unsigned int row = 0; row < percentRange; row++){
- for(unsigned int col = 0; col < c; col++){
- trainMatrixX(row,col) = p->GetData(row,col);
- }
- }
-
- for(unsigned int row = percentRange; row < maxrowrange; row++){
- for(unsigned int col = 0; col < c; col++){
- testMatrixXPredict(row-percentRange,col) = p->GetData(row,col);
- }
- }
-
- return std::make_pair(trainMatrixX,testMatrixXPredict);
- }
- else
- {
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> trainLabelMatrixY(percentRange,c);
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> testMatrixYPredict(maxrowrange-percentRange,c);
-
- for(unsigned int row = 0; row < percentRange; row++){
- for(unsigned int col = 0; col < c; col++){
- trainLabelMatrixY(row,col) = p->GetData(row,col);
- }
- }
-
- for(unsigned int row = percentRange; row < maxrowrange; row++){
- for(unsigned int col = 0; col < c; col++){
- testMatrixYPredict(row-percentRange,col) = p->GetData(row,col);
- }
- }
-
- return std::make_pair(trainLabelMatrixY,testMatrixYPredict);
- }
- }
-
- /*
- Reading an csv-data and transfer the included datas into an matrix.
- */
- template<typename T>
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> readCsvData(const std::string &path, char delimiter)
- {
- typename itk::CSVArray2DFileReader<T>::Pointer fr = itk::CSVArray2DFileReader<T>::New();
- fr->SetFileName(path);
- fr->SetFieldDelimiterCharacter(delimiter);
- fr->HasColumnHeadersOff();
- fr->HasRowHeadersOff();
- fr->Parse();
- try{
- fr->Update();
- }catch(itk::ExceptionObject& ex){
- cout << "Exception caught!" << std::endl;
- cout << ex << std::endl;
- }
-
- typename itk::CSVArray2DDataObject<T>::Pointer p = fr->GetOutput();
- unsigned int maxrowrange = p->GetMatrix().rows();
- unsigned int maxcols = p->GetMatrix().cols();
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> matrix(maxrowrange,maxcols);
-
- for(unsigned int rows = 0; rows < maxrowrange; rows++){
- for(unsigned int cols = 0; cols < maxcols; cols++ ){
- matrix(rows,cols) = p->GetData(rows,cols);
- }
- }
-
- return matrix;
- }
-
- /*
- Write the content of the array into an own csv-data in the following sequence:
- root.csv: 1 2 3 0 0 4
- writen.csv: 1 1:2 2:3 3:0 4:0 5:4
- */
- template<typename T>
- void writeMatrixToCsv(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> paramMatrix,const std::string &path)
- {
- std::ofstream outputstream (path,std::ofstream::out); // 682
-
- if(outputstream.is_open()){
- for(int i = 0; i < paramMatrix.rows(); i++){
- outputstream << paramMatrix(i,0);
- for(int j = 1; j < 11; j++){
- outputstream << " " << j << ":" << paramMatrix(i,j);
- }
- outputstream << endl;
- }
- outputstream.close();
- }
- else{
- cout << "Unable to write into CSV" << endl;
- }
- }
-
- /*
- Train the classifier with an exampledataset of mattlab.
- Note: The included data are gaußan normaldistributed.
- */
- void TrainSVMClassifier_MatlabDataSet_shouldReturnTrue()
- {
- /* Declarating an featurematrixdataset, the first matrix
- of the matrixpair is the trainingmatrix and the second one is the testmatrix.*/
- std::pair<MatrixDoubleType,MatrixDoubleType> matrixDouble;
- matrixDouble = convertCSVToMatrix<double>(GetTestDataFilePath("Classification/FeaturematrixMatlab.csv"),';',0.5,true);
- m_TrainingMatrixX = matrixDouble.first;
- m_TestXPredict = matrixDouble.second;
-
- /* The declaration of the labelmatrixdataset is equivalent to the declaration
- of the featurematrixdataset.*/
- std::pair<MatrixIntType,MatrixIntType> matrixInt;
- matrixInt = convertCSVToMatrix<int>(GetTestDataFilePath("Classification/LabelmatrixMatlab.csv"),';',0.5,false);
- m_TrainingLabelMatrixY = matrixInt.first;
- m_TestYPredict = matrixInt.second;
- classifier = mitk::LibSVMClassifier::New();
-
- /* Setting of the SVM-Parameters*/
- classifier->SetGamma(1/(double)(m_TrainingMatrixX.cols()));
- classifier->SetSvmType(0);
- classifier->SetKernelType(0);
-
- /* Train the classifier, by giving trainingdataset for the labels and features.
- The result in an colunmvector of the labels.*/
- classifier->Train(m_TrainingMatrixX,m_TrainingLabelMatrixY);
- Eigen::MatrixXi classes = classifier->Predict(m_TestXPredict);
-
- /* Testing the matching between the calculated
- colunmvector and the result of the SVM */
- unsigned int maxrows = classes.rows();
-
- int count = 0;
-
- for (unsigned int i = 0; i < maxrows; i++)
- {
- if(classes(i, 0) == m_TestYPredict(i, 0))
- ++count;
- }
-
- MITK_INFO << 100*count/(double)(maxrows) << "%";
- MITK_TEST_CONDITION(isEqual<int>(m_TestYPredict,classes),"Expected vector and occured vector match.");
- }
-
- // Method of testing for assertions.
- template<typename T>
- bool isEqual(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> expected, Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> actual)
- {
- bool isSimilar = true;
- unsigned int mrow = expected.rows();
- unsigned int mcol = expected.cols();
- for(unsigned int i = 0; i < mrow; i++){
- for(unsigned int j = 0; j < mcol; j++){
- if(expected(i,j) != actual(i,j)){
- isSimilar = false;
- }
- }
- }
- return isSimilar;
- }
-
- // Method of intervalltesting
- template<typename T>
- bool isIntervall(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> expected, Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> actual, double lowrange, double toprange)
- {
- bool isInIntervall = false;
- int count = 0;
- unsigned int rowRange = expected.rows();
- unsigned int colRange = expected.cols();
- for(unsigned int i = 0; i < rowRange; i++){
- for(unsigned int j = 0; j < colRange; j++){
- if(expected(i,j) == actual(i,j)){
- count++;
- }
- }
-
- double valueOfMatch = 100*count/(double)(rowRange);
- if((lowrange <= valueOfMatch) && (toprange >= valueOfMatch)){
- isInIntervall = true;
- }
- }
- return isInIntervall;
- }
-
- /*
- Train the classifier with the dataset of breastcancer patients from the
- LibSVM Libary
- */
- void TrainSVMClassifier_BreastCancerDataSet_shouldReturnTrue()
- {
- /* Declarating an featurematrixdataset, the first matrix
- of the matrixpair is the trainingmatrix and the second one is the testmatrix.*/
- std::pair<MatrixDoubleType,MatrixDoubleType> matrixDouble;
- matrixDouble = convertCSVToMatrix<double>(GetTestDataFilePath("Classification/FeaturematrixBreastcancer.csv"),';',0.5,true);
- m_TrainingMatrixX = matrixDouble.first;
- m_TestXPredict = matrixDouble.second;
-
- /* The declaration of the labelmatrixdataset is equivalent to the declaration
- of the featurematrixdataset.*/
- std::pair<MatrixIntType,MatrixIntType> matrixInt;
- matrixInt = convertCSVToMatrix<int>(GetTestDataFilePath("Classification/LabelmatrixBreastcancer.csv"),';',0.5,false);
- m_TrainingLabelMatrixY = matrixInt.first;
- m_TestYPredict = matrixInt.second;
-
- /* Setting of the SVM-Parameters*/
- classifier = mitk::LibSVMClassifier::New();
- classifier->SetGamma(1/(double)(m_TrainingMatrixX.cols()));
- classifier->SetSvmType(0);
- classifier->SetKernelType(2);
-
- /* Train the classifier, by giving trainingdataset for the labels and features.
- The result in an colunmvector of the labels.*/
- classifier->Train(m_TrainingMatrixX,m_TrainingLabelMatrixY);
- Eigen::MatrixXi classes = classifier->Predict(m_TestXPredict);
-
- /* Testing the matching between the calculated colunmvector and the result
- of the SVM */
- unsigned int maxrows = classes.rows();
-
- int count = 0;
-
- for (unsigned int i = 0; i < maxrows; i++)
- {
- if (classes(i, 0) == m_TestYPredict(i, 0))
- ++count;
- }
-
- MITK_INFO << 100*count/(double)(maxrows) << "%";
- MITK_TEST_CONDITION(isIntervall<int>(m_TestYPredict,classes,75,100),"Testvalue is in range.");
- }
-
- void TestThreadedDecisionForest()
- {
- }
-};
-
-MITK_TEST_SUITE_REGISTRATION(mitkLibSVMClassifier)
diff --git a/Modules/Classification/CLMRUtilities/CMakeLists.txt b/Modules/Classification/CLMRUtilities/CMakeLists.txt
index ba273c3c74..6a56a7aedd 100644
--- a/Modules/Classification/CLMRUtilities/CMakeLists.txt
+++ b/Modules/Classification/CLMRUtilities/CMakeLists.txt
@@ -1,6 +1,4 @@
MITK_CREATE_MODULE(
DEPENDS MitkCore MitkCLCore
PACKAGE_DEPENDS PUBLIC Eigen
)
-
-add_subdirectory(test)
diff --git a/Modules/Classification/CLMRUtilities/test/CMakeLists.txt b/Modules/Classification/CLMRUtilities/test/CMakeLists.txt
deleted file mode 100644
index 153cd81e2e..0000000000
--- a/Modules/Classification/CLMRUtilities/test/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-MITK_CREATE_MODULE_TESTS()
diff --git a/Modules/Classification/CLMRUtilities/test/files.cmake b/Modules/Classification/CLMRUtilities/test/files.cmake
deleted file mode 100644
index cafe0f504f..0000000000
--- a/Modules/Classification/CLMRUtilities/test/files.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-set(MODULE_TESTS
- #mitkSmoothedClassProbabilitesTest.cpp
- #mitkGlobalFeaturesTest.cpp
-)
diff --git a/Modules/Classification/CLMRUtilities/test/mitkGlobalFeaturesTest.cpp b/Modules/Classification/CLMRUtilities/test/mitkGlobalFeaturesTest.cpp
deleted file mode 100644
index ecaf746a12..0000000000
--- a/Modules/Classification/CLMRUtilities/test/mitkGlobalFeaturesTest.cpp
+++ /dev/null
@@ -1,312 +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 <mitkTestingMacros.h>
-#include <mitkTestFixture.h>
-#include "mitkIOUtil.h"
-
-#include <mitkImageCast.h>
-#include <mitkGIFFirstOrderStatistics.h>
-#include <mitkGIFCooccurenceMatrix.h>
-#include <mitkGIFGrayLevelRunLength.h>
-#include <math.h>
-
-#include <mitkImageGenerator.h>
-
-template <typename TPixelType>
-static mitk::Image::Pointer GenerateMaskImage(unsigned int dimX,
- unsigned int dimY,
- unsigned int dimZ,
- float spacingX = 1,
- float spacingY = 1,
- float spacingZ = 1)
-{
- typedef itk::Image< TPixelType, 3 > ImageType;
- typename ImageType::RegionType imageRegion;
- imageRegion.SetSize(0, dimX);
- imageRegion.SetSize(1, dimY);
- imageRegion.SetSize(2, dimZ);
- typename ImageType::SpacingType spacing;
- spacing[0] = spacingX;
- spacing[1] = spacingY;
- spacing[2] = spacingZ;
-
- mitk::Point3D origin; origin.Fill(0.0);
- itk::Matrix<double, 3, 3> directionMatrix; directionMatrix.SetIdentity();
-
- typename ImageType::Pointer image = ImageType::New();
- image->SetSpacing( spacing );
- image->SetOrigin( origin );
- image->SetDirection( directionMatrix );
- image->SetLargestPossibleRegion( imageRegion );
- image->SetBufferedRegion( imageRegion );
- image->SetRequestedRegion( imageRegion );
- image->Allocate();
- image->FillBuffer(1);
-
- mitk::Image::Pointer mitkImage = mitk::Image::New();
- mitkImage->InitializeByItk( image.GetPointer() );
- mitkImage->SetVolume( image->GetBufferPointer() );
- return mitkImage;
-}
-
-template <typename TPixelType>
-static mitk::Image::Pointer GenerateGradientWithDimXImage(unsigned int dimX,
- unsigned int dimY,
- unsigned int dimZ,
- float spacingX = 1,
- float spacingY = 1,
- float spacingZ = 1)
-{
- typedef itk::Image< TPixelType, 3 > ImageType;
- typename ImageType::RegionType imageRegion;
- imageRegion.SetSize(0, dimX);
- imageRegion.SetSize(1, dimY);
- imageRegion.SetSize(2, dimZ);
- typename ImageType::SpacingType spacing;
- spacing[0] = spacingX;
- spacing[1] = spacingY;
- spacing[2] = spacingZ;
-
- mitk::Point3D origin; origin.Fill(0.0);
- itk::Matrix<double, 3, 3> directionMatrix; directionMatrix.SetIdentity();
-
- typename ImageType::Pointer image = ImageType::New();
- image->SetSpacing( spacing );
- image->SetOrigin( origin );
- image->SetDirection( directionMatrix );
- image->SetLargestPossibleRegion( imageRegion );
- image->SetBufferedRegion( imageRegion );
- image->SetRequestedRegion( imageRegion );
- image->Allocate();
- image->FillBuffer(0.0);
-
- typedef itk::ImageRegionIterator<ImageType> IteratorOutputType;
- IteratorOutputType it(image, imageRegion);
- it.GoToBegin();
-
- TPixelType val = 0;
- while(!it.IsAtEnd())
- {
- it.Set(val % dimX);
- val++;
- ++it;
- }
-
- mitk::Image::Pointer mitkImage = mitk::Image::New();
- mitkImage->InitializeByItk( image.GetPointer() );
- mitkImage->SetVolume( image->GetBufferPointer() );
- return mitkImage;
-}
-
-class mitkGlobalFeaturesTestSuite : public mitk::TestFixture
-{
- CPPUNIT_TEST_SUITE(mitkGlobalFeaturesTestSuite );
-
- MITK_TEST(FirstOrder_SinglePoint);
- MITK_TEST(FirstOrder_QubicArea);
- //MITK_TEST(RunLenght_QubicArea);
- MITK_TEST(Coocurrence_QubicArea);
- //MITK_TEST(TestFirstOrderStatistic);
- // MITK_TEST(TestThreadedDecisionForest);
-
- CPPUNIT_TEST_SUITE_END();
-
-private:
-
- typedef itk::Image<double,3> ImageType;
- typedef itk::Image<unsigned char,3> MaskType;
-
- mitk::Image::Pointer m_Image,m_Mask,m_Mask1;
- ImageType::Pointer m_ItkImage;
- MaskType::Pointer m_ItkMask,m_ItkMask1;
-
- mitk::Image::Pointer m_GradientImage, m_GradientMask;
-
-public:
-
- void setUp(void)
- {
- // Load Image Data
- m_Image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Pic3D.nrrd"));
- mitk::CastToItkImage(m_Image,m_ItkImage);
-
- // Create a single mask with only one pixel within the regions
- mitk::Image::Pointer mask1 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Pic3D.nrrd"));
- mitk::CastToItkImage(mask1,m_ItkMask);
- m_ItkMask->FillBuffer(0);
- MaskType::IndexType index;
- index[0]=88;index[1]=81;index[2]=13;
- m_ItkMask->SetPixel(index, 1);
- MITK_INFO << "Pixel Value: "<<m_ItkImage->GetPixel(index);
- mitk::CastToMitkImage(m_ItkMask, m_Mask);
-
- // Create a mask with a covered region
- mitk::Image::Pointer lmask1 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Pic3D.nrrd"));
- mitk::CastToItkImage(lmask1,m_ItkMask1);
- m_ItkMask1->FillBuffer(0);
- int range=2;
- for (int x = 88-range;x < 88+range+1;++x)
- {
- for (int y=81-range;y<81+range+1;++y)
- {
- for (int z=13-range;z<13+range+1;++z)
- {
- index[0] = x;
- index[1] = y;
- index[2] = z;
- //MITK_INFO << "Pixel: " <<m_ItkImage->GetPixel(index);
- m_ItkMask1->SetPixel(index, 1);
- }
- }
- }
- mitk::CastToMitkImage(m_ItkMask1, m_Mask1);
-
- m_GradientImage=GenerateGradientWithDimXImage<unsigned char>(5,5,5);
- m_GradientMask = GenerateMaskImage<unsigned char>(5,5,5);
- }
-
- void FirstOrder_SinglePoint()
- {
- mitk::GIFFirstOrderStatistics::Pointer calculator = mitk::GIFFirstOrderStatistics::New();
- calculator->SetHistogramSize(4096);
- calculator->SetUseCtRange(true);
- auto features = calculator->CalculateFeatures(m_Image, m_Mask);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
-
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range of a single pixel should be 0",0.0, results["FirstOrder Range"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",1.0, results["FirstOrder Uniformity"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",0.0, results["FirstOrder Entropy"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",352.0, results["FirstOrder RMS"], 0.01);
- CPPUNIT_ASSERT_EQUAL_MESSAGE("The Kurtosis of a single pixel should be undefined",results["FirstOrder Kurtosis"]==results["FirstOrder Kurtosis"], false);
- CPPUNIT_ASSERT_EQUAL_MESSAGE("The Skewness of a single pixel should be undefined",results["FirstOrder Skewness"]==results["FirstOrder Skewness"], false);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",0, results["FirstOrder Mean absolute deviation"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0, results["FirstOrder Covered Image Intensity Range"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-352, results["FirstOrder Minimum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",-352, results["FirstOrder Maximum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-352, results["FirstOrder Mean"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",0, results["FirstOrder Variance"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-352, results["FirstOrder Sum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-352, results["FirstOrder Median"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",0, results["FirstOrder Standard deviation"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",1, results["FirstOrder No. of Voxel"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",352*352, results["FirstOrder Energy"], 0.0);
- // MITK_ASSERT_EQUAL(results["FirstOrder Range"]==0.0,true,"The range of a single pixel should be 0");
- }
-
- void FirstOrder_QubicArea()
- {
- mitk::GIFFirstOrderStatistics::Pointer calculator = mitk::GIFFirstOrderStatistics::New();
- calculator->SetHistogramSize(4096);
- calculator->SetUseCtRange(true);
- auto features = calculator->CalculateFeatures(m_Image, m_Mask1);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
-
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range should be 981",981, results["FirstOrder Range"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",402.895778, results["FirstOrder RMS"], 0.01);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-937, results["FirstOrder Minimum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",44, results["FirstOrder Maximum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-304.448, results["FirstOrder Mean"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-38056, results["FirstOrder Sum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-202, results["FirstOrder Median"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",125, results["FirstOrder No. of Voxel"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",264.949066, results["FirstOrder Standard deviation"], 0.000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",20290626, results["FirstOrder Energy"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",0.0088960, results["FirstOrder Uniformity"], 0.0000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",-6.853784285, results["FirstOrder Entropy"], 0.000000005);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",70198.0074, results["FirstOrder Variance"], 0.0001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Kurtosis of a single pixel should be 0",2.63480121, results["FirstOrder Kurtosis"], 0.0001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Skewness of a single pixel should be 0",-0.91817318, results["FirstOrder Skewness"], 0.00001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",219.348608, results["FirstOrder Mean absolute deviation"], 0.000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0.41149329, results["FirstOrder Covered Image Intensity Range"], 0.000001);
- }
-
- void RunLenght_QubicArea()
- {
- mitk::GIFGrayLevelRunLength::Pointer calculator = mitk::GIFGrayLevelRunLength::New();
- //calculator->SetHistogramSize(4096);
- calculator->SetUseCtRange(true);
- calculator->SetRange(981);
- auto features = calculator->CalculateFeatures(m_Image, m_Mask1);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
- }
-
- void Coocurrence_QubicArea()
- {
- /*
- * Expected Matrix: (Direction 0,0,1)
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 0 | 20 | 0 | 0 | 0 |
- * |------------------------|
- * | 0 | 0 | 20 | 0 | 0 |
- * |------------------------|
- * | 0 | 0 | 0 | 20 | 0 |
- * |------------------------|
- * | 0 | 0 | 0 | 0 | 20 |
- * |------------------------|
-
- * Expected Matrix: (Direction (1,0,0),(0,1,0))
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- */
-
- mitk::GIFCooccurenceMatrix::Pointer calculator = mitk::GIFCooccurenceMatrix::New();
- //calculator->SetHistogramSize(4096);
- //calculator->SetUseCtRange(true);
- //calculator->SetRange(981);
- auto features = calculator->CalculateFeatures(m_GradientImage, m_GradientMask);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean energy value should be 0.2",0.2, results["co-occ. (1) Energy Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean entropy value should be 0.2",2.321928, results["co-occ. (1) Entropy Means"], 0.000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean contrast value should be 0.0",0, results["co-occ. (1) Contrast Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean dissimilarity value should be 0.0",0, results["co-occ. (1) Dissimilarity Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean homogenity1 value should be 1.0",1, results["co-occ. (1) Homogeneity1 Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean InverseDifferenceMoment value should be 1.0",1, results["co-occ. (1) InverseDifferenceMoment Means"], mitk::eps);
- }
-};
-
-MITK_TEST_SUITE_REGISTRATION(mitkGlobalFeatures)
diff --git a/Modules/Classification/CLMRUtilities/test/mitkSmoothedClassProbabilitesTest.cpp b/Modules/Classification/CLMRUtilities/test/mitkSmoothedClassProbabilitesTest.cpp
deleted file mode 100644
index a7b7e977fd..0000000000
--- a/Modules/Classification/CLMRUtilities/test/mitkSmoothedClassProbabilitesTest.cpp
+++ /dev/null
@@ -1,90 +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 <mitkTestingMacros.h>
-#include <mitkTestFixture.h>
-#include "mitkIOUtil.h"
-
-#include <itkSmoothedClassProbabilites.h>
-#include <mitkImageCast.h>
-
-class mitkSmoothedClassProbabilitesTestSuite : public mitk::TestFixture
-{
-
- CPPUNIT_TEST_SUITE(mitkSmoothedClassProbabilitesTestSuite );
-
- MITK_TEST(TrainSVMClassifier);
- // MITK_TEST(TestThreadedDecisionForest);
-
- CPPUNIT_TEST_SUITE_END();
-
-private:
-
- typedef itk::Image<double,3> ImageType;
- mitk::Image::Pointer p1,p2,p3,pmask;
- ImageType::Pointer i1,i2,i3,imask;
-
-public:
-
-
- void setUp(void)
- {
-
- // Load Image Data
- p1 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/ResultProb_Class-0_0.nrrd"));
- p2 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/ResultProb_Class-1_0.nrrd"));
- p3 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/ResultProb_Class-2_0.nrrd"));
- pmask = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/mask.nrrd"));
-
- mitk::CastToItkImage(p1,i1);
- mitk::CastToItkImage(p2,i2);
- mitk::CastToItkImage(p3,i3);
- mitk::CastToItkImage(pmask,imask);
- }
-
- void TrainSVMClassifier()
- {
- itk::SmoothedClassProbabilites<ImageType>::Pointer filter = itk::SmoothedClassProbabilites<ImageType>::New();
- filter->SetInput(0,i1);
- filter->SetInput(1,i2);
- filter->SetInput(2,i3);
- filter->SetMaskImage(imask);
- filter->SetSigma(1.0);
- filter->Update();
-
- mitk::Image::Pointer out;
- mitk::CastToMitkImage(filter->GetOutput(), out);
-
- mitk::IOUtil::Save(out, "/Users/jc/test.nrrd");
- }
-
- void TestThreadedDecisionForest()
- {
- // m_LoadedDecisionForest->SetCollection(m_TrainDatacollection);
- // m_LoadedDecisionForest->SetModalities(m_Selected_items);
- // m_LoadedDecisionForest->SetMaskName("ClassMask");
- // m_LoadedDecisionForest->SetResultMask("ResultMask");
- // m_LoadedDecisionForest->SetResultProb("ResultProb");
- // m_LoadedDecisionForest->TestThreaded();
-
- // mitk::DataCollection::Pointer res_col = dynamic_cast<mitk::DataCollection *>(dynamic_cast<mitk::DataCollection *>(m_TrainDatacollection->GetData("Test-Study").GetPointer())->GetData("Test-Subject").GetPointer());
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultMask"),"/Users/jc/res_mask.nrrd");
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultProb_Class-0"),"/Users/jc/res_prob_0.nrrd");
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultProb_Class-1"),"/Users/jc/res_prob_1.nrrd");
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultProb_Class-2"),"/Users/jc/res_prob_2.nrrd");
- }
-
-};
-
-MITK_TEST_SUITE_REGISTRATION(mitkSmoothedClassProbabilites)
-
-
diff --git a/Modules/Classification/CLMiniApps/CL2Dto3DImage.cpp b/Modules/Classification/CLMiniApps/CL2Dto3DImage.cpp
deleted file mode 100644
index 825465dc24..0000000000
--- a/Modules/Classification/CLMiniApps/CL2Dto3DImage.cpp
+++ /dev/null
@@ -1,55 +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 "mitkCommandLineParser.h"
-#include <mitkConvert2Dto3DImageFilter.h>
-#include "mitkIOUtil.h"
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
-
- parser.setTitle("Dicom Loader");
- parser.setCategory("Preprocessing Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--","-");
- // Add command line argument names
- parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("input", "i", mitkCommandLineParser::Directory, "Input file:", "Input file",us::Any(),false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file:", "Output file",us::Any(),false, false, false, mitkCommandLineParser::Output);
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- // Show a help message
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- std::string inputName = us::any_cast<std::string>(parsedArgs["input"]);
- std::string outputName = us::any_cast<std::string>(parsedArgs["output"]);
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(inputName);
- mitk::Convert2Dto3DImageFilter::Pointer multiFilter2 = mitk::Convert2Dto3DImageFilter::New();
- multiFilter2->SetInput(image);
- multiFilter2->Update();
- mitk::Image::Pointer image2 = multiFilter2->GetOutput();
- mitk::IOUtil::Save(image2, outputName);
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLBrainMask.cpp b/Modules/Classification/CLMiniApps/CLBrainMask.cpp
deleted file mode 100644
index 933f276bb5..0000000000
--- a/Modules/Classification/CLMiniApps/CLBrainMask.cpp
+++ /dev/null
@@ -1,100 +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.
-
-============================================================================*/
-#ifndef mitkCLPolyToNrrd_cpp
-#define mitkCLPolyToNrrd_cpp
-
-#include "time.h"
-#include <sstream>
-#include <fstream>
-
-#include <mitkIOUtil.h>
-#include "mitkCommandLineParser.h"
-
-#include "itkImageRegionIterator.h"
-// MITK
-#include <mitkITKImageImport.h>
-#include <mitkImageCast.h>
-#include <mitkImageAccessByItk.h>
-// ITK
-#include <itkLabelStatisticsImageFilter.h>
-#include <itkMinimumMaximumImageCalculator.h>
-
-typedef itk::Image< double, 3 > FloatImageType;
-typedef itk::Image< unsigned char, 3 > MaskImageType;
-
-template<typename TPixel, unsigned int VImageDimension>
-void
- Normalize(itk::Image<TPixel, VImageDimension>* itkImage, mitk::Image::Pointer im2, mitk::Image::Pointer mask1, std::string output)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::Image<unsigned char, VImageDimension> MaskType;
-
- typename ImageType::Pointer itkIm2 = ImageType::New();
- typename MaskType::Pointer itkMask1 = MaskType::New();
- mitk::CastToItkImage(im2, itkIm2);
- mitk::CastToItkImage(mask1, itkMask1);
-
- itk::ImageRegionIterator<ImageType> iterI1(itkImage, itkImage->GetLargestPossibleRegion());
- itk::ImageRegionIterator<ImageType> iterI2(itkIm2, itkImage->GetLargestPossibleRegion());
- itk::ImageRegionIterator<MaskType> iter(itkMask1, itkImage->GetLargestPossibleRegion());
- while (! iter.IsAtEnd())
- {
- unsigned char maskV = 0;
- if (iterI1.Value() > 0.0001 && iterI2.Value() > 0.00001)
- maskV = 1;
- iter.Set(maskV);
- ++iter;
- ++iterI1;
- ++iterI2;
- }
-
- mitk::Image::Pointer img = mitk::ImportItkImage(itkMask1);
- mitk::IOUtil::Save(img, output);
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("image", "i", mitkCommandLineParser::Image, "Input Image", "Path to the input VTK polydata", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("image2", "i2", mitkCommandLineParser::Image, "Input Mask", "The median of the area covered by this mask will be set to 0", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("mask", "m", mitkCommandLineParser::Image, "Input Mask", "The median of the area covered by this mask will be set to 1", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output Image", "Target file. The output statistic is appended to this file.", us::Any(), false, false, false, mitkCommandLineParser::Output);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("MR Normalization Tool");
- parser.setDescription("Normalizes a MR image. Sets the Median of the tissue covered by mask 0 to 0 and the median of the area covered by mask 1 to 1.");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(parsedArgs["image"].ToString());
- mitk::Image::Pointer im2= mitk::IOUtil::Load<mitk::Image>(parsedArgs["image2"].ToString());
- mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(parsedArgs["mask"].ToString());
-
- AccessByItk_3(image, Normalize, im2, mask, parsedArgs["output"].ToString());
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLDicom2Nrrd.cpp b/Modules/Classification/CLMiniApps/CLDicom2Nrrd.cpp
deleted file mode 100644
index 1c2c2b82a7..0000000000
--- a/Modules/Classification/CLMiniApps/CLDicom2Nrrd.cpp
+++ /dev/null
@@ -1,84 +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 "mitkProperties.h"
-
-#include "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-
-#include <itksys/SystemTools.hxx>
-
-#include "mitkPreferenceListReaderOptionsFunctor.h"
-
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
-
- parser.setTitle("Dicom Loader");
- parser.setCategory("Preprocessing Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--","-");
- // Add command line argument names
- parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("input", "i", mitkCommandLineParser::Directory, "Input folder:", "Input folder",us::Any(),false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file:", "Output file", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("reader", "r", mitkCommandLineParser::String, "Reader Name", "Reader Name", us::Any());
-
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- // Show a help message
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- std::string inputFolder = us::any_cast<std::string>(parsedArgs["input"]);
- std::string outFileName = us::any_cast<std::string>(parsedArgs["output"]);
-
- mitk::PreferenceListReaderOptionsFunctor::ListType preference = {};
- if (parsedArgs.count("reader"))
- {
- preference.push_back(us::any_cast<std::string>(parsedArgs["reader"]));
- }
- mitk::PreferenceListReaderOptionsFunctor::ListType emptyList = {};
- mitk::IOUtil::LoadInfo info(inputFolder);
- mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor(preference, emptyList);
- functor(info);
-
- std::string extension = itksys::SystemTools::GetFilenameExtension(outFileName);
- std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(outFileName);
- std::string path = itksys::SystemTools::GetFilenamePath(outFileName);
-
- auto nodes = mitk::IOUtil::Load(inputFolder, &functor);
-
- unsigned count = 0;
- for (auto node : nodes)
- {
- std::string writeName = path + "/" + filename + extension;
- if (count > 0)
- {
- writeName = path + "/" + filename + "_" + std::to_string(count) + extension;
- }
- mitk::IOUtil::Save(node, writeName);
- ++count;
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp b/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp
index 80ba5e8016..4ff557a00d 100644
--- a/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp
+++ b/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp
@@ -1,786 +1,786 @@
/*============================================================================
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 mitkCLPolyToNrrd_cpp
#define mitkCLPolyToNrrd_cpp
#include "time.h"
#include <sstream>
#include <fstream>
#include <mitkIOUtil.h>
#include "mitkCommandLineParser.h"
#include <mitkSplitParameterToVector.h>
#include <mitkGlobalImageFeaturesParameter.h>
#include <mitkGIFCooccurenceMatrix.h>
#include <mitkGIFCooccurenceMatrix2.h>
#include <mitkGIFGreyLevelRunLength.h>
#include <mitkGIFFirstOrderStatistics.h>
#include <mitkGIFFirstOrderHistogramStatistics.h>
#include <mitkGIFFirstOrderNumericStatistics.h>
#include <mitkGIFVolumetricStatistics.h>
#include <mitkGIFVolumetricDensityStatistics.h>
#include <mitkGIFGreyLevelSizeZone.h>
#include <mitkGIFGreyLevelDistanceZone.h>
#include <mitkGIFImageDescriptionFeatures.h>
#include <mitkGIFLocalIntensity.h>
#include <mitkGIFCurvatureStatistic.h>
#include <mitkGIFIntensityVolumeHistogramFeatures.h>
#include <mitkGIFNeighbourhoodGreyToneDifferenceFeatures.h>
#include <mitkGIFNeighbouringGreyLevelDependenceFeatures.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
#include <mitkConvert2Dto3DImageFilter.h>
#include <mitkCLResultWriter.h>
#include <mitkCLResultXMLWriter.h>
#include <mitkVersion.h>
#include <iostream>
#include <locale>
#include <itkImageDuplicator.h>
#include <itkImageRegionIterator.h>
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "itkResampleImageFilter.h"
#include <QApplication>
#include <mitkStandaloneDataStorage.h>
#include "QmitkRegisterClasses.h"
#include "QmitkRenderWindow.h"
#include "vtkRenderLargeImage.h"
#include "vtkPNGWriter.h"
typedef itk::Image< double, 3 > FloatImageType;
typedef itk::Image< unsigned short, 3 > MaskImageType;
template <class charT>
class punct_facet : public std::numpunct<charT> {
public:
punct_facet(charT sep) :
m_Sep(sep)
{
}
protected:
charT do_decimal_point() const override { return m_Sep; }
private:
charT m_Sep;
};
template<typename TPixel, unsigned int VImageDimension>
void
ResampleImage(itk::Image<TPixel, VImageDimension>* itkImage, float resolution, mitk::Image::Pointer& newImage)
{
typedef itk::Image<TPixel, VImageDimension> ImageType;
typedef itk::ResampleImageFilter<ImageType, ImageType> ResampleFilterType;
typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
auto spacing = itkImage->GetSpacing();
auto size = itkImage->GetLargestPossibleRegion().GetSize();
for (unsigned int i = 0; i < VImageDimension; ++i)
{
size[i] = size[i] / (1.0*resolution)*(1.0*spacing[i])+1.0;
}
spacing.Fill(resolution);
resampler->SetInput(itkImage);
resampler->SetSize(size);
resampler->SetOutputSpacing(spacing);
resampler->SetOutputOrigin(itkImage->GetOrigin());
resampler->SetOutputDirection(itkImage->GetDirection());
resampler->Update();
newImage->InitializeByItk(resampler->GetOutput());
mitk::GrabItkImageMemory(resampler->GetOutput(), newImage);
}
template<typename TPixel, unsigned int VImageDimension>
static void
CreateNoNaNMask(itk::Image<TPixel, VImageDimension>* itkValue, mitk::Image::Pointer mask, mitk::Image::Pointer& newMask)
{
typedef itk::Image< TPixel, VImageDimension> LFloatImageType;
typedef itk::Image< unsigned short, VImageDimension> LMaskImageType;
typename LMaskImageType::Pointer itkMask = LMaskImageType::New();
mitk::CastToItkImage(mask, itkMask);
typedef itk::ImageDuplicator< LMaskImageType > DuplicatorType;
typename DuplicatorType::Pointer duplicator = DuplicatorType::New();
duplicator->SetInputImage(itkMask);
duplicator->Update();
auto tmpMask = duplicator->GetOutput();
itk::ImageRegionIterator<LMaskImageType> mask1Iter(itkMask, itkMask->GetLargestPossibleRegion());
itk::ImageRegionIterator<LMaskImageType> mask2Iter(tmpMask, tmpMask->GetLargestPossibleRegion());
itk::ImageRegionIterator<LFloatImageType> imageIter(itkValue, itkValue->GetLargestPossibleRegion());
while (!mask1Iter.IsAtEnd())
{
mask2Iter.Set(0);
if (mask1Iter.Value() > 0)
{
// Is not NaN
if (imageIter.Value() == imageIter.Value())
{
mask2Iter.Set(1);
}
}
++mask1Iter;
++mask2Iter;
++imageIter;
}
newMask->InitializeByItk(tmpMask);
mitk::GrabItkImageMemory(tmpMask, newMask);
}
template<typename TPixel, unsigned int VImageDimension>
static void
ResampleMask(itk::Image<TPixel, VImageDimension>* itkMoving, mitk::Image::Pointer ref, mitk::Image::Pointer& newMask)
{
typedef itk::Image< TPixel, VImageDimension> LMaskImageType;
typedef itk::NearestNeighborInterpolateImageFunction< LMaskImageType> NearestNeighborInterpolateImageFunctionType;
typedef itk::ResampleImageFilter<LMaskImageType, LMaskImageType> ResampleFilterType;
typename NearestNeighborInterpolateImageFunctionType::Pointer nn_interpolator = NearestNeighborInterpolateImageFunctionType::New();
typename LMaskImageType::Pointer itkRef = LMaskImageType::New();
mitk::CastToItkImage(ref, itkRef);
typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetInput(itkMoving);
resampler->SetReferenceImage(itkRef);
resampler->UseReferenceImageOn();
resampler->SetInterpolator(nn_interpolator);
resampler->Update();
newMask->InitializeByItk(resampler->GetOutput());
mitk::GrabItkImageMemory(resampler->GetOutput(), newMask);
}
static void
ExtractSlicesFromImages(mitk::Image::Pointer image, mitk::Image::Pointer mask,
mitk::Image::Pointer maskNoNaN, mitk::Image::Pointer morphMask,
int direction,
std::vector<mitk::Image::Pointer> &imageVector,
std::vector<mitk::Image::Pointer> &maskVector,
std::vector<mitk::Image::Pointer> &maskNoNaNVector,
std::vector<mitk::Image::Pointer> &morphMaskVector)
{
typedef itk::Image< double, 2 > FloatImage2DType;
typedef itk::Image< unsigned short, 2 > MaskImage2DType;
FloatImageType::Pointer itkFloat = FloatImageType::New();
MaskImageType::Pointer itkMask = MaskImageType::New();
MaskImageType::Pointer itkMaskNoNaN = MaskImageType::New();
MaskImageType::Pointer itkMorphMask = MaskImageType::New();
mitk::CastToItkImage(mask, itkMask);
mitk::CastToItkImage(maskNoNaN, itkMaskNoNaN);
mitk::CastToItkImage(image, itkFloat);
mitk::CastToItkImage(morphMask, itkMorphMask);
int idxA, idxB, idxC;
switch (direction)
{
case 0:
idxA = 1; idxB = 2; idxC = 0;
break;
case 1:
idxA = 0; idxB = 2; idxC = 1;
break;
case 2:
idxA = 0; idxB = 1; idxC = 2;
break;
default:
idxA = 1; idxB = 2; idxC = 0;
break;
}
auto imageSize = image->GetLargestPossibleRegion().GetSize();
FloatImageType::IndexType index3D;
FloatImage2DType::IndexType index2D;
FloatImage2DType::SpacingType spacing2D;
spacing2D[0] = itkFloat->GetSpacing()[idxA];
spacing2D[1] = itkFloat->GetSpacing()[idxB];
for (unsigned int i = 0; i < imageSize[idxC]; ++i)
{
FloatImage2DType::RegionType region;
FloatImage2DType::IndexType start;
FloatImage2DType::SizeType size;
start[0] = 0; start[1] = 0;
size[0] = imageSize[idxA];
size[1] = imageSize[idxB];
region.SetIndex(start);
region.SetSize(size);
FloatImage2DType::Pointer image2D = FloatImage2DType::New();
image2D->SetRegions(region);
image2D->Allocate();
MaskImage2DType::Pointer mask2D = MaskImage2DType::New();
mask2D->SetRegions(region);
mask2D->Allocate();
MaskImage2DType::Pointer masnNoNaN2D = MaskImage2DType::New();
masnNoNaN2D->SetRegions(region);
masnNoNaN2D->Allocate();
MaskImage2DType::Pointer morph2D = MaskImage2DType::New();
morph2D->SetRegions(region);
morph2D->Allocate();
unsigned long voxelsInMask = 0;
for (unsigned int a = 0; a < imageSize[idxA]; ++a)
{
for (unsigned int b = 0; b < imageSize[idxB]; ++b)
{
index3D[idxA] = a;
index3D[idxB] = b;
index3D[idxC] = i;
index2D[0] = a;
index2D[1] = b;
image2D->SetPixel(index2D, itkFloat->GetPixel(index3D));
mask2D->SetPixel(index2D, itkMask->GetPixel(index3D));
masnNoNaN2D->SetPixel(index2D, itkMaskNoNaN->GetPixel(index3D));
morph2D->SetPixel(index2D, itkMorphMask->GetPixel(index3D));
voxelsInMask += (itkMask->GetPixel(index3D) > 0) ? 1 : 0;
}
}
image2D->SetSpacing(spacing2D);
mask2D->SetSpacing(spacing2D);
masnNoNaN2D->SetSpacing(spacing2D);
morph2D->SetSpacing(spacing2D);
mitk::Image::Pointer tmpFloatImage = mitk::Image::New();
tmpFloatImage->InitializeByItk(image2D.GetPointer());
mitk::GrabItkImageMemory(image2D, tmpFloatImage);
mitk::Image::Pointer tmpMaskImage = mitk::Image::New();
tmpMaskImage->InitializeByItk(mask2D.GetPointer());
mitk::GrabItkImageMemory(mask2D, tmpMaskImage);
mitk::Image::Pointer tmpMaskNoNaNImage = mitk::Image::New();
tmpMaskNoNaNImage->InitializeByItk(masnNoNaN2D.GetPointer());
mitk::GrabItkImageMemory(masnNoNaN2D, tmpMaskNoNaNImage);
mitk::Image::Pointer tmpMorphMaskImage = mitk::Image::New();
tmpMorphMaskImage->InitializeByItk(morph2D.GetPointer());
mitk::GrabItkImageMemory(morph2D, tmpMorphMaskImage);
if (voxelsInMask > 0)
{
imageVector.push_back(tmpFloatImage);
maskVector.push_back(tmpMaskImage);
maskNoNaNVector.push_back(tmpMaskNoNaNImage);
morphMaskVector.push_back(tmpMorphMaskImage);
}
}
}
static
void SaveSliceOrImageAsPNG(mitk::Image::Pointer image, mitk::Image::Pointer mask, std::string path, int index)
{
// Create a Standalone Datastorage for the single purpose of saving screenshots..
mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New();
QmitkRenderWindow renderWindow;
renderWindow.GetRenderer()->SetDataStorage(ds);
auto nodeI = mitk::DataNode::New();
nodeI->SetData(image);
auto nodeM = mitk::DataNode::New();
nodeM->SetData(mask);
ds->Add(nodeI);
ds->Add(nodeM);
auto geo = ds->ComputeBoundingGeometry3D(ds->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(geo);
mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController();
unsigned int numberOfSteps = 1;
if (sliceNaviController)
{
- numberOfSteps = sliceNaviController->GetSlice()->GetSteps();
- sliceNaviController->GetSlice()->SetPos(0);
+ numberOfSteps = sliceNaviController->GetStepper()->GetSteps();
+ sliceNaviController->GetStepper()->SetPos(0);
}
renderWindow.show();
renderWindow.resize(256, 256);
for (unsigned int currentStep = 0; currentStep < numberOfSteps; ++currentStep)
{
if (sliceNaviController)
{
- sliceNaviController->GetSlice()->SetPos(currentStep);
+ sliceNaviController->GetStepper()->SetPos(currentStep);
}
renderWindow.GetRenderer()->PrepareRender();
vtkRenderWindow* renderWindow2 = renderWindow.GetVtkRenderWindow();
mitk::BaseRenderer* baserenderer = mitk::BaseRenderer::GetInstance(renderWindow2);
auto vtkRender = baserenderer->GetVtkRenderer();
vtkRender->GetRenderWindow()->WaitForCompletion();
vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New();
magnifier->SetInput(vtkRender);
magnifier->SetMagnification(3.0);
std::stringstream ss;
ss << path << "_Idx-" << index << "_Step-"<<currentStep<<".png";
std::string tmpImageName;
ss >> tmpImageName;
auto fileWriter = vtkPNGWriter::New();
fileWriter->SetInputConnection(magnifier->GetOutputPort());
fileWriter->SetFileName(tmpImageName.c_str());
fileWriter->Write();
fileWriter->Delete();
}
}
int main(int argc, char* argv[])
{
// Commented : Updated to a common interface, include, if possible, mask is type unsigned short, uses Quantification, Comments
// Name follows standard scheme with Class Name::Feature Name
// Commented 2: Updated to use automatic inclusion of list of parameters if required.
mitk::GIFImageDescriptionFeatures::Pointer ipCalculator = mitk::GIFImageDescriptionFeatures::New(); // Commented 2, Tested
mitk::GIFFirstOrderStatistics::Pointer firstOrderCalculator = mitk::GIFFirstOrderStatistics::New(); //Commented 2
mitk::GIFFirstOrderHistogramStatistics::Pointer firstOrderHistoCalculator = mitk::GIFFirstOrderHistogramStatistics::New(); // Commented 2, Tested
mitk::GIFFirstOrderNumericStatistics::Pointer firstOrderNumericCalculator = mitk::GIFFirstOrderNumericStatistics::New(); // Commented 2, Tested
mitk::GIFVolumetricStatistics::Pointer volCalculator = mitk::GIFVolumetricStatistics::New(); // Commented 2, Tested
mitk::GIFVolumetricDensityStatistics::Pointer voldenCalculator = mitk::GIFVolumetricDensityStatistics::New(); // Commented 2, Tested
mitk::GIFCooccurenceMatrix::Pointer coocCalculator = mitk::GIFCooccurenceMatrix::New(); // Commented 2, Will not be tested
mitk::GIFCooccurenceMatrix2::Pointer cooc2Calculator = mitk::GIFCooccurenceMatrix2::New(); //Commented 2
mitk::GIFNeighbouringGreyLevelDependenceFeature::Pointer ngldCalculator = mitk::GIFNeighbouringGreyLevelDependenceFeature::New(); //Commented 2, Tested
mitk::GIFGreyLevelRunLength::Pointer rlCalculator = mitk::GIFGreyLevelRunLength::New(); // Commented 2
mitk::GIFGreyLevelSizeZone::Pointer glszCalculator = mitk::GIFGreyLevelSizeZone::New(); // Commented 2, Tested
mitk::GIFGreyLevelDistanceZone::Pointer gldzCalculator = mitk::GIFGreyLevelDistanceZone::New(); //Commented 2, Tested
mitk::GIFLocalIntensity::Pointer lociCalculator = mitk::GIFLocalIntensity::New(); //Commented 2, Tested
mitk::GIFIntensityVolumeHistogramFeatures::Pointer ivohCalculator = mitk::GIFIntensityVolumeHistogramFeatures::New(); // Commented 2
mitk::GIFNeighbourhoodGreyToneDifferenceFeatures::Pointer ngtdCalculator = mitk::GIFNeighbourhoodGreyToneDifferenceFeatures::New(); //Commented 2, Tested
mitk::GIFCurvatureStatistic::Pointer curvCalculator = mitk::GIFCurvatureStatistic::New(); //Commented 2, Tested
std::vector<mitk::AbstractGlobalImageFeature::Pointer> features;
features.push_back(volCalculator.GetPointer());
features.push_back(voldenCalculator.GetPointer());
features.push_back(curvCalculator.GetPointer());
features.push_back(firstOrderCalculator.GetPointer());
features.push_back(firstOrderNumericCalculator.GetPointer());
features.push_back(firstOrderHistoCalculator.GetPointer());
features.push_back(ivohCalculator.GetPointer());
features.push_back(lociCalculator.GetPointer());
features.push_back(coocCalculator.GetPointer());
features.push_back(cooc2Calculator.GetPointer());
features.push_back(ngldCalculator.GetPointer());
features.push_back(rlCalculator.GetPointer());
features.push_back(glszCalculator.GetPointer());
features.push_back(gldzCalculator.GetPointer());
features.push_back(ipCalculator.GetPointer());
features.push_back(ngtdCalculator.GetPointer());
mitkCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
mitk::cl::GlobalImageFeaturesParameter param;
param.AddParameter(parser);
parser.addArgument("--","-", mitkCommandLineParser::String, "---", "---", us::Any(),true);
for (auto cFeature : features)
{
cFeature->AddArguments(parser);
}
parser.addArgument("--", "-", mitkCommandLineParser::String, "---", "---", us::Any(), true);
parser.addArgument("description","d",mitkCommandLineParser::String,"Text","Description that is added to the output",us::Any());
parser.addArgument("direction", "dir", mitkCommandLineParser::String, "Int", "Allows to specify the direction for Cooc and RL. 0: All directions, 1: Only single direction (Test purpose), 2,3,4... Without dimension 0,1,2... ", us::Any());
parser.addArgument("slice-wise", "slice", mitkCommandLineParser::String, "Int", "Allows to specify if the image is processed slice-wise (number giving direction) ", us::Any());
parser.addArgument("output-mode", "omode", mitkCommandLineParser::Int, "Int", "Defines the format of the output. 0: (Default) results of an image / slice are written in a single row;"
" 1: results of an image / slice are written in a single column; 2: store the result of on image as structured radiomocs report (XML).");
// Miniapp Infos
parser.setCategory("Classification Tools");
parser.setTitle("Global Image Feature calculator");
parser.setDescription("Calculates different global statistics for a given segmentation / image combination");
parser.setContributor("German Cancer Research Center (DKFZ)");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
param.ParseParameter(parsedArgs);
if (parsedArgs.size()==0)
{
return EXIT_FAILURE;
}
if ( parsedArgs.count("help") || parsedArgs.count("h"))
{
return EXIT_SUCCESS;
}
std::string version = "Version: 1.23";
MITK_INFO << version;
std::ofstream log;
if (param.useLogfile)
{
log.open(param.logfilePath, std::ios::app);
log << std::endl;
log << version;
log << "Image: " << param.imagePath;
log << "Mask: " << param.maskPath;
}
if (param.useDecimalPoint)
{
std::cout.imbue(std::locale(std::cout.getloc(), new punct_facet<char>(param.decimalPoint)));
}
//representing the original loaded image data without any prepropcessing that might come.
mitk::Image::Pointer loadedImage = mitk::IOUtil::Load<mitk::Image>(param.imagePath);
//representing the original loaded mask data without any prepropcessing that might come.
mitk::Image::Pointer loadedMask = mitk::IOUtil::Load<mitk::Image>(param.maskPath);
mitk::Image::Pointer image = loadedImage;
mitk::Image::Pointer mask = loadedMask;
mitk::Image::Pointer tmpImage = loadedImage;
mitk::Image::Pointer tmpMask = loadedMask;
mitk::Image::Pointer morphMask = mask;
if (param.useMorphMask)
{
morphMask = mitk::IOUtil::Load<mitk::Image>(param.morphPath);
}
log << " Check for Dimensions -";
if ((image->GetDimension() != mask->GetDimension()))
{
MITK_INFO << "Dimension of image does not match. ";
MITK_INFO << "Correct one image, may affect the result";
if (image->GetDimension() == 2)
{
mitk::Convert2Dto3DImageFilter::Pointer multiFilter2 = mitk::Convert2Dto3DImageFilter::New();
multiFilter2->SetInput(tmpImage);
multiFilter2->Update();
image = multiFilter2->GetOutput();
}
if (mask->GetDimension() == 2)
{
mitk::Convert2Dto3DImageFilter::Pointer multiFilter3 = mitk::Convert2Dto3DImageFilter::New();
multiFilter3->SetInput(tmpMask);
multiFilter3->Update();
mask = multiFilter3->GetOutput();
}
}
int writeDirection = 0;
if (parsedArgs.count("output-mode"))
{
writeDirection = us::any_cast<int>(parsedArgs["output-mode"]);
}
log << " Check for Resolution -";
if (param.resampleToFixIsotropic)
{
mitk::Image::Pointer newImage = mitk::Image::New();
AccessByItk_2(image, ResampleImage, param.resampleResolution, newImage);
image = newImage;
}
log << " Resample if required -";
if (param.resampleMask)
{
mitk::Image::Pointer newMaskImage = mitk::Image::New();
AccessByItk_2(mask, ResampleMask, image, newMaskImage);
mask = newMaskImage;
}
if ( ! mitk::Equal(mask->GetGeometry(0)->GetOrigin(), image->GetGeometry(0)->GetOrigin()))
{
MITK_INFO << "Not equal Origins";
if (param.ensureSameSpace)
{
MITK_INFO << "Warning!";
MITK_INFO << "The origin of the input image and the mask do not match. They are";
MITK_INFO << "now corrected. Please check to make sure that the images still match";
image->GetGeometry(0)->SetOrigin(mask->GetGeometry(0)->GetOrigin());
} else
{
return -1;
}
}
log << " Check for Equality -";
if ( ! mitk::Equal(mask->GetGeometry(0)->GetSpacing(), image->GetGeometry(0)->GetSpacing()))
{
MITK_INFO << "Not equal Spacing";
if (param.ensureSameSpace)
{
MITK_INFO << "Warning!";
MITK_INFO << "The spacing of the mask was set to match the spacing of the input image.";
MITK_INFO << "This might cause unintended spacing of the mask image";
image->GetGeometry(0)->SetSpacing(mask->GetGeometry(0)->GetSpacing());
} else
{
MITK_INFO << "The spacing of the mask and the input images is not equal.";
MITK_INFO << "Terminating the programm. You may use the '-fi' option";
return -1;
}
}
int direction = 0;
if (parsedArgs.count("direction"))
{
direction = mitk::cl::splitDouble(parsedArgs["direction"].ToString(), ';')[0];
}
MITK_INFO << "Start creating Mask without NaN";
mitk::Image::Pointer maskNoNaN = mitk::Image::New();
AccessByItk_2(image, CreateNoNaNMask, mask, maskNoNaN);
//CreateNoNaNMask(mask, image, maskNoNaN);
bool sliceWise = false;
int sliceDirection = 0;
unsigned int currentSlice = 0;
bool imageToProcess = true;
std::vector<mitk::Image::Pointer> floatVector;
std::vector<mitk::Image::Pointer> maskVector;
std::vector<mitk::Image::Pointer> maskNoNaNVector;
std::vector<mitk::Image::Pointer> morphMaskVector;
if ((parsedArgs.count("slice-wise")) && image->GetDimension() > 2)
{
MITK_INFO << "Enabled slice-wise";
sliceWise = true;
sliceDirection = mitk::cl::splitDouble(parsedArgs["slice-wise"].ToString(), ';')[0];
MITK_INFO << sliceDirection;
ExtractSlicesFromImages(image, mask, maskNoNaN, morphMask, sliceDirection, floatVector, maskVector, maskNoNaNVector, morphMaskVector);
MITK_INFO << "Slice";
}
log << " Configure features -";
for (auto cFeature : features)
{
if (param.defineGlobalMinimumIntensity)
{
cFeature->SetMinimumIntensity(param.globalMinimumIntensity);
cFeature->SetUseMinimumIntensity(true);
}
if (param.defineGlobalMaximumIntensity)
{
cFeature->SetMaximumIntensity(param.globalMaximumIntensity);
cFeature->SetUseMaximumIntensity(true);
}
if (param.defineGlobalNumberOfBins)
{
cFeature->SetBins(param.globalNumberOfBins);
MITK_INFO << param.globalNumberOfBins;
}
cFeature->SetParameters(parsedArgs);
cFeature->SetDirection(direction);
cFeature->SetEncodeParametersInFeaturePrefix(param.encodeParameter);
}
bool addDescription = parsedArgs.count("description");
mitk::cl::FeatureResultWriter writer(param.outputPath, writeDirection);
if (param.useDecimalPoint)
{
writer.SetDecimalPoint(param.decimalPoint);
}
std::string description = "";
if (addDescription)
{
description = parsedArgs["description"].ToString();
}
mitk::Image::Pointer cImage = image;
mitk::Image::Pointer cMask = mask;
mitk::Image::Pointer cMaskNoNaN = maskNoNaN;
mitk::Image::Pointer cMorphMask = morphMask;
if (param.useHeader)
{
writer.AddColumn("SoftwareVersion");
writer.AddColumn("Patient");
writer.AddColumn("Image");
writer.AddColumn("Segmentation");
}
// Create a QTApplication and a Datastorage
// This is necessary in order to save screenshots of
// each image / slice.
QApplication qtapplication(argc, argv);
QmitkRegisterClasses();
std::vector<mitk::AbstractGlobalImageFeature::FeatureListType> allStats;
log << " Begin Processing -";
while (imageToProcess)
{
if (sliceWise)
{
cImage = floatVector[currentSlice];
cMask = maskVector[currentSlice];
cMaskNoNaN = maskNoNaNVector[currentSlice];
cMorphMask = morphMaskVector[currentSlice];
imageToProcess = (floatVector.size()-1 > (currentSlice)) ? true : false ;
}
else
{
imageToProcess = false;
}
if (param.writePNGScreenshots)
{
SaveSliceOrImageAsPNG(cImage, cMask, param.pngScreenshotsPath, currentSlice);
}
if (param.writeAnalysisImage)
{
mitk::IOUtil::Save(cImage, param.anaylsisImagePath);
}
if (param.writeAnalysisMask)
{
mitk::IOUtil::Save(cMask, param.analysisMaskPath);
}
mitk::AbstractGlobalImageFeature::FeatureListType stats;
for (auto cFeature : features)
{
log << " Calculating " << cFeature->GetFeatureClassName() << " -";
cFeature->SetMorphMask(cMorphMask);
cFeature->CalculateAndAppendFeatures(cImage, cMask, cMaskNoNaN, stats, !param.calculateAllFeatures);
}
for (std::size_t i = 0; i < stats.size(); ++i)
{
std::cout << stats[i].first.legacyName << " - " << stats[i].second << std::endl;
}
writer.AddHeader(description, currentSlice, stats, param.useHeader, addDescription);
if (true)
{
writer.AddSubjectInformation(MITK_REVISION);
writer.AddSubjectInformation(param.imageFolder);
writer.AddSubjectInformation(param.imageName);
writer.AddSubjectInformation(param.maskName);
}
writer.AddResult(description, currentSlice, stats, param.useHeader, addDescription);
allStats.push_back(stats);
++currentSlice;
}
log << " Process Slicewise -";
if (sliceWise)
{
mitk::AbstractGlobalImageFeature::FeatureListType statMean, statStd;
for (std::size_t i = 0; i < allStats[0].size(); ++i)
{
auto cElement1 = allStats[0][i];
cElement1.first.legacyName = "SliceWise Mean " + cElement1.first.legacyName;
cElement1.second = 0.0;
auto cElement2 = allStats[0][i];
cElement2.first.legacyName = "SliceWise Var. " + cElement2.first.legacyName;
cElement2.second = 0.0;
statMean.push_back(cElement1);
statStd.push_back(cElement2);
}
for (auto cStat : allStats)
{
for (std::size_t i = 0; i < cStat.size(); ++i)
{
statMean[i].second += cStat[i].second / (1.0*allStats.size());
}
}
for (auto cStat : allStats)
{
for (std::size_t i = 0; i < cStat.size(); ++i)
{
statStd[i].second += (cStat[i].second - statMean[i].second)*(cStat[i].second - statMean[i].second) / (1.0*allStats.size());
}
}
for (std::size_t i = 0; i < statMean.size(); ++i)
{
std::cout << statMean[i].first.legacyName << " - " << statMean[i].second << std::endl;
std::cout << statStd[i].first.legacyName << " - " << statStd[i].second << std::endl;
}
if (true)
{
writer.AddSubjectInformation(MITK_REVISION);
writer.AddSubjectInformation(param.imageFolder);
writer.AddSubjectInformation(param.imageName);
writer.AddSubjectInformation(param.maskName + " - Mean");
}
writer.AddResult(description, currentSlice, statMean, param.useHeader, addDescription);
if (true)
{
writer.AddSubjectInformation(MITK_REVISION);
writer.AddSubjectInformation(param.imageFolder);
writer.AddSubjectInformation(param.imageName);
writer.AddSubjectInformation(param.maskName + " - Var.");
}
writer.AddResult(description, currentSlice, statStd, param.useHeader, addDescription);
}
int returnCode = EXIT_SUCCESS;
if (!param.outputXMLPath.empty())
{
if (sliceWise)
{
MITK_ERROR << "Xml output is not supported in slicewise mode";
returnCode = EXIT_FAILURE;
}
else
{
mitk::cl::CLResultXMLWriter xmlWriter;
xmlWriter.SetCLIArgs(parsedArgs);
xmlWriter.SetFeatures(allStats.front());
xmlWriter.SetImage(loadedImage);
xmlWriter.SetMask(loadedMask);
xmlWriter.SetMethodName("CLGlobalImageFeatures");
xmlWriter.SetMethodVersion(version + "(mitk: " MITK_VERSION_STRING+")");
xmlWriter.SetOrganisation("German Cancer Research Center (DKFZ)");
xmlWriter.SetPipelineUID(param.pipelineUID);
xmlWriter.write(param.outputXMLPath);
}
}
if (param.useLogfile)
{
log << "Finished calculation" << std::endl;
log.close();
}
return returnCode;
}
#endif
diff --git a/Modules/Classification/CLMiniApps/CLImageCropper.cpp b/Modules/Classification/CLMiniApps/CLImageCropper.cpp
deleted file mode 100644
index ca14b0b953..0000000000
--- a/Modules/Classification/CLMiniApps/CLImageCropper.cpp
+++ /dev/null
@@ -1,62 +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 "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-#include <mitkBoundingObjectCutter.h>
-#include <mitkCuboid.h>
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
-
- parser.setTitle("Dicom Loader");
- parser.setCategory("Preprocessing Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--","-");
- // Add command line argument names
- parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("reference", "r", mitkCommandLineParser::Directory, "Input file:", "Input file",us::Any(),false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("input", "i", mitkCommandLineParser::Directory, "Input file:", "Input file",us::Any(),false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file:", "Output file",us::Any(),false, false, false, mitkCommandLineParser::Output);
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- // Show a help message
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- std::string referenceName = us::any_cast<std::string>(parsedArgs["reference"]);
- std::string inputName = us::any_cast<std::string>(parsedArgs["input"]);
- std::string outputName = us::any_cast<std::string>(parsedArgs["output"]);
-
- mitk::Image::Pointer imageToCrop = mitk::IOUtil::Load<mitk::Image>(inputName);
- mitk::Image::Pointer referenceImage = mitk::IOUtil::Load<mitk::Image>(referenceName);
- mitk::BoundingObjectCutter::Pointer cutter = mitk::BoundingObjectCutter::New();
- mitk::BoundingObject::Pointer boundingObject = (mitk::Cuboid::New()).GetPointer();
- boundingObject->FitGeometry(referenceImage->GetGeometry());
-
- cutter->SetBoundingObject(boundingObject);
- cutter->SetInput(imageToCrop);
- cutter->Update();
- mitk::IOUtil::Save(cutter->GetOutput(), outputName);
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLLungSegmentation.cpp b/Modules/Classification/CLMiniApps/CLLungSegmentation.cpp
deleted file mode 100644
index e4d668d732..0000000000
--- a/Modules/Classification/CLMiniApps/CLLungSegmentation.cpp
+++ /dev/null
@@ -1,197 +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 "mitkProperties.h"
-
-#include "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-
-#include <mitkOtsuSegmentationFilter.h>
-#include "mitkLabelSetImage.h"
-
-#include "mitkImageCast.h"
-#include "mitkImageTimeSelector.h"
-#include "mitkITKImageImport.h"
-#include "mitkImageAccessByItk.h"
-
-#include <mitkMorphologicalOperations.h>
-
-#include <itkConnectedThresholdImageFilter.h>
-#include <itkImageRegionConstIterator.h>
-
-template<typename TPixel, unsigned int VImageDimension>
-void GetMinimum(itk::Image<TPixel, VImageDimension>* itkImage, double &minimum)
-{
- typedef itk::Image<TPixel, VImageDimension> InputImageType;
-
- minimum = std::numeric_limits<double>::max();
- itk::ImageRegionConstIterator<InputImageType> iter(itkImage, itkImage->GetLargestPossibleRegion());
-
- while (!iter.IsAtEnd())
- {
- minimum = std::min<double>(minimum, iter.Get());
- ++iter;
- }
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void StartRegionGrowing(itk::Image<TPixel, VImageDimension>* itkImage, mitk::Image::Pointer &result)
-{
- typedef itk::Image<TPixel, VImageDimension> InputImageType;
- typedef typename InputImageType::IndexType IndexType;
- typedef itk::ConnectedThresholdImageFilter<InputImageType, InputImageType> RegionGrowingFilterType;
- typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
-
- // convert world coordinates to image indices
- IndexType startIndex;
- IndexType seedIndex;
- IndexType bestSeedIndex;
- startIndex[0] = itkImage->GetLargestPossibleRegion().GetSize()[0]/2;
- startIndex[1] = itkImage->GetLargestPossibleRegion().GetSize()[1]/2;
- startIndex[2] = itkImage->GetLargestPossibleRegion().GetSize()[2]/2;
- auto region = itkImage->GetLargestPossibleRegion();
- auto spacing = itkImage->GetSpacing();
- spacing[0] = itkImage->GetSpacing()[0];
- spacing[1] = itkImage->GetSpacing()[1];
- spacing[2] = itkImage->GetSpacing()[2];
-
- int minimumDistance = 50 * 50 * (spacing[0] + spacing[1] + spacing[2]);
-
- for (int x = -50; x < 50; ++x)
- {
- for (int y = -50; y < 50; ++y)
- {
- for (int z = -20; z < 20; ++z)
- {
- seedIndex[0] = startIndex[0] + x;
- seedIndex[1] = startIndex[1] + y;
- seedIndex[2] = startIndex[2] + z;
- if (region.IsInside(seedIndex))
- {
- if (itkImage->GetPixel(seedIndex) > 0)
- {
- int newDistance = x*x*spacing[0] + y*y*spacing[1] + z*z*spacing[2];
- if (newDistance < minimumDistance)
- {
- bestSeedIndex = seedIndex;
- minimumDistance = newDistance;
- }
- }
- }
- }
- }
- }
- seedIndex = bestSeedIndex;
-
- MITK_INFO << "Seedpoint: " << seedIndex;
- //perform region growing in desired segmented region
- regionGrower->SetInput(itkImage);
- regionGrower->AddSeed(seedIndex);
-
- regionGrower->SetLower(1);
- regionGrower->SetUpper(255);
-
- try
- {
- regionGrower->Update();
- }
- catch (const itk::ExceptionObject&)
- {
- return; // can't work
- }
- catch (...)
- {
- return;
- }
-
- //Store result and preview
- mitk::CastToMitkImage(regionGrower->GetOutput(), result);
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
-
- parser.setTitle("Dicom Loader");
- parser.setCategory("Preprocessing Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--","-");
- // Add command line argument names
- parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("input", "i", mitkCommandLineParser::Directory, "Input folder:", "Input folder", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file:", "Output file",us::Any(),false, false, false, mitkCommandLineParser::Output);
-
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- // Show a help message
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- std::string inputFile = us::any_cast<std::string>(parsedArgs["input"]);
- std::string outFileName = us::any_cast<std::string>(parsedArgs["output"]);
-
- MITK_INFO << "Start Image Loading";
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(inputFile);
-
- MITK_INFO << "Loaded Image";
- double minimum = 0;
- AccessByItk_1(image, GetMinimum, minimum);
-
- unsigned int offset = 0;
- if (minimum < -3000)
- {
- offset = 1;
- }
- MITK_INFO << "With Minimum at " << minimum<< " Offset is set to: " << offset;
-
- mitk::OtsuSegmentationFilter::Pointer otsuFilter = mitk::OtsuSegmentationFilter::New();
- otsuFilter->SetNumberOfThresholds(1+offset);
- otsuFilter->SetValleyEmphasis(false);
- otsuFilter->SetNumberOfBins(128);
- otsuFilter->SetInput(image);
- try
- {
- otsuFilter->Update();
- }
- catch (...)
- {
- mitkThrow() << "itkOtsuFilter error (image dimension must be in {2, 3} and image must not be RGB)";
- }
-
- MITK_INFO << "Calculated Otsu";
-
- mitk::LabelSetImage::Pointer resultImage = mitk::LabelSetImage::New();
- resultImage->InitializeByLabeledImage(otsuFilter->GetOutput());
- mitk::Image::Pointer rawMask = resultImage->CreateLabelMask(offset);
- mitk::Image::Pointer pickedMask;
-
- AccessFixedTypeByItk_n(rawMask, StartRegionGrowing, (mitk::LabelSet::PixelType), (2)(3), (pickedMask));
-
- mitk::MorphologicalOperations::FillHoles(pickedMask);
- mitk::MorphologicalOperations::Closing(pickedMask, 5, mitk::MorphologicalOperations::StructuralElementType::Ball);
- mitk::MorphologicalOperations::FillHoles(pickedMask);
-
-
- mitk::IOUtil::Save(pickedMask, outFileName);
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLMatchPointReg.cpp b/Modules/Classification/CLMiniApps/CLMatchPointReg.cpp
deleted file mode 100644
index 2e29e11d93..0000000000
--- a/Modules/Classification/CLMiniApps/CLMatchPointReg.cpp
+++ /dev/null
@@ -1,164 +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 "mitkProperties.h"
-
-#include "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-
-#include "mitkPreferenceListReaderOptionsFunctor.h"
-
-
-// MatchPoint
-#include <mapRegistrationAlgorithmInterface.h>
-#include <mapAlgorithmEvents.h>
-#include <mapAlgorithmWrapperEvent.h>
-#include <mapExceptionObjectMacros.h>
-#include <mapDeploymentDLLDirectoryBrowser.h>
-#include <mapImageRegistrationAlgorithmInterface.h>
-#include <mapPointSetRegistrationAlgorithmInterface.h>
-#include <mapMaskedRegistrationAlgorithmInterface.h>
-#include <mapConvert.h>
-#include <mapDeploymentDLLAccess.h>
-#include <mapRegistrationBase.h>
-
-#include <mitkMAPAlgorithmHelper.h>
-// Qt
-#include <QDir>
-#include <QFileInfo>
-#include <mitkStandaloneDataStorage.h>
-//#include <QApplication>
-#include <QStringList>
-#include <QCoreApplication>
-#include <QmitkRegistrationJob.h>
-#include <mitkImageMappingHelper.h>
-
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
-
- parser.setTitle("Dicom Loader");
- parser.setCategory("Preprocessing Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--","-");
- // Add command line argument names
- parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("moving", "m", mitkCommandLineParser::Directory, "Input folder:", "Input folder", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("fixed", "f", mitkCommandLineParser::Directory, "Input folder:", "Input folder", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file:", "Output file", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("reader", "r", mitkCommandLineParser::Int, "Reader ID", "Reader Name", us::Any(), false);
- parser.addArgument("interpolation", "interp", mitkCommandLineParser::Int, "Reader ID", "Reader Name", us::Any(), false);
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- QFileInfo fi(argv[0]);
- map::deployment::DLLDirectoryBrowser::Pointer browser = map::deployment::DLLDirectoryBrowser::New();
- browser->addDLLSearchLocation(QDir::homePath().toStdString());
- browser->addDLLSearchLocation(QDir::currentPath().toStdString());
- browser->addDLLSearchLocation(fi.canonicalPath().toStdString());
- browser->update();
- auto dllList = browser->getLibraryInfos();
-
- int id = 0;
- std::cout << std::endl << " --- Algorithm List --- " << std::endl;
- for (auto info : dllList)
- {
- std::cout << "Algorithm ID " << id << ": " << info->getAlgorithmUID().getName() << std::endl;
- ++id;
- }
- std::cout << std::endl << " --- Interpolation List --- " << std::endl;
- std::cout << "Interpolation ID 0: Linear Interpolation " << std::endl;
- std::cout << "Interpolation ID 1: Nearest Neighbour" << std::endl;
- std::cout << "Interpolation ID 2: BSpline 3D" << std::endl << std::endl;
-
- mitk::ImageMappingInterpolator::Type interpolationMode = mitk::ImageMappingInterpolator::Linear;
-
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- // Show a help message
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
-
- std::string movingFile = us::any_cast<std::string>(parsedArgs["moving"]);
- std::string fixedFile = us::any_cast<std::string>(parsedArgs["fixed"]);
- int selectedAlgorithm = us::any_cast<int>(parsedArgs["reader"]);
- std::string outputPath = us::any_cast<std::string>(parsedArgs["output"]);
-
- if (parsedArgs.count("interpolation"))
- {
- switch (us::any_cast<int>(parsedArgs["interpolation"]))
- {
- case 0:
- interpolationMode = mitk::ImageMappingInterpolator::Linear;
- break;
- case 1:
- interpolationMode = mitk::ImageMappingInterpolator::NearestNeighbor;
- break;
- case 2:
- interpolationMode = mitk::ImageMappingInterpolator::BSpline_3;
- break;
- default:
- interpolationMode = mitk::ImageMappingInterpolator::Linear;
- }
- }
-
-
- mitk::Image::Pointer movingImage = mitk::IOUtil::Load<mitk::Image>(movingFile);
- mitk::Image::Pointer fixedImage = mitk::IOUtil::Load<mitk::Image>(fixedFile);
-
- auto dllInfo = dllList[selectedAlgorithm];
-
- if (!dllInfo)
- {
- MITK_ERROR << "No valid algorithm is selected. Cannot load algorithm. ABORTING.";
- return -1;
- }
-
- ::map::deployment::DLLHandle::Pointer tempDLLHandle = ::map::deployment::openDeploymentDLL(
- dllInfo->getLibraryFilePath());
- ::map::algorithm::RegistrationAlgorithmBase::Pointer tempAlgorithm
- = ::map::deployment::getRegistrationAlgorithm(tempDLLHandle);
- MITK_INFO << "Well....";
- if (tempAlgorithm.IsNull())
- {
- MITK_ERROR << "Error. Cannot load selected algorithm.";
- return -2;
- }
-
- mitk::MAPAlgorithmHelper helper(tempAlgorithm);
- helper.SetData(movingImage, fixedImage);
- auto registration = helper.GetRegistration();
- MITK_INFO << "Well....";
-
- mitk::Image::Pointer spResultData= mitk::ImageMappingHelper::map(movingImage,
- registration,
- false, // Use all Pixels
- 0.0, // Padding Value
- fixedImage->GetGeometry()->Clone().GetPointer(), // Ref. Geometry
- false, //!(this->m_allowUnregPixels),
- 0, // Error Value
- interpolationMode // Interpolator Type
- );
-
- MITK_INFO << "Well....";
- mitk::IOUtil::Save(spResultData, outputPath);
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLMultiForestPrediction.cpp b/Modules/Classification/CLMiniApps/CLMultiForestPrediction.cpp
deleted file mode 100644
index f19a777b53..0000000000
--- a/Modules/Classification/CLMiniApps/CLMultiForestPrediction.cpp
+++ /dev/null
@@ -1,247 +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.
-
-============================================================================*/
-#ifndef mitkForest_cpp
-#define mitkForest_cpp
-
-#include "time.h"
-#include <sstream>
-
-#include <mitkConfigFileReader.h>
-#include <mitkDataCollection.h>
-#include <mitkCollectionReader.h>
-#include <mitkCollectionWriter.h>
-#include <mitkCollectionStatistic.h>
-#include <mitkCostingStatistic.h>
-#include <vtkSmartPointer.h>
-#include <mitkIOUtil.h>
-
-#include <mitkDataCollectionUtilities.h>
-#include <mitkRandomForestIO.h>
-
-// ----------------------- Forest Handling ----------------------
-#include <mitkVigraRandomForestClassifier.h>
-
-
-int main(int argc, char* argv[])
-{
- MITK_INFO << "Starting MITK_Forest Mini-App";
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Console Input Parameter
- //////////////////////////////////////////////////////////////////////////////
- ConfigFileReader allConfig(argv[1]);
-
- bool readFile = true;
- std::stringstream ss;
- for (int i = 0; i < argc; ++i )
- {
- MITK_INFO << "-----"<< argv[i]<<"------";
- if (readFile)
- {
- if (argv[i][0] == '+')
- {
- readFile = false;
- continue;
- } else
- {
- try
- {
- allConfig.ReadFile(argv[i]);
- }
- catch ( const std::exception &e )
- {
- MITK_INFO << e.what();
- }
- }
- }
- else
- {
- std::string input = argv[i];
- std::replace(input.begin(), input.end(),'_',' ');
- ss << input << std::endl;
- }
- }
- allConfig.ReadStream(ss);
-
- try
- {
- //////////////////////////////////////////////////////////////////////////////
- // General
- //////////////////////////////////////////////////////////////////////////////
- int currentRun = allConfig.IntValue("General","Run",0);
- //int doTraining = allConfig.IntValue("General","Do Training",1);
- std::string forestPath = allConfig.Value("General","Forest Path");
- std::string trainingCollectionPath = allConfig.Value("General","Patient Collection");
- std::string testCollectionPath = allConfig.Value("General", "Patient Test Collection", trainingCollectionPath);
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Default Classification
- //////////////////////////////////////////////////////////////////////////////
- std::vector<std::string> trainPatients = allConfig.Vector("Training Group",currentRun);
- std::vector<std::string> testPatients = allConfig.Vector("Test Group",currentRun);
- std::vector<std::string> modalities = allConfig.Vector("Modalities", 0);
- std::vector<std::string> outputFilter = allConfig.Vector("Output Filter", 0);
- std::string trainMask = allConfig.Value("Data","Training Mask");
- std::string completeTrainMask = allConfig.Value("Data","Complete Training Mask");
- std::string testMask = allConfig.Value("Data","Test Mask");
- std::string resultMask = allConfig.Value("Data", "Result Mask");
- std::string resultProb = allConfig.Value("Data", "Result Propability");
- std::string outputFolder = allConfig.Value("General","Output Folder");
-
- std::string writeDataFilePath = allConfig.Value("Forest","File to write data to");
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Data Forest Parameter
- //////////////////////////////////////////////////////////////////////////////
- int testSingleDataset = allConfig.IntValue("Data", "Test Single Dataset",0);
- std::string singleDatasetName = allConfig.Value("Data", "Single Dataset Name", "none");
- std::vector<std::string> forestVector = allConfig.Vector("Forests", 0);
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Statistic Parameter
- //////////////////////////////////////////////////////////////////////////////
- std::string statisticFilePath = allConfig.Value("Evaluation", "Statistic output file");
- std::string statisticShortFilePath = allConfig.Value("Evaluation", "Statistic short output file");
- std::string statisticShortFileLabel = allConfig.Value("Evaluation", "Index for short file");
- std::string statisticGoldStandard = allConfig.Value("Evaluation", "Gold Standard Name","GTV");
- //bool statisticWithHeader = allConfig.IntValue("Evaluation", "Write header in short file",0);
- std::vector<std::string> labelGroupA = allConfig.Vector("LabelsA",0);
- std::vector<std::string> labelGroupB = allConfig.Vector("LabelsB",0);
-
-
- std::ofstream timingFile;
- timingFile.open((statisticFilePath + ".timing").c_str(), std::ios::app);
- timingFile << statisticShortFileLabel << ";";
- std::time_t lastTimePoint;
- time(&lastTimePoint);
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Images
- //////////////////////////////////////////////////////////////////////////////
- std::vector<std::string> usedModalities;
- for (std::size_t i = 0; i < modalities.size(); ++i)
- {
- usedModalities.push_back(modalities[i]);
- }
- usedModalities.push_back(trainMask);
- usedModalities.push_back(completeTrainMask);
- usedModalities.push_back(testMask);
- usedModalities.push_back(statisticGoldStandard);
-
- // vtkSmartPointer<mitk::CollectionReader> colReader = vtkSmartPointer<mitk::CollectionReader>::New();
- mitk::CollectionReader* colReader = new mitk::CollectionReader();
- colReader->AddDataElementIds(trainPatients);
- colReader->SetDataItemNames(usedModalities);
-
- if (testSingleDataset > 0)
- {
- testPatients.clear();
- testPatients.push_back(singleDatasetName);
- }
- colReader->ClearDataElementIds();
- colReader->AddDataElementIds(testPatients);
- mitk::DataCollection::Pointer testCollection = colReader->LoadCollection(testCollectionPath);
-
- std::time_t now;
- time(&now);
- double seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << ";";
- time(&lastTimePoint);
-
-
- mitk::VigraRandomForestClassifier::Pointer forest = mitk::VigraRandomForestClassifier::New();
- MITK_INFO << "Convert Test data";
- auto testDataX = mitk::DCUtilities::DC3dDToMatrixXd(testCollection, modalities, testMask);
-
- for (std::size_t i = 0; i < forestVector.size(); ++i)
- {
- forest = mitk::IOUtil::Load<mitk::VigraRandomForestClassifier>(forestVector[i]);
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- MITK_INFO << "Duration for Training: " << seconds;
- timingFile << seconds << ";";
- time(&lastTimePoint);
-
- MITK_INFO << "Predict Test Data";
- auto testDataNewY = forest->Predict(testDataX);
- auto testDataNewProb = forest->GetPointWiseProbabilities();
-
- auto maxClassValue = testDataNewProb.cols();
- std::vector<std::string> names;
- for (int j = 0; j < maxClassValue; ++j)
- {
- std::string name = resultProb + std::to_string(j);
- names.push_back(name);
- }
-
- mitk::DCUtilities::MatrixToDC3d(testDataNewY, testCollection, resultMask, testMask);
- mitk::DCUtilities::MatrixToDC3d(testDataNewProb, testCollection, names, testMask);
- MITK_INFO << "Converted predicted data";
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << ";";
- time(&lastTimePoint);
-
- //////////////////////////////////////////////////////////////////////////////
- // Save results to folder
- //////////////////////////////////////////////////////////////////////////////
- MITK_INFO << "Write Result to HDD";
- mitk::CollectionWriter::ExportCollectionToFolder(testCollection,
- outputFolder + "/result_collection.xml",
- outputFilter);
-
- MITK_INFO << "Calculate Statistic....";
- //////////////////////////////////////////////////////////////////////////////
- // Calculate and Print Statistic
- //////////////////////////////////////////////////////////////////////////////
- std::ofstream statisticFile;
- statisticFile.open(statisticFilePath.c_str(), std::ios::app);
- std::ofstream sstatisticFile;
- sstatisticFile.open(statisticShortFilePath.c_str(), std::ios::app);
-
- mitk::CollectionStatistic stat;
- stat.SetCollection(testCollection);
- stat.SetClassCount(5);
- stat.SetGoldName(statisticGoldStandard);
- stat.SetTestName(resultMask);
- stat.SetMaskName(testMask);
- mitk::BinaryValueminusOneToIndexMapper mapper;
- stat.SetGroundTruthValueToIndexMapper(&mapper);
- stat.SetTestValueToIndexMapper(&mapper);
- stat.Update();
- //stat.Print(statisticFile,sstatisticFile,statisticWithHeader, statisticShortFileLabel);
- stat.Print(statisticFile, sstatisticFile, true, statisticShortFileLabel + "_"+std::to_string(i));
- statisticFile.close();
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << std::endl;
- time(&lastTimePoint);
- timingFile.close();
- }
- }
- catch (std::string s)
- {
- MITK_INFO << s;
- return 0;
- }
- catch (char* s)
- {
- MITK_INFO << s;
- }
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLNrrdToPoly.cpp b/Modules/Classification/CLMiniApps/CLNrrdToPoly.cpp
deleted file mode 100644
index 4b6625af5a..0000000000
--- a/Modules/Classification/CLMiniApps/CLNrrdToPoly.cpp
+++ /dev/null
@@ -1,74 +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.
-
-============================================================================*/
-#ifndef mitkCLPolyToNrrd_cpp
-#define mitkCLPolyToNrrd_cpp
-
-#include "time.h"
-#include <sstream>
-#include <fstream>
-
-#include <mitkIOUtil.h>
-#include "mitkCommandLineParser.h"
-
-// VTK
-#include <vtkSmartPointer.h>
-#include <vtkImageMarchingCubes.h>
-#include <vtkXMLPolyDataWriter.h>
-
-typedef itk::Image< double, 3 > FloatImageType;
-typedef itk::Image< unsigned char, 3 > MaskImageType;
-
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("mask", "m", mitkCommandLineParser::Image, "Input Mask", "Mask Image that specifies the area over for the statistic, (Values = 1)", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output text file", "Target file. The output statistic is appended to this file.", us::Any(), false, false, false, mitkCommandLineParser::Output);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Segmentation to Mask");
- parser.setDescription("Estimates a Mesh from a segmentation");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- MITK_INFO << "Version: "<< 1.0;
-
- mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(parsedArgs["mask"].ToString());
-
-
- vtkSmartPointer<vtkImageData> image = mask->GetVtkImageData();
- image->SetOrigin(mask->GetGeometry()->GetOrigin()[0], mask->GetGeometry()->GetOrigin()[1], mask->GetGeometry()->GetOrigin()[2]);
- vtkSmartPointer<vtkImageMarchingCubes> mesher = vtkSmartPointer<vtkImageMarchingCubes>::New();
- mesher->SetInputData(image);
- mitk::Surface::Pointer surf = mitk::Surface::New();
- mesher->SetValue(0,0.5);
- mesher->Update();
- surf->SetVtkPolyData(mesher->GetOutput());
- mitk::IOUtil::Save(surf, parsedArgs["output"].ToString());
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp b/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp
deleted file mode 100644
index 62465f1958..0000000000
--- a/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp
+++ /dev/null
@@ -1,173 +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.
-
-============================================================================*/
-#ifndef mitkCLPolyToNrrd_cpp
-#define mitkCLPolyToNrrd_cpp
-
-#include "time.h"
-#include <sstream>
-#include <fstream>
-
-#include <mitkIOUtil.h>
-#include "mitkCommandLineParser.h"
-
-#include <mitkSplitParameterToVector.h>
-#include <mitkGlobalImageFeaturesParameter.h>
-#include <itkImageRegionIteratorWithIndex.h>
-
-#include <QApplication>
-#include <mitkStandaloneDataStorage.h>
-#include "QmitkRegisterClasses.h"
-#include "QmitkRenderWindow.h"
-#include "vtkRenderLargeImage.h"
-#include "vtkPNGWriter.h"
-
-#include <mitkImageAccessByItk.h>
-#include <mitkImageCast.h>
-
-typedef itk::Image< double, 3 > FloatImageType;
-typedef itk::Image< unsigned char, 3 > MaskImageType;
-
-
-template<typename TPixel, unsigned int VImageDimension>
-static void
-FindMostSampleSlice(itk::Image<TPixel, VImageDimension>* mask, int & selectedSlice)
-{
- int idx = VImageDimension - 1;
-
- int size = mask->GetLargestPossibleRegion().GetSize()[idx];
- std::vector<int> numberOfSamples;
- numberOfSamples.resize(size,0);
-
- itk::ImageRegionIteratorWithIndex<itk::Image<TPixel, VImageDimension> > mask1Iter(mask, mask->GetLargestPossibleRegion());
- while (!mask1Iter.IsAtEnd())
- {
- if (mask1Iter.Value() > 0)
- {
- numberOfSamples[mask1Iter.GetIndex()[idx]]+=1;
- }
- ++mask1Iter;
- }
- selectedSlice = 0;
- for (std::size_t i = 0; i < numberOfSamples.size(); ++i)
- {
- if (numberOfSamples[selectedSlice] < numberOfSamples[i])
- selectedSlice = i;
- }
-}
-
-static
-void SaveSliceOrImageAsPNG(mitk::Image::Pointer image, mitk::Image::Pointer mask, std::string path, int index)
-{
- // Create a Standalone Datastorage for the single purpose of saving screenshots..
- mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New();
- QmitkRenderWindow renderWindow;
- renderWindow.GetRenderer()->SetDataStorage(ds);
-
- auto nodeI = mitk::DataNode::New();
- nodeI->SetData(image);
- auto nodeM = mitk::DataNode::New();
- nodeM->SetData(mask);
- ds->Add(nodeI);
- ds->Add(nodeM);
-
- auto geo = ds->ComputeBoundingGeometry3D(ds->GetAll());
- mitk::RenderingManager::GetInstance()->InitializeViews(mask->GetTimeGeometry());
-
- mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController();
- sliceNaviController->SetViewDirection(mitk::AnatomicalPlane::Axial);
- unsigned int numberOfSteps = 1;
- if (sliceNaviController)
- {
- numberOfSteps = sliceNaviController->GetSlice()->GetSteps();
- sliceNaviController->GetSlice()->SetPos(numberOfSteps-index);
- }
-
- renderWindow.show();
- renderWindow.resize(256, 256);
-
- //if (sliceNaviController)
- //{
- // sliceNaviController->GetSlice()->SetPos(index);
- //}
- renderWindow.GetRenderer()->PrepareRender();
-
- vtkRenderWindow* renderWindow2 = renderWindow.GetVtkRenderWindow();
- mitk::BaseRenderer* baserenderer = mitk::BaseRenderer::GetInstance(renderWindow2);
- auto vtkRender = baserenderer->GetVtkRenderer();
- vtkRender->GetRenderWindow()->WaitForCompletion();
-
- vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New();
- magnifier->SetInput(vtkRender);
- magnifier->SetMagnification(3.0);
-
- std::stringstream ss;
- ss << path <<".png";
- std::string tmpImageName;
- ss >> tmpImageName;
- auto fileWriter = vtkPNGWriter::New();
- fileWriter->SetInputConnection(magnifier->GetOutputPort());
- fileWriter->SetFileName(tmpImageName.c_str());
- fileWriter->Write();
- fileWriter->Delete();
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
-
- parser.addArgument("image", "i", mitkCommandLineParser::Image, "Input Image", "", us::Any(),false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("mask", "m", mitkCommandLineParser::Image, "Input Image", "", us::Any(),false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::Image, "Output Image", "", us::Any(),false, false, false, mitkCommandLineParser::Input);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Image with Overlay Plotter");
- parser.setDescription("Plots ");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- std::string imagePath = us::any_cast<std::string>(parsedArgs["image"]);
- std::string maskPath = us::any_cast<std::string>(parsedArgs["mask"]);
- std::string outputPath = us::any_cast<std::string>(parsedArgs["output"]);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- std::string version = "Version: 1.0";
- MITK_INFO << version;
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(imagePath);
- mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(maskPath);
-
- // Create a QTApplication and a Datastorage
- // This is necessary in order to save screenshots of
- // each image / slice.
- QApplication qtapplication(argc, argv);
- QmitkRegisterClasses();
-
- int currentSlice = 0;
- AccessByItk_1(mask, FindMostSampleSlice, currentSlice);
-
- SaveSliceOrImageAsPNG(image, mask, outputPath, currentSlice);
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLPlanarFigureToNrrd.cpp b/Modules/Classification/CLMiniApps/CLPlanarFigureToNrrd.cpp
deleted file mode 100644
index da36d996ee..0000000000
--- a/Modules/Classification/CLMiniApps/CLPlanarFigureToNrrd.cpp
+++ /dev/null
@@ -1,140 +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.
-
-============================================================================*/
-#ifndef mitkCLPolyToNrrd_cpp
-#define mitkCLPolyToNrrd_cpp
-
-#include "time.h"
-#include <sstream>
-
-#include <mitkIOUtil.h>
-
-#include "mitkCommandLineParser.h"
-#include <mitkPlanarFigureMaskGenerator.h>
-#include <mitkImageAccessByItk.h>
-#include <mitkImageCast.h>
-#include <itkImageRegionIteratorWithIndex.h>
-#include <mitkImageAccessByItk.h>
-
-
-typedef itk::Image< double, 3 > FloatImageType;
-typedef itk::Image< unsigned char, 3 > MaskImageType;
-
-struct MaskParameter
-{
- mitk::Image::ConstPointer mask;
- unsigned int axis;
- unsigned int slice;
-};
-
-template < typename TPixel, unsigned int VImageDimension >
-void CreateNewMask(const itk::Image< TPixel, VImageDimension > *image, MaskParameter param, mitk::Image::Pointer &output)
-{
- int transform[3][2];
- transform[0][0] = 1; transform[0][1] = 2;
- transform[1][0] = 0; transform[1][1] = 2;
- transform[2][0] = 0; transform[2][1] = 1;
-
- typedef itk::Image<unsigned short, VImageDimension> MaskType;
- typedef itk::Image<unsigned short, 2> Mask2DType;
- typename Mask2DType::Pointer mask = Mask2DType::New();
- mitk::CastToItkImage(param.mask, mask);
-
-
- typename MaskType::Pointer mask3D = MaskType::New();
- mask3D->SetRegions(image->GetLargestPossibleRegion());
- mask3D->SetSpacing(image->GetSpacing());
- mask3D->SetOrigin(image->GetOrigin());
- mask3D->Allocate();
-
- itk::ImageRegionIteratorWithIndex<MaskType> iter(mask3D, mask3D->GetLargestPossibleRegion());
- while (!iter.IsAtEnd())
- {
- auto index = iter.GetIndex();
- iter.Set(0);
- if (index[param.axis] == param.slice)
- {
- Mask2DType::IndexType index2D;
- index2D[0] = index[transform[param.axis][0]];
- index2D[1] = index[transform[param.axis][1]];
- auto pixel = mask->GetPixel(index2D);
- iter.Set(pixel);
- }
- ++iter;
- }
-
- mitk::CastToMitkImage(mask3D, output);
-
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("planar", "p", mitkCommandLineParser::Directory, "Input Polydata", "Path to the input VTK polydata", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("image", "i", mitkCommandLineParser::Directory, "Input Image", "Image which defines the dimensions of the Segmentation", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file", "Output file. ", us::Any(), false, false, false, mitkCommandLineParser::Input);
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Planar Data to Nrrd Segmentation");
- parser.setDescription("Creates a Nrrd segmentation based on a 2d-vtk polydata.");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- try
- {
- mitk::BaseData::Pointer data = mitk::IOUtil::Load(parsedArgs["planar"].ToString())[0];
- mitk::PlanarFigure::Pointer planar = dynamic_cast<mitk::PlanarFigure*>(data.GetPointer());
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(parsedArgs["image"].ToString());
-
- mitk::PlanarFigureMaskGenerator::Pointer pfMaskGen = mitk::PlanarFigureMaskGenerator::New();
- pfMaskGen->SetPlanarFigure(planar);
- pfMaskGen->SetTimeStep(0);
- pfMaskGen->SetInputImage(image.GetPointer());
-
- mitk::Image::ConstPointer mask = pfMaskGen->GetMask();
- unsigned int axis = pfMaskGen->GetPlanarFigureAxis();
- unsigned int slice = pfMaskGen->GetPlanarFigureSlice();
-
- //itk::Image<unsigned short, 3>::IndexType index;
- mitk::Image::Pointer fullMask;
- MaskParameter param;
- param.slice = slice;
- param.axis = axis;
- param.mask = mask;
- AccessByItk_2(image, CreateNewMask, param, fullMask);
-
- std::string saveAs = parsedArgs["output"].ToString();
- MITK_INFO << "Save as: " << saveAs;
- mitk::IOUtil::Save(mask, saveAs);
- mitk::IOUtil::Save(fullMask, saveAs);
-
- return 0;
- }
- catch (...)
- {
- return EXIT_FAILURE;
- }
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLPointSetToSegmentation.cpp b/Modules/Classification/CLMiniApps/CLPointSetToSegmentation.cpp
deleted file mode 100644
index ecfb94790f..0000000000
--- a/Modules/Classification/CLMiniApps/CLPointSetToSegmentation.cpp
+++ /dev/null
@@ -1,116 +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.
-
-============================================================================*/
-#ifndef mitkCLPolyToNrrd_cpp
-#define mitkCLPolyToNrrd_cpp
-
-#include "time.h"
-#include <sstream>
-
-#include <mitkIOUtil.h>
-#include <mitkPointSet.h>
-#include <mitkImageCast.h>
-#include <itkImageRegionIteratorWithIndex.h>
-#include <limits>
-
-#include "mitkCommandLineParser.h"
-
-
-
-typedef itk::Image< double, 3 > FloatImageType;
-typedef itk::Image< unsigned short, 3 > MaskImageType;
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("pointset", "p", mitkCommandLineParser::Directory, "Input Polydata", "Path to the input VTK polydata", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("image", "i", mitkCommandLineParser::Directory, "Input Image", "Image which defines the dimensions of the Segmentation", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file", "Output files. Two files are create, a .nrrd image and a 3d-vtk.", us::Any(), false, false, false, mitkCommandLineParser::Input);
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("2D-Polydata to Nrrd Segmentation");
- parser.setDescription("Creates a Nrrd segmentation based on a 2d-vtk polydata.");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- mitk::BaseData::Pointer data = mitk::IOUtil::Load(parsedArgs["pointset"].ToString())[0];
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(parsedArgs["image"].ToString());
-
- //MITK_INFO << data;
- mitk::PointSet::Pointer points = dynamic_cast<mitk::PointSet*>(data.GetPointer());
- MaskImageType::Pointer mask = MaskImageType::New();
- mitk::CastToItkImage(image, mask);
-
- double minX, minY, minZ;
- double maxX, maxY, maxZ;
- minX = minY = minZ = std::numeric_limits<double>::max();
- maxX = maxY = maxZ = std::numeric_limits<double>::lowest();
-
- for (auto iter = points->Begin(); iter != points->End(); ++iter)
- {
- minX = std::min<double>(minX, iter.Value().GetElement(0));
- minY = std::min<double>(minY, iter.Value().GetElement(1));
- minZ = std::min<double>(minZ, iter.Value().GetElement(2));
- maxX = std::max<double>(maxX, iter.Value().GetElement(0));
- maxY = std::max<double>(maxY, iter.Value().GetElement(1));
- maxZ = std::max<double>(maxZ, iter.Value().GetElement(2));
- }
- MaskImageType::PointType point;
- MaskImageType::IndexType iMin;
- MaskImageType::IndexType iMax;
- point[0] = minX;
- point[1] = minY;
- point[2] = minZ;
- mask->TransformPhysicalPointToIndex(point, iMin);
- point[0] = maxX;
- point[1] = maxY;
- point[2] = maxZ;
- mask->TransformPhysicalPointToIndex(point, iMax);
-
- itk::ImageRegionIteratorWithIndex<MaskImageType> iter(mask, mask->GetLargestPossibleRegion());
- while (!iter.IsAtEnd())
- {
- MaskImageType::IndexType index = iter.GetIndex();
- if ((index[0] >= iMin[0]) && (index[1] >= iMin[1]) && (index[2] >= iMin[2]) &&
- (index[0] <= iMax[0]) && (index[1] <= iMax[1]) && (index[2] <= iMax[2]))
- {
- iter.Set(1);
- }
- else
- {
- iter.Set(0);
- }
- ++iter;
- }
-
- mitk::Image::Pointer ergImage = mitk::Image::New();
- mitk::CastToMitkImage(mask, ergImage);
-
- std::string saveAs = parsedArgs["output"].ToString();
- MITK_INFO << "Save as: " << saveAs;
- mitk::IOUtil::Save(ergImage, saveAs);
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLPolyToNrrd.cpp b/Modules/Classification/CLMiniApps/CLPolyToNrrd.cpp
deleted file mode 100644
index 80dc07b5d7..0000000000
--- a/Modules/Classification/CLMiniApps/CLPolyToNrrd.cpp
+++ /dev/null
@@ -1,104 +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.
-
-============================================================================*/
-#ifndef mitkCLPolyToNrrd_cpp
-#define mitkCLPolyToNrrd_cpp
-
-#include "time.h"
-#include <sstream>
-
-#include <mitkIOUtil.h>
-#include <vtkPolyData.h>
-#include <vtkCellArray.h>
-#include <mitkSurface.h>
-
-#include "mitkCommandLineParser.h"
-
-#include <mitkSurfaceToImageFilter.h>
-#include <vtkSmartPointer.h>
-#include <vtkLinearExtrusionFilter.h>
-#include <mitkSurfaceToImageFilter.h>
-#include <mitkConvert2Dto3DImageFilter.h>
-
-
-
-typedef itk::Image< double, 3 > FloatImageType;
-typedef itk::Image< unsigned char, 3 > MaskImageType;
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("polydata", "p", mitkCommandLineParser::Directory, "Input Polydata", "Path to the input VTK polydata", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("image", "i", mitkCommandLineParser::Directory, "Input Image", "Image which defines the dimensions of the Segmentation", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file", "Output files. Two files are create, a .nrrd image and a 3d-vtk.", us::Any(), false, false, false, mitkCommandLineParser::Input);
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("2D-Polydata to Nrrd Segmentation");
- parser.setDescription("Creates a Nrrd segmentation based on a 2d-vtk polydata.");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- mitk::BaseData::Pointer data = mitk::IOUtil::Load(parsedArgs["polydata"].ToString())[0];
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(parsedArgs["image"].ToString());
-
- //MITK_INFO << data;
- mitk::Surface::Pointer surf = dynamic_cast<mitk::Surface*>(data.GetPointer());
- vtkSmartPointer<vtkPolyData> circle = surf->GetVtkPolyData();
-
- vtkSmartPointer<vtkLinearExtrusionFilter> extruder =
- vtkSmartPointer<vtkLinearExtrusionFilter>::New();
-
- extruder->SetInputData(circle);
- image->GetGeometry()->GetSpacing()[2];
- extruder->SetScaleFactor(1.);
- extruder->SetExtrusionTypeToNormalExtrusion();
- extruder->SetVector(0, 0, image->GetGeometry()->GetSpacing()[2]);
- extruder->Update();
- surf->SetVtkPolyData(extruder->GetOutput());
-
- mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
- surfaceToImageFilter->MakeOutputBinaryOn();
- surfaceToImageFilter->SetInput(surf);
- surfaceToImageFilter->SetImage(image);
- surfaceToImageFilter->Update();
- mitk::Image::Pointer resultImage = surfaceToImageFilter->GetOutput();
-
- mitk::Convert2Dto3DImageFilter::Pointer multiFilter = mitk::Convert2Dto3DImageFilter::New();
- multiFilter->SetInput(resultImage);
- multiFilter->Update();
- resultImage = multiFilter->GetOutput();
-
- std::string saveAs = parsedArgs["output"].ToString();
- MITK_INFO << "Save as: " << saveAs;
- saveAs = saveAs + ".vtk";
- mitk::IOUtil::Save(surf.GetPointer(),saveAs);
-
- saveAs = parsedArgs["output"].ToString();
- MITK_INFO << "Save as: " << saveAs;
- saveAs = saveAs + ".nrrd";
- mitk::IOUtil::Save(resultImage,saveAs);
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLPurfVoxelClassification.cpp b/Modules/Classification/CLMiniApps/CLPurfVoxelClassification.cpp
deleted file mode 100644
index 54e9951314..0000000000
--- a/Modules/Classification/CLMiniApps/CLPurfVoxelClassification.cpp
+++ /dev/null
@@ -1,443 +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.
-
-============================================================================*/
-#ifndef mitkForest_cpp
-#define mitkForest_cpp
-
-#include "time.h"
-#include <sstream>
-
-#include <mitkConfigFileReader.h>
-#include <mitkDataCollection.h>
-#include <mitkCollectionReader.h>
-#include <mitkCollectionWriter.h>
-#include <mitkCollectionStatistic.h>
-#include <mitkCostingStatistic.h>
-#include <vtkSmartPointer.h>
-#include <mitkIOUtil.h>
-
-#include <mitkDataCollectionUtilities.h>
-#include <mitkRandomForestIO.h>
-
-// ----------------------- Forest Handling ----------------------
-//#include <mitkDecisionForest.h>
-#include <mitkVigraRandomForestClassifier.h>
-//#include <mitkThresholdSplit.h>
-//#include <mitkImpurityLoss.h>
-//#include <mitkLinearSplitting.h>
-//#include <mitkVigraConverter.h>
-// ----------------------- Point weighting ----------------------
-//#include <mitkForestWeighting.h>
-//#include <mitkKliepDensityEstimation.h>
-//#include <mitkExternalWeighting.h>
-#include <mitkLRDensityEstimation.h>
-//#include <mitkKNNDensityEstimation.h>
-//#include <mitkZadroznyWeighting.h>
-//#include <mitkSpectralDensityEstimation.h>
-//#include <mitkULSIFDensityEstimation.h>
-
-int main(int argc, char* argv[])
-{
- MITK_INFO << "Starting MITK_Forest Mini-App";
- double startTime = time(0);
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Console Input Parameter
- //////////////////////////////////////////////////////////////////////////////
- ConfigFileReader allConfig(argv[1]);
-
- bool readFile = true;
- std::stringstream ss;
- for (int i = 0; i < argc; ++i )
- {
- MITK_INFO << "-----"<< argv[i]<<"------";
- if (readFile)
- {
- if (argv[i][0] == '+')
- {
- readFile = false;
- continue;
- } else
- {
- try
- {
- allConfig.ReadFile(argv[i]);
- }
- catch (std::exception &e)
- {
- MITK_INFO << e.what();
- }
- }
- }
- else
- {
- std::string input = argv[i];
- std::replace(input.begin(), input.end(),'_',' ');
- ss << input << std::endl;
- }
- }
- allConfig.ReadStream(ss);
-
- try
- {
- //////////////////////////////////////////////////////////////////////////////
- // General
- //////////////////////////////////////////////////////////////////////////////
- int currentRun = allConfig.IntValue("General","Run",0);
- int doTraining = allConfig.IntValue("General","Do Training",1);
- std::string forestPath = allConfig.Value("General","Forest Path");
- std::string trainingCollectionPath = allConfig.Value("General","Patient Collection");
- std::string testCollectionPath = trainingCollectionPath;
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Default Classification
- //////////////////////////////////////////////////////////////////////////////
- std::vector<std::string> trainPatients = allConfig.Vector("Training Group",currentRun);
- std::vector<std::string> testPatients = allConfig.Vector("Test Group",currentRun);
- std::vector<std::string> modalities = allConfig.Vector("Modalities",0);
- std::string trainMask = allConfig.Value("Data","Training Mask");
- std::string completeTrainMask = allConfig.Value("Data","Complete Training Mask");
- std::string testMask = allConfig.Value("Data","Test Mask");
- std::string resultMask = allConfig.Value("Data", "Result Mask");
- std::string resultProb = allConfig.Value("Data", "Result Propability");
- std::string outputFolder = allConfig.Value("General","Output Folder");
-
- std::string writeDataFilePath = allConfig.Value("Forest","File to write data to");
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Forest Parameter
- //////////////////////////////////////////////////////////////////////////////
- int minimumSplitNodeSize = allConfig.IntValue("Forest", "Minimum split node size",1);
- int numberOfTrees = allConfig.IntValue("Forest", "Number of Trees",255);
- double samplesPerTree = atof(allConfig.Value("Forest", "Samples per Tree").c_str());
- if (samplesPerTree <= 0.0000001)
- {
- samplesPerTree = 1.0;
- }
- MITK_INFO << "Samples per Tree: " << samplesPerTree;
- int sampleWithReplacement = allConfig.IntValue("Forest", "Sample with replacement",1);
- double trainPrecision = atof(allConfig.Value("Forest", "Precision").c_str());
- if (trainPrecision <= 0.0000000001)
- {
- trainPrecision = 0.0;
- }
- double weightLambda = atof(allConfig.Value("Forest", "Weight Lambda").c_str());
- if (weightLambda <= 0.0000000001)
- {
- weightLambda = 0.0;
- }
- int maximumTreeDepth = allConfig.IntValue("Forest", "Maximum Tree Depth",10000);
- int randomSplit = allConfig.IntValue("Forest","Use RandomSplit",0);
- //////////////////////////////////////////////////////////////////////////////
- // Read Statistic Parameter
- //////////////////////////////////////////////////////////////////////////////
- std::string statisticFilePath = allConfig.Value("Evaluation", "Statistic output file");
- std::string statisticShortFilePath = allConfig.Value("Evaluation", "Statistic short output file");
- std::string statisticShortFileLabel = allConfig.Value("Evaluation", "Index for short file");
- std::string statisticGoldStandard = allConfig.Value("Evaluation", "Gold Standard Name","GTV");
- bool statisticWithHeader = allConfig.IntValue("Evaluation", "Write header in short file",0);
- std::vector<std::string> labelGroupA = allConfig.Vector("LabelsA",0);
- std::vector<std::string> labelGroupB = allConfig.Vector("LabelsB",0);
- //////////////////////////////////////////////////////////////////////////////
- // Read Special Parameter
- //////////////////////////////////////////////////////////////////////////////
- bool useWeightedPoints = allConfig.IntValue("Forest", "Use point-based weighting",0);
- bool writePointsToFile = allConfig.IntValue("Forest", "Write points to file",0);
- int importanceWeightAlgorithm = allConfig.IntValue("Forest","Importance weight Algorithm",0);
- std::string importanceWeightName = allConfig.Value("Forest","Importance weight name","");
-
- std::ofstream timingFile;
- timingFile.open((statisticFilePath + ".timing").c_str(), std::ios::app);
- timingFile << statisticShortFileLabel << ";";
- std::time_t lastTimePoint;
- time(&lastTimePoint);
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Images
- //////////////////////////////////////////////////////////////////////////////
- std::vector<std::string> usedModalities;
- for (int i = 0; i < modalities.size(); ++i)
- {
- usedModalities.push_back(modalities[i]);
- }
- usedModalities.push_back(trainMask);
- usedModalities.push_back(completeTrainMask);
- usedModalities.push_back(testMask);
- usedModalities.push_back(statisticGoldStandard);
- usedModalities.push_back(importanceWeightName);
-
- // vtkSmartPointer<mitk::CollectionReader> colReader = vtkSmartPointer<mitk::CollectionReader>::New();
- mitk::CollectionReader* colReader = new mitk::CollectionReader();
- colReader->AddDataElementIds(trainPatients);
- colReader->SetDataItemNames(usedModalities);
- //colReader->SetNames(usedModalities);
- mitk::DataCollection::Pointer trainCollection;
- if (doTraining)
- {
- trainCollection = colReader->LoadCollection(trainingCollectionPath);
- }
- colReader->ClearDataElementIds();
- colReader->AddDataElementIds(testPatients);
- mitk::DataCollection::Pointer testCollection = colReader->LoadCollection(testCollectionPath);
-
- std::time_t now;
- time(&now);
- double seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << ";";
- time(&lastTimePoint);
-
- /*
- if (writePointsToFile)
- {
- MITK_INFO << "Use external weights...";
- mitk::ExternalWeighting weightReader;
- weightReader.SetModalities(modalities);
- weightReader.SetTestCollection(testCollection);
- weightReader.SetTrainCollection(trainCollection);
- weightReader.SetTestMask(testMask);
- weightReader.SetTrainMask(trainMask);
- weightReader.SetWeightsName("weights");
- weightReader.SetCorrectionFactor(1.0);
- weightReader.SetWeightFileName(writeDataFilePath);
- weightReader.WriteData();
- return 0;
- }*/
-
- //////////////////////////////////////////////////////////////////////////////
- // If required do Training....
- //////////////////////////////////////////////////////////////////////////////
- //mitk::DecisionForest forest;
-
- mitk::VigraRandomForestClassifier::Pointer forest = mitk::VigraRandomForestClassifier::New();
- forest->SetSamplesPerTree(samplesPerTree);
- forest->SetMinimumSplitNodeSize(minimumSplitNodeSize);
- forest->SetTreeCount(numberOfTrees);
- forest->UseSampleWithReplacement(sampleWithReplacement);
- forest->SetPrecision(trainPrecision);
- forest->SetMaximumTreeDepth(maximumTreeDepth);
- forest->SetWeightLambda(weightLambda);
-
- // TOOD forest.UseRandomSplit(randomSplit);
-
- if (doTraining)
- {
- // 0 = LR-Estimation
- // 1 = KNN-Estimation
- // 2 = Kliep
- // 3 = Extern Image
- // 4 = Zadrozny
- // 5 = Spectral
- // 6 = uLSIF
- auto trainDataX = mitk::DCUtilities::DC3dDToMatrixXd(trainCollection, modalities, trainMask);
- auto trainDataY = mitk::DCUtilities::DC3dDToMatrixXi(trainCollection, trainMask, trainMask);
-
- if (useWeightedPoints)
- //if (false)
- {
- MITK_INFO << "Activated Point-based weighting...";
- //forest.UseWeightedPoints(true);
- forest->UsePointWiseWeight(true);
- //forest.SetWeightName("calculated_weight");
- /*if (importanceWeightAlgorithm == 1)
- {
- mitk::KNNDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 2)
- {
- mitk::KliepDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 3)
- {
- forest.SetWeightName(importanceWeightName);
- } else if (importanceWeightAlgorithm == 4)
- {
- mitk::ZadroznyWeighting est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 5)
- {
- mitk::SpectralDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 6)
- {
- mitk::ULSIFDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else*/
- {
- mitk::LRDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- }
- auto trainDataW = mitk::DCUtilities::DC3dDToMatrixXd(trainCollection, "calculated_weight", trainMask);
- forest->SetPointWiseWeight(trainDataW);
- forest->UsePointWiseWeight(true);
- }
- forest->Train(trainDataX, trainDataY);
- // TODO forest.Save(forestPath);
- } else
- {
- // TODO forest.Load(forestPath);
- }
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << ";";
- time(&lastTimePoint);
- //////////////////////////////////////////////////////////////////////////////
- // If required do Save Forest....
- //////////////////////////////////////////////////////////////////////////////
-
- //writer.// (forest);
- /*
- auto w = forest->GetTreeWeights();
- w(0,0) = 10;
- forest->SetTreeWeights(w);*/
- //mitk::IOUtil::Save(forest,"d:/tmp/forest.forest");
-
- //////////////////////////////////////////////////////////////////////////////
- // If required do test
- //////////////////////////////////////////////////////////////////////////////
- auto testDataX = mitk::DCUtilities::DC3dDToMatrixXd(testCollection,modalities, testMask);
- auto testDataNewY = forest->Predict(testDataX);
- auto testDataNewProb = forest->GetPointWiseProbabilities();
- //MITK_INFO << testDataNewY;
-
- std::vector<std::string> names;
- names.push_back("prob-1");
- names.push_back("prob-2");
-
- mitk::DCUtilities::MatrixToDC3d(testDataNewY, testCollection, resultMask, testMask);
- mitk::DCUtilities::MatrixToDC3d(testDataNewProb, testCollection, names, testMask);
- //forest.SetMaskName(testMask);
- //forest.SetCollection(testCollection);
- //forest.Test();
- //forest.PrintTree(0);
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << ";";
- time(&lastTimePoint);
-
- //////////////////////////////////////////////////////////////////////////////
- // Cost-based analysis
- //////////////////////////////////////////////////////////////////////////////
-
- // TODO Reactivate
- //MITK_INFO << "Calculate Cost-based Statistic ";
- //mitk::CostingStatistic costStat;
- //costStat.SetCollection(testCollection);
- //costStat.SetCombinedA("combinedHealty");
- //costStat.SetCombinedB("combinedTumor");
- //costStat.SetCombinedLabel("combinedLabel");
- //costStat.SetMaskName(testMask);
- ////std::vector<std::string> labelHealthy;
- ////labelHealthy.push_back("result_prop_Class-0");
- ////labelHealthy.push_back("result_prop_Class-4");
- ////std::vector<std::string> labelTumor;
- ////labelTumor.push_back("result_prop_Class-1");
- ////labelTumor.push_back("result_prop_Class-2");
- ////labelTumor.push_back("result_prop_Class-3");
- //costStat.SetProbabilitiesA(labelGroupA);
- //costStat.SetProbabilitiesB(labelGroupB);
-
- //std::ofstream costStatisticFile;
- //costStatisticFile.open((statisticFilePath + ".cost").c_str(), std::ios::app);
- //std::ofstream lcostStatisticFile;
-
- //lcostStatisticFile.open((statisticFilePath + ".longcost").c_str(), std::ios::app);
- //costStat.WriteStatistic(lcostStatisticFile,costStatisticFile,2.5,statisticShortFileLabel);
- //costStatisticFile.close();
-
- //costStat.CalculateClass(50);
-
- //////////////////////////////////////////////////////////////////////////////
- // Save results to folder
- //////////////////////////////////////////////////////////////////////////////
- std::vector<std::string> outputFilter;
- //outputFilter.push_back(resultMask);
- //std::vector<std::string> propNames = forest.GetListOfProbabilityNames();
- //outputFilter.insert(outputFilter.begin(), propNames.begin(), propNames.end());
- mitk::CollectionWriter::ExportCollectionToFolder(testCollection,
- outputFolder + "/result_collection.xml",
- outputFilter);
-
- MITK_INFO << "Calculate Statistic...." ;
- //////////////////////////////////////////////////////////////////////////////
- // Calculate and Print Statistic
- //////////////////////////////////////////////////////////////////////////////
- std::ofstream statisticFile;
- statisticFile.open(statisticFilePath.c_str(), std::ios::app);
- std::ofstream sstatisticFile;
- sstatisticFile.open(statisticShortFilePath.c_str(), std::ios::app);
-
- mitk::CollectionStatistic stat;
- stat.SetCollection(testCollection);
- stat.SetClassCount(2);
- stat.SetGoldName(statisticGoldStandard);
- stat.SetTestName(resultMask);
- stat.SetMaskName(testMask);
- mitk::BinaryValueminusOneToIndexMapper* mapper = new mitk::BinaryValueminusOneToIndexMapper;
- stat.SetGroundTruthValueToIndexMapper(mapper);
- stat.SetTestValueToIndexMapper(mapper);
- stat.Update();
- //stat.Print(statisticFile,sstatisticFile,statisticWithHeader, statisticShortFileLabel);
- stat.Print(statisticFile,sstatisticFile,true, statisticShortFileLabel);
- statisticFile.close();
- delete mapper;
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << std::endl;
- time(&lastTimePoint);
- timingFile.close();
- }
- catch (std::string s)
- {
- MITK_INFO << s;
- return 0;
- }
- catch (char* s)
- {
- MITK_INFO << s;
- }
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLRandomSampling.cpp b/Modules/Classification/CLMiniApps/CLRandomSampling.cpp
deleted file mode 100644
index 7dab031c69..0000000000
--- a/Modules/Classification/CLMiniApps/CLRandomSampling.cpp
+++ /dev/null
@@ -1,154 +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 "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-#include <mitkRandomImageSampler.h>
-
-static std::vector<double> splitDouble(std::string str, char delimiter) {
- std::vector<double> internal;
- std::stringstream ss(str); // Turn the string into a stream.
- std::string tok;
- double val;
- while (getline(ss, tok, delimiter)) {
- std::stringstream s2(tok);
- s2 >> val;
- internal.push_back(val);
- }
-
- return internal;
-}
-
-static std::vector<unsigned int> splitUInt(std::string str, char delimiter) {
- std::vector<unsigned int> internal;
- std::stringstream ss(str); // Turn the string into a stream.
- std::string tok;
- unsigned int val;
- while (getline(ss, tok, delimiter)) {
- std::stringstream s2(tok);
- s2 >> val;
- internal.push_back(val);
- }
-
- return internal;
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
-
- parser.setTitle("Random Sampling");
- parser.setCategory("Classification Command Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--", "-");
- // Add command line argument names
- parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("input", "i", mitkCommandLineParser::Directory, "Input file:", "Input file", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file:", "Output file", us::Any(), false, false, false, mitkCommandLineParser::Output);
-
- parser.addArgument("single-rate", "sr", mitkCommandLineParser::File, "Single Acceptance rate for all voxel", "Output file", us::Any(), true, false, false, mitkCommandLineParser::Output);
- parser.addArgument("class-rate", "cr", mitkCommandLineParser::File, "Class-dependend acceptance rate", "Output file", us::Any(), true, false, false, mitkCommandLineParser::Output);
- parser.addArgument("single-number", "sn", mitkCommandLineParser::File, "Single Number of Voxel for each class", "Output file", us::Any(), true, false, false, mitkCommandLineParser::Output);
- parser.addArgument("class-number", "cn", mitkCommandLineParser::File, "Class-dependedn number of voxels ", "Output file", us::Any(), true, false, false, mitkCommandLineParser::Output);
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size() == 0)
- return EXIT_FAILURE;
-
- // Show a help message
- if (parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- if (parsedArgs.count("single-rate") + parsedArgs.count("class-rate") + parsedArgs.count("single-number") + parsedArgs.count("class-number") < 1)
- {
- std::cout << "Please specify the sampling rate or number of voxels to be labeled" << std::endl << std::endl;
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- if (parsedArgs.count("single-rate") + parsedArgs.count("class-rate") + parsedArgs.count("single-number") + parsedArgs.count("class-number") > 2)
- {
- std::cout << "Please specify only one way for the sampling rate or number of voxels to be labeled" << std::endl << std::endl;
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
-
- std::string inputName = us::any_cast<std::string>(parsedArgs["input"]);
- std::string outputName = us::any_cast<std::string>(parsedArgs["output"]);
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(inputName);
-
- mitk::RandomImageSampler::Pointer filter = mitk::RandomImageSampler::New();
- filter->SetInput(image);
-
- if (parsedArgs.count("single-rate"))
- {
- filter->SetSamplingMode(mitk::RandomImageSamplerMode::SINGLE_ACCEPTANCE_RATE);
- auto rate = splitDouble(parsedArgs["single-rate"].ToString(), ';');
- if (rate.size() != 1)
- {
- std::cout << "Please specify a single double value for single-rate, for example 0.3." << std::endl << std::endl;
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
- filter->SetAcceptanceRate(rate[0]);
- }
-
- else if (parsedArgs.count("class-rate"))
- {
- filter->SetSamplingMode(mitk::RandomImageSamplerMode::CLASS_DEPENDEND_ACCEPTANCE_RATE);
- auto rate = splitDouble(parsedArgs["class-rate"].ToString(), ';');
- if (rate.size() < 2)
- {
- std::cout << "Please specify at least two, semicolon separated values for class-rate, for example '0.3;0.2' ." << std::endl << std::endl;
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
- filter->SetAcceptanceRateVector(rate);
- }
-
- else if (parsedArgs.count("single-number"))
- {
- filter->SetSamplingMode(mitk::RandomImageSamplerMode::SINGLE_NUMBER_OF_ACCEPTANCE);
- auto rate = splitUInt(parsedArgs["single-number"].ToString(), ';');
- if (rate.size() != 1)
- {
- std::cout << "Please specify a single double value for single-number, for example 100." << std::endl << std::endl;
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
- filter->SetNumberOfSamples(rate[0]);
- }
-
- else if (parsedArgs.count("class-number"))
- {
- filter->SetSamplingMode(mitk::RandomImageSamplerMode::CLASS_DEPENDEND_NUMBER_OF_ACCEPTANCE);
- auto rate = splitUInt(parsedArgs["class-number"].ToString(), ';');
- if (rate.size() < 2)
- {
- std::cout << "Please specify at least two, semicolon separated values for class-number, for example '100;200' ." << std::endl << std::endl;
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
- filter->SetNumberOfSamplesVector(rate);
- }
- filter->Update();
- mitk::IOUtil::Save(filter->GetOutput(), outputName);
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLRemoveEmptyVoxels.cpp b/Modules/Classification/CLMiniApps/CLRemoveEmptyVoxels.cpp
deleted file mode 100644
index 653058d606..0000000000
--- a/Modules/Classification/CLMiniApps/CLRemoveEmptyVoxels.cpp
+++ /dev/null
@@ -1,155 +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 "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-#include "mitkImageCast.h"
-#include <itkImageRegionConstIterator.h>
-#include <itkImageRegionIterator.h>
-#include "mitkImageGenerator.h"
-
-int main(int argc, char* argv[])
-{
- typedef itk::Image<double, 3> ImageType;
- typedef itk::Image<unsigned char, 3> MaskImageType;
- typedef ImageType::Pointer ImagePointerType;
- typedef MaskImageType::Pointer MaskImagePointerType;
-
- typedef itk::ImageRegionConstIterator<ImageType> ConstIteratorType;
- typedef itk::ImageRegionConstIterator<MaskImageType> ConstMaskIteratorType;
- typedef itk::ImageRegionIterator<ImageType> IteratorType;
- typedef itk::ImageRegionIterator<MaskImageType> MaskIteratorType;
-
- mitkCommandLineParser parser;
-
- parser.setTitle("Remove empty voxels Sampling");
- parser.setCategory("Classification Command Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--", "-");
- // Add command line argument names
- parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("mask-input", "mi", mitkCommandLineParser::Directory, "Input file:", "Input file", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("mask-output", "mo", mitkCommandLineParser::File, "Output file:", "Output file", us::Any(), false, false, false, mitkCommandLineParser::Output);
-
- for (int i = 0; i < 100; ++i)
- {
- std::stringstream s1; s1 << i; std::string number = s1.str();
- parser.addArgument("input"+number, "i"+number, mitkCommandLineParser::File, "Input file", "input file", us::Any(), true, false, false, mitkCommandLineParser::Output);
- parser.addArgument("output" + number, "o" + number, mitkCommandLineParser::File, "Output File", "Output file", us::Any(), true, false, false, mitkCommandLineParser::Output);
- }
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size() == 0)
- return EXIT_FAILURE;
-
- // Show a help message
- if (parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- // Load Mask Image and count number of non-zero voxels
- mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(parsedArgs["mask-input"].ToString());
- MaskImagePointerType itkMask = MaskImageType::New();
- mitk::CastToItkImage(mask, itkMask);
- ConstMaskIteratorType maskIter(itkMask, itkMask->GetLargestPossibleRegion());
- std::size_t nonZero = 0;
- while (!maskIter.IsAtEnd())
- {
- if (maskIter.Value() > 0)
- {
- ++nonZero;
- }
- ++maskIter;
- }
- maskIter.GoToBegin();
-
- // Create new mask image
- auto mitkNewMask = mitk::ImageGenerator::GenerateGradientImage<unsigned char>(nonZero, 1, 1, 1, 1, 1);
- MaskImagePointerType itkNewMask = MaskImageType::New();
- mitk::CastToItkImage(mitkNewMask, itkNewMask);
- MaskIteratorType newMaskIter(itkNewMask, itkNewMask->GetLargestPossibleRegion());
-
- // Read additional image
- std::vector<mitk::Image::Pointer> mitkImagesVector;
- std::vector<ImagePointerType> itkImageVector;
- std::vector<ImagePointerType> itkOutputImageVector;
- std::vector<ConstIteratorType> inputIteratorVector;
- std::vector<IteratorType> outputIteratorVector;
- for (int i = 0; i < 100; ++i)
- {
- std::stringstream s1; s1 << i; std::string number = s1.str();
- if (parsedArgs.count("input" + number) < 1)
- break;
- if (parsedArgs.count("output" + number) < 1)
- break;
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(parsedArgs["input"+number].ToString());
- mitkImagesVector.push_back(image);
-
- ImagePointerType itkImage = ImageType::New();
- mitk::CastToItkImage(image, itkImage);
- itkImageVector.push_back(itkImage);
-
- ConstIteratorType iter(itkImage, itkImage->GetLargestPossibleRegion());
- inputIteratorVector.push_back(iter);
-
- auto mitkNewImage = mitk::ImageGenerator::GenerateGradientImage<double>(nonZero, 1, 1, 1, 1, 1);
- ImagePointerType itkNewOutput = ImageType::New();
- mitk::CastToItkImage(mitkNewImage, itkNewOutput);
- IteratorType outputIter(itkNewOutput, itkNewOutput->GetLargestPossibleRegion());
- itkOutputImageVector.push_back(itkNewOutput);
- outputIteratorVector.push_back(outputIter);
- }
-
- // Convert non-zero voxels to the new images
- while (!maskIter.IsAtEnd())
- {
- if (maskIter.Value() > 0)
- {
- newMaskIter.Set(maskIter.Value());
- ++newMaskIter;
- for (std::size_t i = 0; i < outputIteratorVector.size(); ++i)
- {
- outputIteratorVector[i].Set(inputIteratorVector[i].Value());
- ++(outputIteratorVector[i]);
- }
- }
- ++maskIter;
- for (std::size_t i = 0; i < inputIteratorVector.size(); ++i)
- {
- ++(inputIteratorVector[i]);
- }
-
- }
-
- // Save the new images
- for (std::size_t i = 0; i < outputIteratorVector.size(); ++i)
- {
- std::stringstream s1; s1 << i; std::string number = s1.str();
- mitk::Image::Pointer mitkImage = mitk::Image::New();
- mitk::CastToMitkImage(itkOutputImageVector[i], mitkImage);
- mitk::IOUtil::Save(mitkImage, parsedArgs["output" + number].ToString());
- }
- // Save the new mask
- {
- mitk::Image::Pointer mitkImage = mitk::Image::New();
- mitk::CastToMitkImage(itkNewMask, mitkImage);
- mitk::IOUtil::Save(mitkImage, parsedArgs["mask-output"].ToString());
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLResampleImageToReference.cpp b/Modules/Classification/CLMiniApps/CLResampleImageToReference.cpp
deleted file mode 100644
index 4bae1ca503..0000000000
--- a/Modules/Classification/CLMiniApps/CLResampleImageToReference.cpp
+++ /dev/null
@@ -1,134 +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.
-
-============================================================================*/
-#ifndef mitkCLResampleImageToReference_cpp
-#define mitkCLResampleImageToReference_cpp
-
-#include "mitkCommandLineParser.h"
-#include <mitkImageAccessByItk.h>
-#include <mitkIOUtil.h>
-#include <mitkImage.h>
-#include <mitkImageCast.h>
-#include <mitkITKImageImport.h>
-#include <mitkImageTimeSelector.h>
-
-// ITK
-#include "itkLinearInterpolateImageFunction.h"
-#include "itkWindowedSincInterpolateImageFunction.h"
-#include "itkNearestNeighborInterpolateImageFunction.h"
-#include "itkIdentityTransform.h"
-#include "itkResampleImageFilter.h"
-
-
-template<typename TPixel, unsigned int VImageDimension>
-void
-ResampleImageToReferenceFunction(itk::Image<TPixel, VImageDimension>* itkReference, mitk::Image::Pointer moving, std::string ergPath, int interp=0)
-{
- typedef itk::Image<TPixel, VImageDimension> InputImageType;
-
- // Identify Transform
- typedef itk::IdentityTransform<double, VImageDimension> T_Transform;
- typename T_Transform::Pointer _pTransform = T_Transform::New();
- _pTransform->SetIdentity();
-
- typedef itk::WindowedSincInterpolateImageFunction< InputImageType, VImageDimension> WindowedSincInterpolatorType;
- typename WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New();
-
- typedef itk::LinearInterpolateImageFunction< InputImageType> LinearInterpolateImageFunctionType;
- typename LinearInterpolateImageFunctionType::Pointer lin_interpolator = LinearInterpolateImageFunctionType::New();
-
- typedef itk::NearestNeighborInterpolateImageFunction< InputImageType> NearestNeighborInterpolateImageFunctionType;
- typename NearestNeighborInterpolateImageFunctionType::Pointer nn_interpolator = NearestNeighborInterpolateImageFunctionType::New();
-
- typename InputImageType::Pointer itkMoving = InputImageType::New();
- mitk::CastToItkImage(moving,itkMoving);
- typedef itk::ResampleImageFilter<InputImageType, InputImageType> ResampleFilterType;
-
- typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
- resampler->SetInput(itkMoving);
- resampler->SetReferenceImage( itkReference );
- resampler->UseReferenceImageOn();
- resampler->SetTransform(_pTransform);
-
- switch(interp)
- {
- case 0:
- {
- resampler->SetInterpolator(lin_interpolator);
- break;
- }
- case 1:
- {
- resampler->SetInterpolator(nn_interpolator);
- break;
- }
- case 2:
- {
- resampler->SetInterpolator(sinc_interpolator);
- break;
- }
- default:
- resampler->SetInterpolator(lin_interpolator);
- }
-
- resampler->Update();
-
- // Convert back to mitk
- mitk::Image::Pointer result = mitk::Image::New();
- result->InitializeByItk(resampler->GetOutput());
- GrabItkImageMemory(resampler->GetOutput(), result);
- MITK_INFO << "writing result to: " << ergPath;
- mitk::IOUtil::Save(result, ergPath);
- //return result;
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("fix", "f", mitkCommandLineParser::Image, "Fixed Image", "fixed image file", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("moving", "m", mitkCommandLineParser::File, "Moving Image", "moving image file", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output Image", "output image", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("interpolator", "", mitkCommandLineParser::Int, "Interpolator:", "interpolator type: 0=linear (default), 1=nearest neighbor, 2=sinc", 0);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Resample Image To Reference");
- parser.setDescription("Resamples an image (moving) to an given image (fix) without additional registration.");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size() == 0)
- {
- return EXIT_FAILURE;
- }
- if (parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- mitk::Image::Pointer fix = mitk::IOUtil::Load<mitk::Image>(parsedArgs["fix"].ToString());
- mitk::Image::Pointer moving = mitk::IOUtil::Load<mitk::Image>(parsedArgs["moving"].ToString());
- mitk::Image::Pointer erg = mitk::Image::New();
-
- int interpolator = 0;
- if (parsedArgs.count("interpolator"))
- interpolator = us::any_cast<int>(parsedArgs["interpolator"]);
-
- AccessByItk_3(fix, ResampleImageToReferenceFunction, moving, parsedArgs["output"].ToString(), interpolator);
-
-}
-
-
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLScreenshot.cpp b/Modules/Classification/CLMiniApps/CLScreenshot.cpp
index 439d62b1c5..ad7532da5b 100644
--- a/Modules/Classification/CLMiniApps/CLScreenshot.cpp
+++ b/Modules/Classification/CLMiniApps/CLScreenshot.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.
============================================================================*/
#ifndef mitkCLPolyToNrrd_cpp
#define mitkCLPolyToNrrd_cpp
#include "time.h"
#include <sstream>
#include <fstream>
#include <mitkIOUtil.h>
#include "mitkCommandLineParser.h"
#include <mitkSplitParameterToVector.h>
#include <mitkProperties.h>
#include <QApplication>
#include <mitkStandaloneDataStorage.h>
#include "QmitkRegisterClasses.h"
#include "QmitkRenderWindow.h"
#include "vtkRenderLargeImage.h"
#include "vtkPNGWriter.h"
static
void SaveSliceOrImageAsPNG(std::vector<std::string> listOfOutputs, std::string path)
{
std::vector<mitk::ColorProperty::Pointer> colorList;
colorList.push_back(mitk::ColorProperty::New(0.9569, 0.16471, 0.25490)); // Red
colorList.push_back(mitk::ColorProperty::New(1, 0.839, 0)); // Yellow
colorList.push_back(mitk::ColorProperty::New(0, 0.6, 0.2)); // Green
colorList.push_back(mitk::ColorProperty::New(0, 0.2784, 0.7255)); // BLue
colorList.push_back(mitk::ColorProperty::New(1,0.3608,0)); // Orange
colorList.push_back(mitk::ColorProperty::New(0.839215,0.141176,0.80784)); // Violett
colorList.push_back(mitk::ColorProperty::New(0.1372,0.81568,0.7647)); // Turkis
colorList.push_back(mitk::ColorProperty::New(0.61176,0.9568,0.16078)); // Bright Green
colorList.push_back(mitk::ColorProperty::New(1,0.4274,0.16862)); // Dark Orange
colorList.push_back(mitk::ColorProperty::New(0.88633,0.14901,0.64705)); // Pink
// Create a Standalone Datastorage for the single purpose of saving screenshots..
mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New();
QmitkRenderWindow renderWindow;
renderWindow.GetRenderer()->SetDataStorage(ds);
int numberOfSegmentations = 0;
bool isSegmentation = false;
for (auto name : listOfOutputs)
{
mitk::Image::Pointer tmpImage = mitk::IOUtil::Load<mitk::Image>(name);
auto nodeI = mitk::DataNode::New();
nodeI->SetData(tmpImage);
nodeI->GetPropertyValue("binary",isSegmentation);
if (isSegmentation)
{
nodeI->SetProperty("color", colorList[numberOfSegmentations % colorList.size()]);
nodeI->SetProperty("binaryimage.hoveringannotationcolor", colorList[numberOfSegmentations % colorList.size()]);
nodeI->SetProperty("binaryimage.hoveringcolor", colorList[numberOfSegmentations % colorList.size()]);
nodeI->SetProperty("binaryimage.selectedannotationcolor", colorList[numberOfSegmentations % colorList.size()]);
nodeI->SetProperty("binaryimage.selectedcolor", colorList[numberOfSegmentations % colorList.size()]);
numberOfSegmentations++;
}
ds->Add(nodeI);
}
auto geo = ds->ComputeBoundingGeometry3D(ds->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(geo);
mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController();
unsigned int numberOfSteps = 1;
if (sliceNaviController)
{
- numberOfSteps = sliceNaviController->GetSlice()->GetSteps();
- sliceNaviController->GetSlice()->SetPos(0);
+ numberOfSteps = sliceNaviController->GetStepper()->GetSteps();
+ sliceNaviController->GetStepper()->SetPos(0);
}
renderWindow.show();
renderWindow.resize(512, 512);
for (unsigned int currentStep = 0; currentStep < numberOfSteps; ++currentStep)
{
if (sliceNaviController)
{
- sliceNaviController->GetSlice()->SetPos(currentStep);
+ sliceNaviController->GetStepper()->SetPos(currentStep);
}
renderWindow.GetRenderer()->PrepareRender();
vtkRenderWindow* renderWindow2 = renderWindow.GetVtkRenderWindow();
mitk::BaseRenderer* baserenderer = mitk::BaseRenderer::GetInstance(renderWindow2);
auto vtkRender = baserenderer->GetVtkRenderer();
vtkRender->GetRenderWindow()->WaitForCompletion();
vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New();
magnifier->SetInput(vtkRender);
magnifier->SetMagnification(3.0);
std::stringstream ss;
ss << path << "screenshot_step-"<<currentStep<<".png";
std::string tmpImageName;
ss >> tmpImageName;
auto fileWriter = vtkPNGWriter::New();
fileWriter->SetInputConnection(magnifier->GetOutputPort());
fileWriter->SetFileName(tmpImageName.c_str());
fileWriter->Write();
fileWriter->Delete();
}
}
int main(int argc, char* argv[])
{
mitkCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
// Required Parameter
parser.addArgument("image", "i", mitkCommandLineParser::Image, "Input Image", "Path to the input image files (Separated with semicolons)", us::Any(), false, false, false, mitkCommandLineParser::Input);
parser.addArgument("output", "o", mitkCommandLineParser::File, "Output text file", "Path to output file. The output statistic is appended to this file.", us::Any(), false, false, false, mitkCommandLineParser::Output);
parser.addArgument("direction", "dir", mitkCommandLineParser::String, "Int", "Allows to specify the direction for Cooc and RL. 0: All directions, 1: Only single direction (Test purpose), 2,3,4... Without dimension 0,1,2... ", us::Any());
// Miniapp Infos
parser.setCategory("Classification Tools");
parser.setTitle("Screenshot of a single image");
parser.setDescription("");
parser.setContributor("German Cancer Research Center (DKFZ)");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
{
return EXIT_FAILURE;
}
if ( parsedArgs.count("help") || parsedArgs.count("h"))
{
return EXIT_SUCCESS;
}
std::string version = "Version: 1.0";
MITK_INFO << version;
//int direction = 0;
if (parsedArgs.count("direction"))
{
MITK_INFO << "Warning: Option direction currently not supported";
// direction = mitk::cl::splitDouble(parsedArgs["direction"].ToString(), ';')[0];
}
auto listOfFiles = mitk::cl::splitString(parsedArgs["image"].ToString(), ';');
// Create a QTApplication and a Datastorage
// This is necessary in order to save screenshots of
// each image / slice.
QApplication qtapplication(argc, argv);
QmitkRegisterClasses();
SaveSliceOrImageAsPNG(listOfFiles, parsedArgs["output"].ToString());
return 0;
}
#endif
diff --git a/Modules/Classification/CLMiniApps/CLSimpleVoxelClassification.cpp b/Modules/Classification/CLMiniApps/CLSimpleVoxelClassification.cpp
deleted file mode 100644
index 4254e0f7fd..0000000000
--- a/Modules/Classification/CLMiniApps/CLSimpleVoxelClassification.cpp
+++ /dev/null
@@ -1,219 +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 <sstream>
-
-#include <mitkConfigFileReader.h>
-#include <mitkDataCollection.h>
-#include <mitkCollectionReader.h>
-#include <mitkCollectionWriter.h>
-#include <mitkCollectionStatistic.h>
-#include <mitkCostingStatistic.h>
-#include <vtkSmartPointer.h>
-#include <mitkIOUtil.h>
-
-#include <mitkDataCollectionUtilities.h>
-#include <mitkRandomForestIO.h>
-#include <mitkVigraRandomForestClassifier.h>
-
-// CTK
-#include "mitkCommandLineParser.h"
-
-
-
-
-int main(int argc, char* argv[])
-{
- // Setup CLI Module parsable interface
- mitkCommandLineParser parser;
- parser.setTitle("Simple Random Forest Classifier");
- parser.setCategory("Classification");
- parser.setDescription("Learns and predicts classes");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("--", "-");
- // Add command line argument names
- parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Show options");
- parser.addArgument("loadFile", "l", mitkCommandLineParser::File,
- "DataCollection File", "", us::Any(), true, false, false, mitkCommandLineParser::Input);
- parser.addArgument(
- "colIds", "c", mitkCommandLineParser::String,
- "Patient Identifiers from DataCollection used for training");
- parser.addArgument("testId", "t", mitkCommandLineParser::String,
- "Patient Identifier from DataCollection used for testing");
- parser.addArgument("features", "b", mitkCommandLineParser::String,
- "Features");
- parser.addArgument("stats", "s", mitkCommandLineParser::String,
- "Output file for stats");
- parser.addArgument("treeDepth", "d", mitkCommandLineParser::Int,
- "limits tree depth");
- parser.addArgument("forestSize", "f", mitkCommandLineParser::Int,
- "number of trees");
- parser.addArgument("configName", "n", mitkCommandLineParser::String,
- "human readable name for configuration");
- parser.addArgument("output", "o", mitkCommandLineParser::Directory,
- "output folder for results", "", us::Any(), true, false, false, mitkCommandLineParser::Input);
-
- parser.addArgument("classmap", "m", mitkCommandLineParser::String,
- "name of class that is to be learnt");
-
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
- // Show a help message
- if (parsedArgs.size()==0 || parsedArgs.count("help") || parsedArgs.count("h")) {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- // Default values
- unsigned int forestSize = 8;
- unsigned int treeDepth = 10;
- std::string configName = "";
- std::string outputFolder = "";
-
- std::vector<std::string> features;
- std::vector<std::string> trainingIds;
- std::vector<std::string> testingIds;
- std::vector<std::string> loadIds; // features + masks needed for training and evaluation
- std::string outputFile;
- std::string classMap;
- std::string xmlFile;
- std::ofstream experimentFS;
-
- // Parse input parameters
- {
- if (parsedArgs.count("colIds") || parsedArgs.count("c")) {
- std::istringstream ss(us::any_cast<std::string>(parsedArgs["colIds"]));
- std::string token;
-
- while (std::getline(ss, token, ','))
- trainingIds.push_back(token);
- }
-
- if (parsedArgs.count("output") || parsedArgs.count("o")) {
- outputFolder = us::any_cast<std::string>(parsedArgs["output"]);
- }
-
- if (parsedArgs.count("classmap") || parsedArgs.count("m")) {
- classMap = us::any_cast<std::string>(parsedArgs["classmap"]);
- }
-
- if (parsedArgs.count("configName") || parsedArgs.count("n")) {
- configName = us::any_cast<std::string>(parsedArgs["configName"]);
- }
-
- if (parsedArgs.count("features") || parsedArgs.count("b")) {
- std::istringstream ss(us::any_cast<std::string>(parsedArgs["features"]));
- std::string token;
-
- while (std::getline(ss, token, ','))
- features.push_back(token);
- }
-
- if (parsedArgs.count("treeDepth") || parsedArgs.count("d")) {
- treeDepth = us::any_cast<int>(parsedArgs["treeDepth"]);
- }
-
-
- if (parsedArgs.count("forestSize") || parsedArgs.count("f")) {
- forestSize = us::any_cast<int>(parsedArgs["forestSize"]);
- }
-
- if (parsedArgs.count("stats") || parsedArgs.count("s")) {
- experimentFS.open(us::any_cast<std::string>(parsedArgs["stats"]).c_str(),
- std::ios_base::app);
- }
-
-
- if (parsedArgs.count("testId") || parsedArgs.count("t")) {
- std::istringstream ss(us::any_cast<std::string>(parsedArgs["testId"]));
- std::string token;
-
- while (std::getline(ss, token, ','))
- testingIds.push_back(token);
- }
-
- for (unsigned int i = 0; i < features.size(); i++) {
- loadIds.push_back(features.at(i));
- }
- loadIds.push_back(classMap);
-
- if (parsedArgs.count("stats") || parsedArgs.count("s")) {
- outputFile = us::any_cast<std::string>(parsedArgs["stats"]);
- }
-
- if (parsedArgs.count("loadFile") || parsedArgs.count("l")) {
- xmlFile = us::any_cast<std::string>(parsedArgs["loadFile"]);
- } else {
- MITK_ERROR << parser.helpText();
- return EXIT_FAILURE;
- }
- }
-
- mitk::DataCollection::Pointer trainCollection;
- mitk::DataCollection::Pointer testCollection;
- {
- mitk::CollectionReader colReader;
- // Load only relevant images
- colReader.SetDataItemNames(loadIds);
- colReader.AddSubColIds(testingIds);
- testCollection = colReader.LoadCollection(xmlFile);
- colReader.ClearDataElementIds();
- colReader.ClearSubColIds();
- colReader.SetDataItemNames(loadIds);
- colReader.AddSubColIds(trainingIds);
- trainCollection = colReader.LoadCollection(xmlFile);
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // If required do Training....
- //////////////////////////////////////////////////////////////////////////////
- //mitk::DecisionForest forest;
-
- mitk::VigraRandomForestClassifier::Pointer forest = mitk::VigraRandomForestClassifier::New();
-
- forest->SetTreeCount(forestSize);
- forest->SetMaximumTreeDepth(treeDepth);
-
-
- // create feature matrix
- auto trainDataX = mitk::DCUtilities::DC3dDToMatrixXd(trainCollection, features, classMap);
- // create label matrix
- auto trainDataY = mitk::DCUtilities::DC3dDToMatrixXi(trainCollection, classMap, classMap);
-
- forest->Train(trainDataX, trainDataY);
-
-
- // prepare feature matrix for test case
- auto testDataX = mitk::DCUtilities::DC3dDToMatrixXd(testCollection,features, classMap);
- auto testDataNewY = forest->Predict(testDataX);
-
-
- mitk::DCUtilities::MatrixToDC3d(testDataNewY, testCollection, "RESULT", classMap);
-
- Eigen::MatrixXd Probs = forest->GetPointWiseProbabilities();
-
-
- Eigen::MatrixXd prob0 = Probs.col(0);
- Eigen::MatrixXd prob1 = Probs.col(1);
-
- mitk::DCUtilities::MatrixToDC3d(prob0, testCollection,"prob0", classMap);
- mitk::DCUtilities::MatrixToDC3d(prob1, testCollection,"prob1", classMap);
-
-
- std::vector<std::string> outputFilter;
- mitk::CollectionWriter::ExportCollectionToFolder(testCollection,
- outputFolder + "/result_collection.xml",
- outputFilter);
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLSkullMask.cpp b/Modules/Classification/CLMiniApps/CLSkullMask.cpp
deleted file mode 100644
index cd532d77ec..0000000000
--- a/Modules/Classification/CLMiniApps/CLSkullMask.cpp
+++ /dev/null
@@ -1,194 +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.
-
-============================================================================*/
-#ifndef mitkCLPolyToNrrd_cpp
-#define mitkCLPolyToNrrd_cpp
-
-#include "time.h"
-#include <sstream>
-#include <fstream>
-
-#include <mitkIOUtil.h>
-#include "mitkCommandLineParser.h"
-
-#include "itkImageRegionIterator.h"
-// MITK
-#include <mitkITKImageImport.h>
-#include <mitkImageCast.h>
-#include <mitkImageAccessByItk.h>
-// ITK
-#include <itkLabelStatisticsImageFilter.h>
-#include <itkMinimumMaximumImageCalculator.h>
-
-typedef itk::Image< double, 3 > FloatImageType;
-typedef itk::Image< unsigned char, 3 > MaskImageType;
-
-template<typename TPixel, unsigned int VImageDimension>
-static void
- DetectSkull(itk::Image<TPixel, VImageDimension>* itkImage, mitk::Image::Pointer im2, mitk::Image::Pointer mask1, std::string output)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::Image<unsigned char, VImageDimension> MaskType;
-
- typename ImageType::Pointer itkIm2 = ImageType::New();
- typename MaskType::Pointer itkMask1 = MaskType::New();
- mitk::CastToItkImage(im2, itkIm2);
- mitk::CastToItkImage(mask1, itkMask1);
-
- itk::ImageRegionIterator<ImageType> iterI1(itkImage, itkImage->GetLargestPossibleRegion());
- itk::ImageRegionIterator<ImageType> iterI2(itkIm2, itkImage->GetLargestPossibleRegion());
- itk::ImageRegionIterator<MaskType> iter(itkMask1, itkImage->GetLargestPossibleRegion());
- while (! iter.IsAtEnd())
- {
- unsigned char maskV = 0;
- if (iterI1.Value() > 0.0001 && iterI2.Value() > 0.00001)
- maskV = 1;
- iter.Set(maskV);
- ++iter;
- ++iterI1;
- ++iterI2;
- }
-
- mitk::Image::Pointer img = mitk::ImportItkImage(itkMask1);
- mitk::IOUtil::Save(img, output);
-}
-
-int main(int argc, char* argv[])
-{
- typedef itk::Image<double, 3> ImageType;
- typedef itk::Image<unsigned short, 3> MaskType;
-
-
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("image", "i", mitkCommandLineParser::StringList, "Input Image", "Path to the input images. Mask covers area of all images", us::Any(), false);
- parser.addArgument("mask", "m", mitkCommandLineParser::Image, "Input Mask", "The median of the area covered by this mask will be set to 1", us::Any(), false, false, false, mitkCommandLineParser::Input);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("MR Normalization Tool");
- parser.setDescription("Normalizes a MR image. Sets the Median of the tissue covered by mask 0 to 0 and the median of the area covered by mask 1 to 1.");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
- us::Any listAny = parsedArgs["image"];
- auto inputImageList = us::any_cast<mitkCommandLineParser::StringContainerType>(listAny);
-
- std::vector<ImageType::Pointer> imageList;
- for (std::size_t i = 0; i < inputImageList.size(); ++i)
- {
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(inputImageList[i]);
- ImageType::Pointer itkImage = ImageType::New();
- mitk::CastToItkImage(image, itkImage);
- imageList.push_back(itkImage);
- }
- mitk::Image::Pointer mitkMask = mitk::IOUtil::Load<mitk::Image>(inputImageList[0]);
- MaskType::Pointer mask = MaskType::New();
- mitk::CastToItkImage(mitkMask, mask);
-
- itk::ImageRegionIterator<MaskType> maskIter(mask, mask->GetLargestPossibleRegion());
- while (!maskIter.IsAtEnd())
- {
- maskIter.Set(0);
- ++maskIter;
- }
-
- std::vector<ImageType::IndexType> listOfIndexes;
- listOfIndexes.reserve(1000);
-
- // Find Start Location for the case that one corner is "blocked" by content. Works only on the first image!
- ImageType::IndexType tmpIndex;
- ImageType::IndexType startIndex;
- startIndex.Fill(0);
- for (unsigned char i = 0; i < 8; ++i)
- {
- tmpIndex.Fill(0);
- if ((i & 1) > 0) tmpIndex[0] = mask->GetLargestPossibleRegion().GetSize(0)-1;
- if ((i & 2) > 0) tmpIndex[1] = mask->GetLargestPossibleRegion().GetSize(1)-1;
- if ((i & 4) > 0) tmpIndex[2] = mask->GetLargestPossibleRegion().GetSize(2)-1;
-
- MITK_INFO << tmpIndex;
- if (imageList[0]->GetPixel(tmpIndex) < imageList[0]->GetPixel(startIndex))
- {
- startIndex = tmpIndex;
- }
- }
- listOfIndexes.push_back(tmpIndex);
-
- while (listOfIndexes.size() > 0)
- {
- ImageType::IndexType currentIndex = listOfIndexes.back();
- listOfIndexes.pop_back();
- if (!(mask->GetLargestPossibleRegion().IsInside(currentIndex)))
- {
- continue;
- }
- if (mask->GetPixel(currentIndex) == 0)
- {
- mask->SetPixel(currentIndex, 1);
- double minimum = std::numeric_limits<double>::max();
- for (std::size_t i = 0; i < imageList.size(); ++i)
- {
- minimum = std::min<double>(minimum, imageList[i]->GetPixel(currentIndex));
- }
- if (minimum < 35)
- {
- mask->SetPixel(currentIndex, 2);
- tmpIndex = currentIndex;
- tmpIndex[0] += 1;
- listOfIndexes.push_back(tmpIndex);
- tmpIndex[0] -= 2;
- listOfIndexes.push_back(tmpIndex);
- tmpIndex[0] += 1;
- tmpIndex[1] += 1;
- listOfIndexes.push_back(tmpIndex);
- tmpIndex[1] -= 2;
- listOfIndexes.push_back(tmpIndex);
- tmpIndex[1] += 1;
- tmpIndex[2] += 1;
- listOfIndexes.push_back(tmpIndex);
- tmpIndex[2] -= 2;
- listOfIndexes.push_back(tmpIndex);
- }
- }
- }
- MITK_INFO << "Im here";
- maskIter.GoToBegin();
- while (!maskIter.IsAtEnd())
- {
- if (maskIter.Get() == 2)
- maskIter.Set(0);
- else
- maskIter.Set(1);
- ++maskIter;
- }
-
- mitk::Image::Pointer ergMask = mitk::ImportItkImage(mask);
-
- std::string maskPath = parsedArgs["mask"].ToString();
- mitk::IOUtil::Save(ergMask, maskPath);
-
- //AccessByItk_3(image, Normalize, im2, mask, parsedArgs["output"].ToString());
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLStaple.cpp b/Modules/Classification/CLMiniApps/CLStaple.cpp
deleted file mode 100644
index ad4a5dea1d..0000000000
--- a/Modules/Classification/CLMiniApps/CLStaple.cpp
+++ /dev/null
@@ -1,42 +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 "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-#include <mitkImageCast.h>
-
-#include <itkSTAPLEImageFilter.h>
-
-int main(int argc, char* argv[])
-{
- typedef itk::Image<unsigned char, 3> MaskImageType;
- typedef itk::Image<float, 3> ImageType;
- typedef itk::STAPLEImageFilter<MaskImageType, ImageType> FilterType;
-
- FilterType::Pointer filter = FilterType::New();
- filter->SetForegroundValue(2);
- for (int i = 2; i < argc; ++i)
- {
- MITK_INFO << argv[i];
- MaskImageType::Pointer itkImg = MaskImageType::New();
- mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(argv[i]);
- mitk::CastToItkImage(img,itkImg);
- filter->SetInput(i-2, itkImg);
- }
- filter->Update();
- auto out = filter->GetOutput();
- mitk::Image::Pointer outImg = mitk::Image::New();
- mitk::CastToMitkImage(out, outImg);
- mitk::IOUtil::Save(outImg, argv[1]);
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/CLSurWeighting.cpp b/Modules/Classification/CLMiniApps/CLSurWeighting.cpp
deleted file mode 100644
index df0ddf1b8c..0000000000
--- a/Modules/Classification/CLMiniApps/CLSurWeighting.cpp
+++ /dev/null
@@ -1,69 +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.
-
-============================================================================*/
-#ifndef mitkForest_cpp
-#define mitkForest_cpp
-
-#include "time.h"
-#include <sstream>
-
-#include <mitkDataCollection.h>
-#include <mitkCollectionReader.h>
-#include <mitkCollectionWriter.h>
-#include <mitkCollectionStatistic.h>
-#include <vtkSmartPointer.h>
-#include <mitkIOUtil.h>
-#include <sstream>
-
-#include <mitkLRDensityEstimation.h>
-
-int main(int argc, char* argv[])
-{
- MITK_INFO << "Argc " << argc;
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Images
- //////////////////////////////////////////////////////////////////////////////
- mitk::DataCollection::Pointer col = mitk::DataCollection::New();
-
- MITK_INFO << "Arg 2 " << argv[2];
- mitk::Image::Pointer sur=mitk::IOUtil::Load<mitk::Image>(argv[2]);
- col->AddData(sur.GetPointer(),"sur");
- MITK_INFO << "Arg 3 " << argv[3];
- mitk::Image::Pointer mask=mitk::IOUtil::Load<mitk::Image>(argv[3]);
- col->AddData(mask.GetPointer(),"mask");
-
- std::vector<std::string> modalities;
- for (int i = 4; i < argc; ++i)
- {
- MITK_INFO << "Img " << argv[i];
- std::stringstream ss;
- ss << i;
- modalities.push_back(ss.str());
- mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(argv[i]);
- col->AddData(img.GetPointer(),ss.str());
- }
-
- mitk::LRDensityEstimation est;
- est.SetCollection(col);
- est.SetTrainMask("sur");
- est.SetTestMask("mask");
- est.SetModalities(modalities);
- est.SetWeightName("weight");
- est.Update();
-
- mitk::Image::Pointer w= col->GetMitkImage("weight");
- mitk::IOUtil::Save(w,argv[1]);
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLVoxelClassification.cpp b/Modules/Classification/CLMiniApps/CLVoxelClassification.cpp
deleted file mode 100644
index 6d8aef5230..0000000000
--- a/Modules/Classification/CLMiniApps/CLVoxelClassification.cpp
+++ /dev/null
@@ -1,476 +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.
-
-============================================================================*/
-#ifndef mitkForest_cpp
-#define mitkForest_cpp
-
-#include "time.h"
-#include <sstream>
-
-#include <mitkConfigFileReader.h>
-#include <mitkDataCollection.h>
-#include <mitkCollectionReader.h>
-#include <mitkCollectionWriter.h>
-#include <mitkCollectionStatistic.h>
-#include <mitkCostingStatistic.h>
-#include <vtkSmartPointer.h>
-#include <mitkIOUtil.h>
-
-#include <mitkDataCollectionUtilities.h>
-#include <mitkRandomForestIO.h>
-
-// ----------------------- Forest Handling ----------------------
-//#include <mitkDecisionForest.h>
-#include <mitkVigraRandomForestClassifier.h>
-//#include <mitkThresholdSplit.h>
-//#include <mitkImpurityLoss.h>
-//#include <mitkLinearSplitting.h>
-//#include <mitkVigraConverter.h>
-// ----------------------- Point weighting ----------------------
-//#include <mitkForestWeighting.h>
-//#include <mitkKliepDensityEstimation.h>
-//#include <mitkExternalWeighting.h>
-#include <mitkLRDensityEstimation.h>
-//#include <mitkKNNDensityEstimation.h>
-//#include <mitkZadroznyWeighting.h>
-//#include <mitkSpectralDensityEstimation.h>
-//#include <mitkULSIFDensityEstimation.h>
-
-int main(int argc, char* argv[])
-{
- MITK_INFO << "Starting MITK_Forest Mini-App";
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Console Input Parameter
- //////////////////////////////////////////////////////////////////////////////
- ConfigFileReader allConfig(argv[1]);
-
- bool readFile = true;
- std::stringstream ss;
- for (int i = 0; i < argc; ++i )
- {
- MITK_INFO << "-----"<< argv[i]<<"------";
- if (readFile)
- {
- if (argv[i][0] == '+')
- {
- readFile = false;
- continue;
- } else
- {
- try
- {
- allConfig.ReadFile(argv[i]);
- }
- catch ( const std::exception &e )
- {
- MITK_INFO << e.what();
- }
- }
- }
- else
- {
- std::string input = argv[i];
- std::replace(input.begin(), input.end(),'_',' ');
- ss << input << std::endl;
- }
- }
- allConfig.ReadStream(ss);
-
- try
- {
- //////////////////////////////////////////////////////////////////////////////
- // General
- //////////////////////////////////////////////////////////////////////////////
- int currentRun = allConfig.IntValue("General","Run",0);
- int doTraining = allConfig.IntValue("General","Do Training",1);
- std::string forestPath = allConfig.Value("General","Forest Path");
- std::string trainingCollectionPath = allConfig.Value("General","Patient Collection");
- std::string testCollectionPath = allConfig.Value("General", "Patient Test Collection", trainingCollectionPath);
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Default Classification
- //////////////////////////////////////////////////////////////////////////////
- std::vector<std::string> trainPatients = allConfig.Vector("Training Group",currentRun);
- std::vector<std::string> testPatients = allConfig.Vector("Test Group",currentRun);
- std::vector<std::string> modalities = allConfig.Vector("Modalities", 0);
- std::vector<std::string> outputFilter = allConfig.Vector("Output Filter", 0);
- std::string trainMask = allConfig.Value("Data","Training Mask");
- std::string completeTrainMask = allConfig.Value("Data","Complete Training Mask");
- std::string testMask = allConfig.Value("Data","Test Mask");
- std::string resultMask = allConfig.Value("Data", "Result Mask");
- std::string resultProb = allConfig.Value("Data", "Result Propability");
- std::string outputFolder = allConfig.Value("General","Output Folder");
-
- std::string writeDataFilePath = allConfig.Value("Forest","File to write data to");
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Data Forest Parameter
- //////////////////////////////////////////////////////////////////////////////
- int testSingleDataset = allConfig.IntValue("Data", "Test Single Dataset",0);
- std::string singleDatasetName = allConfig.Value("Data", "Single Dataset Name", "none");
- int trainSingleDataset = allConfig.IntValue("Data", "Train Single Dataset", 0);
- std::string singleTrainDatasetName = allConfig.Value("Data", "Train Single Dataset Name", "none");
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Forest Parameter
- //////////////////////////////////////////////////////////////////////////////
- int minimumSplitNodeSize = allConfig.IntValue("Forest", "Minimum split node size",1);
- int numberOfTrees = allConfig.IntValue("Forest", "Number of Trees",255);
- double samplesPerTree = atof(allConfig.Value("Forest", "Samples per Tree").c_str());
- if (samplesPerTree <= 0.0000001)
- {
- samplesPerTree = 1.0;
- }
- MITK_INFO << "Samples per Tree: " << samplesPerTree;
- int sampleWithReplacement = allConfig.IntValue("Forest", "Sample with replacement",1);
- double trainPrecision = atof(allConfig.Value("Forest", "Precision").c_str());
- if (trainPrecision <= 0.0000000001)
- {
- trainPrecision = 0.0;
- }
- double weightLambda = atof(allConfig.Value("Forest", "Weight Lambda").c_str());
- if (weightLambda <= 0.0000000001)
- {
- weightLambda = 0.0;
- }
- int maximumTreeDepth = allConfig.IntValue("Forest", "Maximum Tree Depth",10000);
- // TODO int randomSplit = allConfig.IntValue("Forest","Use RandomSplit",0);
- //////////////////////////////////////////////////////////////////////////////
- // Read Statistic Parameter
- //////////////////////////////////////////////////////////////////////////////
- std::string statisticFilePath = allConfig.Value("Evaluation", "Statistic output file");
- std::string statisticShortFilePath = allConfig.Value("Evaluation", "Statistic short output file");
- std::string statisticShortFileLabel = allConfig.Value("Evaluation", "Index for short file");
- std::string statisticGoldStandard = allConfig.Value("Evaluation", "Gold Standard Name","GTV");
- // TODO bool statisticWithHeader = allConfig.IntValue("Evaluation", "Write header in short file",0);
- std::vector<std::string> labelGroupA = allConfig.Vector("LabelsA",0);
- std::vector<std::string> labelGroupB = allConfig.Vector("LabelsB",0);
- //////////////////////////////////////////////////////////////////////////////
- // Read Special Parameter
- //////////////////////////////////////////////////////////////////////////////
- bool useWeightedPoints = allConfig.IntValue("Forest", "Use point-based weighting",0);
- // TODO bool writePointsToFile = allConfig.IntValue("Forest", "Write points to file",0);
- // TODO int importanceWeightAlgorithm = allConfig.IntValue("Forest","Importance weight Algorithm",0);
- std::string importanceWeightName = allConfig.Value("Forest","Importance weight name","");
-
- std::ofstream timingFile;
- timingFile.open((statisticFilePath + ".timing").c_str(), std::ios::app);
- timingFile << statisticShortFileLabel << ";";
- std::time_t lastTimePoint;
- time(&lastTimePoint);
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Images
- //////////////////////////////////////////////////////////////////////////////
- std::vector<std::string> usedModalities;
- for (std::size_t i = 0; i < modalities.size(); ++i)
- {
- usedModalities.push_back(modalities[i]);
- }
- usedModalities.push_back(trainMask);
- usedModalities.push_back(completeTrainMask);
- usedModalities.push_back(testMask);
- usedModalities.push_back(statisticGoldStandard);
- usedModalities.push_back(importanceWeightName);
-
- if (trainSingleDataset > 0)
- {
- trainPatients.clear();
- trainPatients.push_back(singleTrainDatasetName);
- }
-
- mitk::CollectionReader* colReader = new mitk::CollectionReader();
- colReader->AddDataElementIds(trainPatients);
- colReader->SetDataItemNames(usedModalities);
- //colReader->SetNames(usedModalities);
- mitk::DataCollection::Pointer trainCollection;
- if (doTraining)
- {
- trainCollection = colReader->LoadCollection(trainingCollectionPath);
- }
-
- if (testSingleDataset > 0)
- {
- testPatients.clear();
- testPatients.push_back(singleDatasetName);
- }
- colReader->ClearDataElementIds();
- colReader->AddDataElementIds(testPatients);
- mitk::DataCollection::Pointer testCollection = colReader->LoadCollection(testCollectionPath);
-
- std::time_t now;
- time(&now);
- double seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << ";";
- time(&lastTimePoint);
-
- /*
- if (writePointsToFile)
- {
- MITK_INFO << "Use external weights...";
- mitk::ExternalWeighting weightReader;
- weightReader.SetModalities(modalities);
- weightReader.SetTestCollection(testCollection);
- weightReader.SetTrainCollection(trainCollection);
- weightReader.SetTestMask(testMask);
- weightReader.SetTrainMask(trainMask);
- weightReader.SetWeightsName("weights");
- weightReader.SetCorrectionFactor(1.0);
- weightReader.SetWeightFileName(writeDataFilePath);
- weightReader.WriteData();
- return 0;
- }*/
-
- //////////////////////////////////////////////////////////////////////////////
- // If required do Training....
- //////////////////////////////////////////////////////////////////////////////
- //mitk::DecisionForest forest;
-
- mitk::VigraRandomForestClassifier::Pointer forest = mitk::VigraRandomForestClassifier::New();
- forest->SetSamplesPerTree(samplesPerTree);
- forest->SetMinimumSplitNodeSize(minimumSplitNodeSize);
- forest->SetTreeCount(numberOfTrees);
- forest->UseSampleWithReplacement(sampleWithReplacement);
- forest->SetPrecision(trainPrecision);
- forest->SetMaximumTreeDepth(maximumTreeDepth);
- forest->SetWeightLambda(weightLambda);
-
- // TODO forest.UseRandomSplit(randomSplit);
-
- if (doTraining)
- {
- // 0 = LR-Estimation
- // 1 = KNN-Estimation
- // 2 = Kliep
- // 3 = Extern Image
- // 4 = Zadrozny
- // 5 = Spectral
- // 6 = uLSIF
- auto trainDataX = mitk::DCUtilities::DC3dDToMatrixXd(trainCollection, modalities, trainMask);
- auto trainDataY = mitk::DCUtilities::DC3dDToMatrixXi(trainCollection, trainMask, trainMask);
-
- if (useWeightedPoints)
- //if (false)
- {
- MITK_INFO << "Activated Point-based weighting...";
- //forest.UseWeightedPoints(true);
- forest->UsePointWiseWeight(true);
- //forest.SetWeightName("calculated_weight");
- /*if (importanceWeightAlgorithm == 1)
- {
- mitk::KNNDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 2)
- {
- mitk::KliepDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 3)
- {
- forest.SetWeightName(importanceWeightName);
- } else if (importanceWeightAlgorithm == 4)
- {
- mitk::ZadroznyWeighting est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 5)
- {
- mitk::SpectralDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else if (importanceWeightAlgorithm == 6)
- {
- mitk::ULSIFDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- } else*/
- {
- mitk::LRDensityEstimation est;
- est.SetCollection(trainCollection);
- est.SetTrainMask(trainMask);
- est.SetTestMask(testMask);
- est.SetModalities(modalities);
- est.SetWeightName("calculated_weight");
- est.Update();
- }
- auto trainDataW = mitk::DCUtilities::DC3dDToMatrixXd(trainCollection, "calculated_weight", trainMask);
- forest->SetPointWiseWeight(trainDataW);
- forest->UsePointWiseWeight(true);
- }
- MITK_INFO << "Start training the forest";
- forest->Train(trainDataX, trainDataY);
-
- MITK_INFO << "Save Forest";
- mitk::IOUtil::Save(forest, forestPath);
- } else
- {
- forest = mitk::IOUtil::Load<mitk::VigraRandomForestClassifier>(forestPath);// TODO forest.Load(forestPath);
- }
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- MITK_INFO << "Duration for Training: " << seconds;
- timingFile << seconds << ";";
- time(&lastTimePoint);
- //////////////////////////////////////////////////////////////////////////////
- // If required do Save Forest....
- //////////////////////////////////////////////////////////////////////////////
-
- //writer.// (forest);
- /*
- auto w = forest->GetTreeWeights();
- w(0,0) = 10;
- forest->SetTreeWeights(w);*/
-
- //////////////////////////////////////////////////////////////////////////////
- // If required do test
- //////////////////////////////////////////////////////////////////////////////
- MITK_INFO << "Convert Test data";
- auto testDataX = mitk::DCUtilities::DC3dDToMatrixXd(testCollection,modalities, testMask);
-
- MITK_INFO << "Predict Test Data";
- auto testDataNewY = forest->Predict(testDataX);
- auto testDataNewProb = forest->GetPointWiseProbabilities();
- //MITK_INFO << testDataNewY;
-
- auto maxClassValue = testDataNewProb.cols();
- std::vector<std::string> names;
- for (int i = 0; i < maxClassValue; ++i)
- {
- std::string name = resultProb + std::to_string(i);
- MITK_INFO << name;
- names.push_back(name);
- }
- //names.push_back("prob-1");
- //names.push_back("prob-2");
-
- mitk::DCUtilities::MatrixToDC3d(testDataNewY, testCollection, resultMask, testMask);
- mitk::DCUtilities::MatrixToDC3d(testDataNewProb, testCollection, names, testMask);
- MITK_INFO << "Converted predicted data";
- //forest.SetMaskName(testMask);
- //forest.SetCollection(testCollection);
- //forest.Test();
- //forest.PrintTree(0);
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << ";";
- time(&lastTimePoint);
-
- //////////////////////////////////////////////////////////////////////////////
- // Cost-based analysis
- //////////////////////////////////////////////////////////////////////////////
-
- // TODO Reactivate
- //MITK_INFO << "Calculate Cost-based Statistic ";
- //mitk::CostingStatistic costStat;
- //costStat.SetCollection(testCollection);
- //costStat.SetCombinedA("combinedHealty");
- //costStat.SetCombinedB("combinedTumor");
- //costStat.SetCombinedLabel("combinedLabel");
- //costStat.SetMaskName(testMask);
- ////std::vector<std::string> labelHealthy;
- ////labelHealthy.push_back("result_prop_Class-0");
- ////labelHealthy.push_back("result_prop_Class-4");
- ////std::vector<std::string> labelTumor;
- ////labelTumor.push_back("result_prop_Class-1");
- ////labelTumor.push_back("result_prop_Class-2");
- ////labelTumor.push_back("result_prop_Class-3");
- //costStat.SetProbabilitiesA(labelGroupA);
- //costStat.SetProbabilitiesB(labelGroupB);
-
- //std::ofstream costStatisticFile;
- //costStatisticFile.open((statisticFilePath + ".cost").c_str(), std::ios::app);
- //std::ofstream lcostStatisticFile;
-
- //lcostStatisticFile.open((statisticFilePath + ".longcost").c_str(), std::ios::app);
- //costStat.WriteStatistic(lcostStatisticFile,costStatisticFile,2.5,statisticShortFileLabel);
- //costStatisticFile.close();
-
- //costStat.CalculateClass(50);
-
- //////////////////////////////////////////////////////////////////////////////
- // Save results to folder
- //////////////////////////////////////////////////////////////////////////////
- ////std::vector<std::string> outputFilter;
- //outputFilter.push_back(resultMask);
- //std::vector<std::string> propNames = forest.GetListOfProbabilityNames();
- //outputFilter.insert(outputFilter.begin(), propNames.begin(), propNames.end());
- MITK_INFO << "Write Result to HDD";
- mitk::CollectionWriter::ExportCollectionToFolder(testCollection,
- outputFolder + "/result_collection.xml",
- outputFilter);
-
- MITK_INFO << "Calculate Statistic...." ;
- //////////////////////////////////////////////////////////////////////////////
- // Calculate and Print Statistic
- //////////////////////////////////////////////////////////////////////////////
- std::ofstream statisticFile;
- statisticFile.open(statisticFilePath.c_str(), std::ios::app);
- std::ofstream sstatisticFile;
- sstatisticFile.open(statisticShortFilePath.c_str(), std::ios::app);
-
- mitk::CollectionStatistic stat;
- stat.SetCollection(testCollection);
- stat.SetClassCount(5);
- stat.SetGoldName(statisticGoldStandard);
- stat.SetTestName(resultMask);
- stat.SetMaskName(testMask);
- mitk::BinaryValueminusOneToIndexMapper mapper;
- stat.SetGroundTruthValueToIndexMapper(&mapper);
- stat.SetTestValueToIndexMapper(&mapper);
- stat.Update();
- //stat.Print(statisticFile,sstatisticFile,statisticWithHeader, statisticShortFileLabel);
- stat.Print(statisticFile,sstatisticFile,true, statisticShortFileLabel);
- statisticFile.close();
-
- time(&now);
- seconds = std::difftime(now, lastTimePoint);
- timingFile << seconds << std::endl;
- time(&lastTimePoint);
- timingFile.close();
- }
- catch ( const std::string s )
- {
- MITK_INFO << s;
- return 0;
- }
- catch (char* s)
- {
- MITK_INFO << s;
- }
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLVoxelFeatures.cpp b/Modules/Classification/CLMiniApps/CLVoxelFeatures.cpp
deleted file mode 100644
index d568d6a9fd..0000000000
--- a/Modules/Classification/CLMiniApps/CLVoxelFeatures.cpp
+++ /dev/null
@@ -1,430 +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.
-
-============================================================================*/
-#ifndef mitkCLVoxeFeatures_cpp
-#define mitkCLVoxeFeatures_cpp
-
-#include "time.h"
-#include <sstream>
-#include <fstream>
-
-#include <mitkIOUtil.h>
-#include <mitkImageAccessByItk.h>
-#include <mitkImageCast.h>
-#include "mitkCommandLineParser.h"
-
-#include "itkDiscreteGaussianImageFilter.h"
-#include <itkLaplacianRecursiveGaussianImageFilter.h>
-#include "itkHessianRecursiveGaussianImageFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
-#include "vnl/algo/vnl_symmetric_eigensystem.h"
-#include <itkMultiHistogramFilter.h>
-#include <itkSubtractImageFilter.h>
-#include <itkLocalStatisticFilter.h>
-
-static std::vector<double> splitDouble(std::string str, char delimiter) {
- std::vector<double> internal;
- std::stringstream ss(str); // Turn the string into a stream.
- std::string tok;
- double val;
- while (std::getline(ss, tok, delimiter)) {
- std::stringstream s2(tok);
- s2 >> val;
- internal.push_back(val);
- }
-
- return internal;
-}
-
-namespace Functor
-{
- template <class TInput, class TOutput>
- class MatrixFirstEigenvalue
- {
- public:
- MatrixFirstEigenvalue() {}
- virtual ~MatrixFirstEigenvalue() {}
-
- int order;
-
- inline TOutput operator ()(const TInput& input)
- {
- double a,b,c;
- if (input[0] < 0.01 && input[1] < 0.01 &&input[2] < 0.01 &&input[3] < 0.01 &&input[4] < 0.01 &&input[5] < 0.01)
- return 0;
- vnl_symmetric_eigensystem_compute_eigenvals(input[0], input[1],input[2],input[3],input[4],input[5],a,b,c);
- switch (order)
- {
- case 0: return a;
- case 1: return b;
- case 2: return c;
- default: return a;
- }
- }
- bool operator !=(const MatrixFirstEigenvalue) const
- {
- return false;
- }
- bool operator ==(const MatrixFirstEigenvalue& other) const
- {
- return !(*this != other);
- }
- };
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void
- GaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType > GaussFilterType;
-
- typename GaussFilterType::Pointer gaussianFilter = GaussFilterType::New();
- gaussianFilter->SetInput( itkImage );
- gaussianFilter->SetVariance(variance);
- gaussianFilter->Update();
- mitk::CastToMitkImage(gaussianFilter->GetOutput(), output);
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void
- DifferenceOfGaussFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType > GaussFilterType;
- typedef itk::SubtractImageFilter<ImageType, ImageType, ImageType> SubFilterType;
-
- typename GaussFilterType::Pointer gaussianFilter1 = GaussFilterType::New();
- gaussianFilter1->SetInput( itkImage );
- gaussianFilter1->SetVariance(variance);
- gaussianFilter1->Update();
- typename GaussFilterType::Pointer gaussianFilter2 = GaussFilterType::New();
- gaussianFilter2->SetInput( itkImage );
- gaussianFilter2->SetVariance(variance*0.66*0.66);
- gaussianFilter2->Update();
- typename SubFilterType::Pointer subFilter = SubFilterType::New();
- subFilter->SetInput1(gaussianFilter1->GetOutput());
- subFilter->SetInput2(gaussianFilter2->GetOutput());
- subFilter->Update();
- mitk::CastToMitkImage(subFilter->GetOutput(), output);
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void
- LaplacianOfGaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, mitk::Image::Pointer &output)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType > GaussFilterType;
- typedef itk::LaplacianRecursiveGaussianImageFilter<ImageType, ImageType> LaplacianFilter;
-
- typename GaussFilterType::Pointer gaussianFilter = GaussFilterType::New();
- gaussianFilter->SetInput( itkImage );
- gaussianFilter->SetVariance(variance);
- gaussianFilter->Update();
- typename LaplacianFilter::Pointer laplaceFilter = LaplacianFilter::New();
- laplaceFilter->SetInput(gaussianFilter->GetOutput());
- laplaceFilter->Update();
- mitk::CastToMitkImage(laplaceFilter->GetOutput(), output);
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void
- HessianOfGaussianFilter(itk::Image<TPixel, VImageDimension>* itkImage, double variance, std::vector<mitk::Image::Pointer> &out)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::Image<double, VImageDimension> FloatImageType;
- typedef itk::HessianRecursiveGaussianImageFilter <ImageType> HessianFilterType;
- typedef typename HessianFilterType::OutputImageType VectorImageType;
- typedef Functor::MatrixFirstEigenvalue<typename VectorImageType::PixelType, double> DeterminantFunctorType;
- typedef itk::UnaryFunctorImageFilter<VectorImageType, FloatImageType, DeterminantFunctorType> DetFilterType;
-
- typename HessianFilterType::Pointer hessianFilter = HessianFilterType::New();
- hessianFilter->SetInput(itkImage);
- hessianFilter->SetSigma(std::sqrt(variance));
- for (unsigned int i = 0; i < VImageDimension; ++i)
- {
- typename DetFilterType::Pointer detFilter = DetFilterType::New();
- detFilter->SetInput(hessianFilter->GetOutput());
- detFilter->GetFunctor().order = i;
- detFilter->Update();
- mitk::CastToMitkImage(detFilter->GetOutput(), out[i]);
- }
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void
-LocalHistograms2(itk::Image<TPixel, VImageDimension>* itkImage, std::vector<mitk::Image::Pointer> &out, std::vector<double> params)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::MultiHistogramFilter <ImageType, ImageType> MultiHistogramType;
-
- double minimum = params[0];
- double maximum = params[1];
- int bins = std::round(params[2]);
-
- double offset = minimum;
- double delta = (maximum - minimum) / bins;
-
- typename MultiHistogramType::Pointer filter = MultiHistogramType::New();
- filter->SetInput(itkImage);
- filter->SetOffset(offset);
- filter->SetDelta(delta);
- filter->SetBins(bins);
- filter->Update();
- for (int i = 0; i < bins; ++i)
- {
- mitk::Image::Pointer img = mitk::Image::New();
- mitk::CastToMitkImage(filter->GetOutput(i), img);
- out.push_back(img);
- }
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void
- LocalHistograms(itk::Image<TPixel, VImageDimension>* itkImage, std::vector<mitk::Image::Pointer> &out, double offset, double delta)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::MultiHistogramFilter <ImageType,ImageType> MultiHistogramType;
-
- typename MultiHistogramType::Pointer filter = MultiHistogramType::New();
- filter->SetInput(itkImage);
- filter->SetOffset(offset);
- filter->SetDelta(delta);
- filter->Update();
- for (int i = 0; i < 11; ++i)
- {
- mitk::Image::Pointer img = mitk::Image::New();
- mitk::CastToMitkImage(filter->GetOutput(i), img);
- out.push_back(img);
- }
-}
-
-template<typename TPixel, unsigned int VImageDimension>
-void
-localStatistic(itk::Image<TPixel, VImageDimension>* itkImage, std::vector<mitk::Image::Pointer> &out, int size)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::LocalStatisticFilter <ImageType, ImageType> MultiHistogramType;
-
- typename MultiHistogramType::Pointer filter = MultiHistogramType::New();
- filter->SetInput(itkImage);
- filter->SetSize(size);
- filter->Update();
- for (int i = 0; i < 5; ++i)
- {
- mitk::Image::Pointer img = mitk::Image::New();
- mitk::CastToMitkImage(filter->GetOutput(i), img);
- out.push_back(img);
- }
-}
-
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("image", "i", mitkCommandLineParser::Image, "Input Image", "Path to the input VTK polydata", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output text file", "Target file. The output statistic is appended to this file.", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("extension", "e", mitkCommandLineParser::File, "Extension", "File extension. Default is .nii.gz", us::Any(), true, false, false, mitkCommandLineParser::Output);
-
- parser.addArgument("gaussian","g",mitkCommandLineParser::String, "Gaussian Filtering of the input images", "Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
- parser.addArgument("difference-of-gaussian","dog",mitkCommandLineParser::String, "Difference of Gaussian Filtering of the input images", "Difference of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
- parser.addArgument("laplace-of-gauss","log",mitkCommandLineParser::String, "Laplacian of Gaussian Filtering", "Laplacian of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
- parser.addArgument("hessian-of-gauss","hog",mitkCommandLineParser::String, "Hessian of Gaussian Filtering", "Hessian of Gaussian Filter. Followed by the used variances seperated by ';' ",us::Any());
- parser.addArgument("local-histogram", "lh", mitkCommandLineParser::String, "Local Histograms", "Calculate the local histogram based feature. Specify Offset and Delta, for exampel -3;0.6 ", us::Any());
- parser.addArgument("local-histogram2", "lh2", mitkCommandLineParser::String, "Local Histograms", "Calculate the local histogram based feature. Specify Minimum;Maximum;Bins, for exampel -3;3;6 ", us::Any());
- parser.addArgument("local-statistic", "ls", mitkCommandLineParser::String, "Local Histograms", "Calculate the local histogram based feature. Specify Offset and Delta, for exampel -3;0.6 ", us::Any());
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Global Image Feature calculator");
- parser.setDescription("Calculates different global statistics for a given segmentation / image combination");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- {
- return EXIT_FAILURE;
- }
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- return EXIT_SUCCESS;
- }
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(parsedArgs["image"].ToString());
- std::string filename=parsedArgs["output"].ToString();
-
- std::string extension = ".nii.gz";
- if (parsedArgs.count("extension"))
- {
- extension = parsedArgs["extension"].ToString();
- }
-
- ////////////////////////////////////////////////////////////////
- // CAlculate Local Histogram
- ////////////////////////////////////////////////////////////////
- MITK_INFO << "Check for Local Histogram...";
- if (parsedArgs.count("local-histogram"))
- {
- std::vector<mitk::Image::Pointer> outs;
- auto ranges = splitDouble(parsedArgs["local-histogram"].ToString(), ';');
- if (ranges.size() < 2)
- {
- MITK_INFO << "Missing Delta and Offset for Local Histogram";
- }
- else
- {
- AccessByItk_3(image, LocalHistograms, outs, ranges[0], ranges[1]);
- for (std::size_t i = 0; i < outs.size(); ++i)
- {
- std::string name = filename + "-lh" + us::any_value_to_string<int>(i)+extension;
- mitk::IOUtil::Save(outs[i], name);
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////
- // CAlculate Local Histogram 2
- ////////////////////////////////////////////////////////////////
- MITK_INFO << "Check for Local Histogram...";
- if (parsedArgs.count("local-histogram2"))
- {
- std::vector<mitk::Image::Pointer> outs;
- auto ranges = splitDouble(parsedArgs["local-histogram2"].ToString(), ';');
- if (ranges.size() < 3)
- {
- MITK_INFO << "Missing Delta and Offset for Local Histogram";
- }
- else
- {
- AccessByItk_2(image, LocalHistograms2, outs, ranges);
- for (std::size_t i = 0; i < outs.size(); ++i)
- {
- std::string name = filename + "-lh2" + us::any_value_to_string<int>(i)+extension;
- mitk::IOUtil::Save(outs[i], name);
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////
- // CAlculate Local Statistic
- ////////////////////////////////////////////////////////////////
- MITK_INFO << "Check for Local Histogram...";
- if (parsedArgs.count("local-statistic"))
- {
- std::vector<mitk::Image::Pointer> outs;
- auto ranges = splitDouble(parsedArgs["local-statistic"].ToString(), ';');
- if (ranges.size() < 1)
- {
- MITK_INFO << "Missing Rage";
- }
- else
- {
- for (std::size_t j = 0; j < ranges.size(); ++j)
- {
- AccessByItk_2(image, localStatistic, outs, ranges[j]);
- for (std::size_t i = 0; i < outs.size(); ++i)
- {
- std::string name = filename + "-lstat" + us::any_value_to_string<int>(ranges[j])+ "_" +us::any_value_to_string<int>(i)+extension;
- mitk::IOUtil::Save(outs[i], name);
- }
- outs.clear();
- }
- }
- }
-
-
- ////////////////////////////////////////////////////////////////
- // CAlculate Gaussian Features
- ////////////////////////////////////////////////////////////////
- MITK_INFO << "Check for Gaussian...";
- if (parsedArgs.count("gaussian"))
- {
- MITK_INFO << "Calculate Gaussian... " << parsedArgs["gaussian"].ToString();
- auto ranges = splitDouble(parsedArgs["gaussian"].ToString(),';');
-
- for (std::size_t i = 0; i < ranges.size(); ++i)
- {
- MITK_INFO << "Gaussian with sigma: " << ranges[i];
- mitk::Image::Pointer output;
- AccessByItk_2(image, GaussianFilter, ranges[i], output);
- MITK_INFO << "Write output:";
- std::string name = filename + "-gaussian-" + us::any_value_to_string(ranges[i]) + extension;
- mitk::IOUtil::Save(output, name);
- }
- }
-
- ////////////////////////////////////////////////////////////////
- // CAlculate Difference of Gaussian Features
- ////////////////////////////////////////////////////////////////
- MITK_INFO << "Check for DoG...";
- if (parsedArgs.count("difference-of-gaussian"))
- {
- MITK_INFO << "Calculate Difference of Gaussian... " << parsedArgs["difference-of-gaussian"].ToString();
- auto ranges = splitDouble(parsedArgs["difference-of-gaussian"].ToString(),';');
-
- for (std::size_t i = 0; i < ranges.size(); ++i)
- {
- mitk::Image::Pointer output;
- AccessByItk_2(image, DifferenceOfGaussFilter, ranges[i], output);
- std::string name = filename + "-dog-" + us::any_value_to_string(ranges[i]) + extension;
- mitk::IOUtil::Save(output, name);
- }
- }
-
- MITK_INFO << "Check for LoG...";
- ////////////////////////////////////////////////////////////////
- // CAlculate Laplacian Of Gauss Features
- ////////////////////////////////////////////////////////////////
- if (parsedArgs.count("laplace-of-gauss"))
- {
- MITK_INFO << "Calculate LoG... " << parsedArgs["laplace-of-gauss"].ToString();
- auto ranges = splitDouble(parsedArgs["laplace-of-gauss"].ToString(),';');
-
- for (std::size_t i = 0; i < ranges.size(); ++i)
- {
- mitk::Image::Pointer output;
- AccessByItk_2(image, LaplacianOfGaussianFilter, ranges[i], output);
- std::string name = filename + "-log-" + us::any_value_to_string(ranges[i]) + extension;
- mitk::IOUtil::Save(output, name);
- }
- }
-
- MITK_INFO << "Check for HoG...";
- ////////////////////////////////////////////////////////////////
- // CAlculate Hessian Of Gauss Features
- ////////////////////////////////////////////////////////////////
- if (parsedArgs.count("hessian-of-gauss"))
- {
- MITK_INFO << "Calculate HoG... " << parsedArgs["hessian-of-gauss"].ToString();
- auto ranges = splitDouble(parsedArgs["hessian-of-gauss"].ToString(),';');
-
- for (std::size_t i = 0; i < ranges.size(); ++i)
- {
- std::vector<mitk::Image::Pointer> outs;
- outs.push_back(mitk::Image::New());
- outs.push_back(mitk::Image::New());
- outs.push_back(mitk::Image::New());
- AccessByItk_2(image, HessianOfGaussianFilter, ranges[i], outs);
- std::string name = filename + "-hog0-" + us::any_value_to_string(ranges[i]) + extension;
- mitk::IOUtil::Save(outs[0], name);
- name = filename + "-hog1-" + us::any_value_to_string(ranges[i]) + extension;
- mitk::IOUtil::Save(outs[1], name);
- name = filename + "-hog2-" + us::any_value_to_string(ranges[i]) + extension;
- mitk::IOUtil::Save(outs[2], name);
- }
- }
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CLWeighting.cpp b/Modules/Classification/CLMiniApps/CLWeighting.cpp
deleted file mode 100644
index c55b10a061..0000000000
--- a/Modules/Classification/CLMiniApps/CLWeighting.cpp
+++ /dev/null
@@ -1,213 +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.
-
-============================================================================*/
-#ifndef mitkForest_cpp
-#define mitkForest_cpp
-
-#include "time.h"
-#include <sstream>
-#include <fstream>
-#include "mitkCommandLineParser.h"
-#include <mitkSplitParameterToVector.h>
-#include <mitkLog.h>
-#include <mitkLogMacros.h>
-
-
-//#include <mitkLRDensityEstimation.h>
-#include <mitkGeneralizedLinearModel.h>
-
-struct TrainingSet {
- vnl_matrix<double> feature;
- vnl_vector<double> label;
- double ratio;
-};
-
-
-const
-vnl_matrix<double> ReadMatrix(std::string path)
-{
- std::fstream file(path);
- std::vector<std::vector<double> > listOfRows;
-
- std::string line;
- while (std::getline(file, line))
- {
- auto current_row = mitk::cl::splitDouble(line, ',');
- if (listOfRows.size() < 1)
- {
- listOfRows.push_back(current_row);
- }
- else if (current_row.size() == listOfRows[0].size())
- {
- listOfRows.push_back(current_row);
- }
- }
- file.close();
-
- vnl_matrix<double> result(listOfRows.size(), listOfRows[0].size());
- for (std::size_t i = 0; i < listOfRows.size(); ++i)
- {
- for (std::size_t j = 0; j < listOfRows[0].size(); ++j)
- {
- result(i, j) = listOfRows[i][j];
- }
- }
- return result;
-}
-
-const
-TrainingSet ReadBothMatrix(std::string train, std::string test)
-{
- std::fstream file(train);
- std::vector<std::vector<double> > listOfRows;
- std::vector<double> label;
-
- double trSamples = 0;
- double teSamples = 0;
-
- std::string line;
- while (std::getline(file, line))
- {
- auto current_row = mitk::cl::splitDouble(line, ',');
- if (listOfRows.size() < 1)
- {
- listOfRows.push_back(current_row);
- label.push_back(0);
- trSamples += 1;
- }
- else if (current_row.size() == listOfRows[0].size())
- {
- listOfRows.push_back(current_row);
- label.push_back(0);
- trSamples += 1;
- }
- }
- file.close();
-
- std::fstream file2(test);
- while (std::getline(file2, line))
- {
- auto current_row = mitk::cl::splitDouble(line, ',');
- if (listOfRows.size() < 1)
- {
- listOfRows.push_back(current_row);
- label.push_back(1);
- teSamples += 1;
- }
- else if (current_row.size() == listOfRows[0].size())
- {
- listOfRows.push_back(current_row);
- label.push_back(1);
- teSamples += 1;
- }
- }
- file2.close();
-
- vnl_matrix<double> resultMatrix(listOfRows.size(), listOfRows[0].size());
- vnl_vector<double> resultLabel(listOfRows.size());
- for (std::size_t i = 0; i < listOfRows.size(); ++i)
- {
- for (std::size_t j = 0; j < listOfRows[0].size(); ++j)
- {
- resultMatrix(i, j) = listOfRows[i][j];
- }
- resultLabel(i) = label[i];
- }
- TrainingSet set;
- set.feature = resultMatrix;
- set.label = resultLabel;
- set.ratio = trSamples / teSamples;
- return set;
-}
-
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
- // required params
- parser.addArgument("training", "t", mitkCommandLineParser::Image, "Input Image", "desc", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("prediction", "p", mitkCommandLineParser::Image, "Input Image", "desc", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::Image, "Normalisation mode", "desc", us::Any(), false, false, false, mitkCommandLineParser::Input);
- //parser.addArgument("algorithm", "a", mitkCommandLineParser::InputImage, "Input Mask", "desc", us::Any(), false);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Importance weighting algorithm");
- parser.setDescription("Calculates the importance weighting of two input matrixes. ");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- MITK_INFO << "Extracting Parameters....";
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- std::string trainingPath = us::any_cast<std::string>(parsedArgs["training"]);
- std::string predictionPath = us::any_cast<std::string>(parsedArgs["prediction"]);
- std::string outputPath = us::any_cast<std::string>(parsedArgs["output"]);
- //std::string algorithm = us::any_cast<std::string>(parsedArgs["algorithm"]);
-
- MITK_INFO << "Reading Data...";
- auto input = ReadBothMatrix(trainingPath, predictionPath);
-
- MITK_INFO << "Calculating Weights...";
- mitk::GeneralizedLinearModel glm(input.feature, input.label);
- auto weights = glm.ExpMu(input.feature);
-
- MITK_INFO << "Writing Weights ...";
- MITK_INFO << outputPath;
- std::ofstream file(outputPath);
- for (unsigned int i = 0; i < input.label.size(); ++i)
- {
- if (input.label(i) < 0.5)
- {
- file << (input.ratio * weights(i)) << std::endl;
- }
- }
- file.close();
-
-
- //////////////////////////////////////////////////////////////////////////////
- // Read Images
- //////////////////////////////////////////////////////////////////////////////
- //mitk::DataCollection::Pointer col = mitk::DataCollection::New();
-
- //MITK_INFO << "Arg 2 " << argv[2];
- //mitk::Image::Pointer sur=mitk::IOUtil::Load<mitk::Image>(argv[2]);
- //col->AddData(sur.GetPointer(),"sur");
- //MITK_INFO << "Arg 3 " << argv[3];
- //mitk::Image::Pointer mask=mitk::IOUtil::Load<mitk::Image>(argv[3]);
- //col->AddData(mask.GetPointer(),"mask");
-
- //std::vector<std::string> modalities;
- //for (int i = 4; i < argc; ++i)
- //{
- // MITK_INFO << "Img " << argv[i];
- // std::stringstream ss;
- // ss << i;
- // modalities.push_back(ss.str());
- // mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(argv[i]);
- // col->AddData(img.GetPointer(),ss.str());
- //}
-
- //mitk::LRDensityEstimation est;
- //est.SetCollection(col);
- //est.SetTrainMask("sur");
- //est.SetTestMask("mask");
- //est.SetModalities(modalities);
- //est.SetWeightName("weight");
- //est.Update();
-
- //mitk::Image::Pointer w= col->GetMitkImage("weight");
- //mitk::IOUtil::SaveImage(w,argv[1]);
-
- return 0;
-}
-
-#endif
diff --git a/Modules/Classification/CLMiniApps/CMakeLists.txt b/Modules/Classification/CLMiniApps/CMakeLists.txt
index 7325e45a38..65a881ed31 100644
--- a/Modules/Classification/CLMiniApps/CMakeLists.txt
+++ b/Modules/Classification/CLMiniApps/CMakeLists.txt
@@ -1,117 +1,8 @@
-option(BUILD_ClassificationMiniApps "Build commandline tools for classification" OFF)
-
-if(BUILD_ClassificationMiniApps OR MITK_BUILD_ALL_APPS)
-
- include_directories(
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_BINARY_DIR}
- )
-
- # list of miniapps
- # if an app requires additional dependencies
- # they are added after a "^^" and separated by "_"
- set( classificationminiapps
- RandomForestTraining^^MitkCLVigraRandomForest
- NativeHeadCTSegmentation^^MitkCLVigraRandomForest
- ManualSegmentationEvaluation^^MitkCLVigraRandomForest
- CLScreenshot^^MitkCore_MitkQtWidgetsExt_MitkCLUtilities
- CLDicom2Nrrd^^MitkCore
- CLResampleImageToReference^^MitkCore
- CLGlobalImageFeatures^^MitkCLUtilities_MitkQtWidgetsExt
- CLMRNormalization^^MitkCLUtilities_MitkCLMRUtilities
- CLStaple^^MitkCLUtilities
- CLVoxelFeatures^^MitkCLUtilities
- CLPolyToNrrd^^
- CLPlanarFigureToNrrd^^MitkCore_MitkSegmentation_MitkMultilabel
- CLSimpleVoxelClassification^^MitkDataCollection_MitkCLVigraRandomForest
- CLVoxelClassification^^MitkDataCollection_MitkCLImportanceWeighting_MitkCLVigraRandomForest
- CLBrainMask^^MitkCLUtilities
- XRaxSimulationFromCT^^MitkCLUtilities
- CLRandomSampling^^MitkCore_MitkCLUtilities
- CLRemoveEmptyVoxels^^MitkCore
- CLN4^^MitkCore
- CLSkullMask^^MitkCore
- CLPointSetToSegmentation^^
- CLMultiForestPrediction^^MitkDataCollection_MitkCLVigraRandomForest
- CLNrrdToPoly^^MitkCore
- CL2Dto3DImage^^MitkCore
- CLWeighting^^MitkCore_MitkCLImportanceWeighting_MitkCLUtilities
- CLOverlayRoiCenterOfMass^^MitkCore_MitkCLUtilities_MitkQtWidgetsExt
- CLLungSegmentation^^MitkCore_MitkSegmentation_MitkMultilabel
- )
-
- foreach(classificationminiapps ${classificationminiapps})
- # extract mini app name and dependencies
- string(REPLACE "^^" "\\;" miniapp_info ${classificationminiapps})
- set(miniapp_info_list ${miniapp_info})
- list(GET miniapp_info_list 0 appname)
- list(GET miniapp_info_list 1 raw_dependencies)
- string(REPLACE "_" "\\;" dependencies "${raw_dependencies}")
- set(dependencies_list ${dependencies})
-
- mitk_create_executable(${appname}
- DEPENDS MitkCore MitkCLCore MitkCommandLine ${dependencies_list}
- PACKAGE_DEPENDS Qt5|Core Vigra VTK|IOImage ITK|Smoothing
- CPP_FILES ${appname}.cpp
- )
-
- if(EXECUTABLE_IS_ENABLED)
-
- # On Linux, create a shell script to start a relocatable application
- if(UNIX AND NOT APPLE)
- install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh)
- endif()
-
- get_target_property(_is_bundle ${EXECUTABLE_TARGET} MACOSX_BUNDLE)
-
- if(APPLE)
- if(_is_bundle)
- set(_target_locations ${EXECUTABLE_TARGET}.app)
- set(${_target_locations}_qt_plugins_install_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS)
- set(_bundle_dest_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS)
- set(_qt_plugins_for_current_bundle ${EXECUTABLE_TARGET}.app/Contents/MacOS)
- set(_qt_conf_install_dirs ${EXECUTABLE_TARGET}.app/Contents/Resources)
- install(TARGETS ${EXECUTABLE_TARGET} BUNDLE DESTINATION . )
- else()
- if(NOT MACOSX_BUNDLE_NAMES)
- set(_qt_conf_install_dirs bin)
- set(_target_locations bin/${EXECUTABLE_TARGET})
- set(${_target_locations}_qt_plugins_install_dir bin)
- install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin)
- else()
- foreach(bundle_name ${MACOSX_BUNDLE_NAMES})
- list(APPEND _qt_conf_install_dirs ${bundle_name}.app/Contents/Resources)
- set(_current_target_location ${bundle_name}.app/Contents/MacOS/${EXECUTABLE_TARGET})
- list(APPEND _target_locations ${_current_target_location})
- set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS)
- message( " set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) ")
-
- install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION ${bundle_name}.app/Contents/MacOS/)
- endforeach()
- endif()
- endif()
- else()
- set(_target_locations bin/${EXECUTABLE_TARGET}${CMAKE_EXECUTABLE_SUFFIX})
- set(${_target_locations}_qt_plugins_install_dir bin)
- set(_qt_conf_install_dirs bin)
- install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin)
- endif()
- endif()
- endforeach()
-
- mitk_create_executable(CLMatchPointReg
- DEPENDS MitkCore MitkCLUtilities MitkMatchPointRegistration MitkCommandLine MitkMatchPointRegistrationUI
- PACKAGE_DEPENDS Qt5|Core Vigra MatchPoint
- CPP_FILES CLMatchPointReg.cpp
- )
-
- # On Linux, create a shell script to start a relocatable application
- if(UNIX AND NOT APPLE)
- install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh)
- endif()
-
- if(EXECUTABLE_IS_ENABLED)
- MITK_INSTALL_TARGETS(EXECUTABLES ${EXECUTABLE_TARGET})
- endif()
+option(BUILD_ClassificationCmdApps "Build classification command-line tools" OFF)
+if(BUILD_ClassificationCmdApps OR MITK_BUILD_ALL_APPS)
+ mitkFunctionCreateCommandLineApp(NAME CLScreenshot DEPENDS MitkCLUtilities MitkQtWidgets)
+ mitkFunctionCreateCommandLineApp(NAME CLGlobalImageFeatures DEPENDS MitkCLUtilities MitkQtWidgets)
+ mitkFunctionCreateCommandLineApp(NAME CLMRNormalization DEPENDS MitkCLMRUtilities)
+ mitkFunctionCreateCommandLineApp(NAME CLN4)
endif()
diff --git a/Modules/Classification/CLMiniApps/ManualSegmentationEvaluation.cpp b/Modules/Classification/CLMiniApps/ManualSegmentationEvaluation.cpp
deleted file mode 100644
index 92ffbb677f..0000000000
--- a/Modules/Classification/CLMiniApps/ManualSegmentationEvaluation.cpp
+++ /dev/null
@@ -1,364 +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 <mitkCoreObjectFactory.h>
-#include "mitkImage.h"
-#include <mitkLexicalCast.h>
-#include <vnl/vnl_random.h>
-#include "mitkCommandLineParser.h"
-#include <mitkIOUtil.h>
-#include <itksys/SystemTools.hxx>
-#include <mitkITKImageImport.h>
-#include <mitkImageCast.h>
-#include <mitkProperties.h>
-
-// ITK
-#include <itkImageRegionIterator.h>
-
-// MITK
-#include <mitkIOUtil.h>
-
-// Classification
-#include <mitkCLUtil.h>
-#include <mitkVigraRandomForestClassifier.h>
-
-#include <QDir>
-#include <QString>
-#include <QStringList>
-
-#include <itkLabelOverlapMeasuresImageFilter.h>
-#include <itkImageRegionIteratorWithIndex.h>
-#include <itkNeighborhoodFunctorImageFilter.h>
-#include <itkFirstOrderStatisticsFeatureFunctor.h>
-#include <itkNeighborhood.h>
-#include <itkHessianMatrixEigenvalueImageFilter.h>
-#include <itkStructureTensorEigenvalueImageFilter.h>
-#include <itkLineHistogramBasedMassImageFilter.h>
-
-#include <random>
-
-using namespace mitk;
-
-std::vector<mitk::Image::Pointer> m_FeatureImageVector;
-
-void ProcessFeatureImages(const mitk::Image::Pointer & raw_image, const mitk::Image::Pointer & brain_mask)
-{
- typedef itk::Image<double,3> DoubleImageType;
- typedef itk::Image<short,3> ShortImageType;
- typedef itk::ConstNeighborhoodIterator<DoubleImageType> NeighborhoodType; // Neighborhood iterator to access image
- typedef itk::Functor::NeighborhoodFirstOrderStatistics<NeighborhoodType, double> FunctorType;
- typedef itk::NeighborhoodFunctorImageFilter<DoubleImageType, DoubleImageType, FunctorType> FOSFilerType;
-
- m_FeatureImageVector.clear();
-
- // RAW
- m_FeatureImageVector.push_back(raw_image);
-
- // GAUSS
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::GaussianFilter(raw_image,smoothed,1);
- m_FeatureImageVector.push_back(smoothed);
-
- // Calculate Probability maps (parameters used from literatur)
- // CSF
- mitk::Image::Pointer csf_prob = mitk::Image::New();
- mitk::CLUtil::ProbabilityMap(smoothed,13.9, 8.3,csf_prob);
- m_FeatureImageVector.push_back(csf_prob);
-
- // Lesion
-
- mitk::Image::Pointer les_prob = mitk::Image::New();
- mitk::CLUtil::ProbabilityMap(smoothed,59, 11.6,les_prob);
- m_FeatureImageVector.push_back(les_prob);
-
- // Barin (GM/WM)
-
- mitk::Image::Pointer brain_prob = mitk::Image::New();
- mitk::CLUtil::ProbabilityMap(smoothed,32, 5.6,brain_prob);
- m_FeatureImageVector.push_back(brain_prob);
-
- std::vector<unsigned int> FOS_sizes;
- FOS_sizes.push_back(1);
-
- DoubleImageType::Pointer input;
- ShortImageType::Pointer mask;
- mitk::CastToItkImage(smoothed, input);
- mitk::CastToItkImage(brain_mask, mask);
-
- for(unsigned int i = 0 ; i < FOS_sizes.size(); i++)
- {
- FOSFilerType::Pointer filter = FOSFilerType::New();
- filter->SetNeighborhoodSize(FOS_sizes[i]);
- filter->SetInput(input);
- filter->SetMask(mask);
-
- filter->Update();
- FOSFilerType::DataObjectPointerArray array = filter->GetOutputs();
-
- for( unsigned int i = 0; i < FunctorType::OutputCount; i++)
- {
- mitk::Image::Pointer featureimage;
- mitk::CastToMitkImage(dynamic_cast<DoubleImageType *>(array[i].GetPointer()),featureimage);
- m_FeatureImageVector.push_back(featureimage);
- // AddImageAsDataNode(featureimage,FunctorType::GetFeatureName(i))->SetVisibility(show_nodes);
- }
- }
-
- {
- itk::HessianMatrixEigenvalueImageFilter< DoubleImageType >::Pointer filter = itk::HessianMatrixEigenvalueImageFilter< DoubleImageType >::New();
- filter->SetInput(input);
- filter->SetImageMask(mask);
- filter->SetSigma(3);
- filter->Update();
-
- mitk::Image::Pointer o1,o2,o3;
- mitk::CastToMitkImage(filter->GetOutput(0),o1);
- mitk::CastToMitkImage(filter->GetOutput(1),o2);
- mitk::CastToMitkImage(filter->GetOutput(2),o3);
-
- m_FeatureImageVector.push_back(o1);
- m_FeatureImageVector.push_back(o2);
- m_FeatureImageVector.push_back(o3);
- }
-
- {
- itk::StructureTensorEigenvalueImageFilter< DoubleImageType >::Pointer filter = itk::StructureTensorEigenvalueImageFilter< DoubleImageType >::New();
- filter->SetInput(input);
- filter->SetImageMask(mask);
- filter->SetInnerScale(1.5);
- filter->SetOuterScale(3);
- filter->Update();
-
- mitk::Image::Pointer o1,o2,o3;
- mitk::CastToMitkImage(filter->GetOutput(0),o1);
- mitk::CastToMitkImage(filter->GetOutput(1),o2);
- mitk::CastToMitkImage(filter->GetOutput(2),o3);
-
- m_FeatureImageVector.push_back(o1);
- m_FeatureImageVector.push_back(o2);
- m_FeatureImageVector.push_back(o3);
- }
-
- {
- itk::LineHistogramBasedMassImageFilter< DoubleImageType >::Pointer filter = itk::LineHistogramBasedMassImageFilter< DoubleImageType >::New();
- filter->SetInput(input);
- filter->SetImageMask(mask);
- filter->Update();
-
- mitk::Image::Pointer o1;
- mitk::CastToMitkImage(filter->GetOutput(0),o1);
-
- m_FeatureImageVector.push_back(o1);
- }
-}
-
-std::vector<mitk::Point3D> PointSetToVector(const mitk::PointSet::Pointer & mps)
-{
- std::vector<mitk::Point3D> result;
- for(int i = 0 ; i < mps->GetSize(); i++)
- result.push_back(mps->GetPoint(i));
- return result;
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
-
- // required params
- parser.addArgument("inputdir", "i", mitkCommandLineParser::Directory, "Input Directory", "Contains input feature files.", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("outputdir", "o", mitkCommandLineParser::Directory, "Output Directory", "Destination of output files.", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("mitkprojectdata", "d", mitkCommandLineParser::File, "original class mask and raw image", "Orig. data.", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("csfmps", "csf", mitkCommandLineParser::File, "CSF Pointset", ".", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("lesmps", "les", mitkCommandLineParser::File, "LES Pointset", ".", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("bramps", "bra", mitkCommandLineParser::File, "BRA Pointset", ".", us::Any(), false, false, false, mitkCommandLineParser::Input);
- // parser.addArgument("points", "p", mitkCommandLineParser::Int, "Ensure that p points are selected", ".", us::Any(), false);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Evaluationtool for Manual-Segmentation");
- parser.setDescription("Uses Datacollection to calculate DICE scores for CSF LES BRA");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- // Params parsing
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- std::string inputdir = us::any_cast<std::string>(parsedArgs["inputdir"]);
- std::string outputdir = us::any_cast<std::string>(parsedArgs["outputdir"]);
- std::string mitkprojectdata = us::any_cast<std::string>(parsedArgs["mitkprojectdata"]);
- std::string csf_mps_name = us::any_cast<std::string>(parsedArgs["csfmps"]);
- std::string les_mps_name = us::any_cast<std::string>(parsedArgs["lesmps"]);
- std::string bra_mps_name = us::any_cast<std::string>(parsedArgs["bramps"]);
-
- mitk::Image::Pointer class_mask_sampled, raw_image, class_mask;
- mitk::PointSet::Pointer CSF_mps, LES_mps, BRA_mps;
-
- // Load from mitk-project
- auto so = mitk::IOUtil::Load(inputdir + "/" + mitkprojectdata);
- std::map<unsigned int, unsigned int> map;
- mitk::CLUtil::CountVoxel(dynamic_cast<mitk::Image *>(so[1].GetPointer()), map);
- raw_image = map.size() <= 7 ? dynamic_cast<mitk::Image *>(so[0].GetPointer()) : dynamic_cast<mitk::Image *>(so[1].GetPointer());
- class_mask = map.size() <= 7 ? dynamic_cast<mitk::Image *>(so[1].GetPointer()) : dynamic_cast<mitk::Image *>(so[0].GetPointer());
-
- CSF_mps = mitk::IOUtil::Load<mitk::PointSet>(inputdir + "/" + csf_mps_name);
- LES_mps = mitk::IOUtil::Load<mitk::PointSet>(inputdir + "/" + les_mps_name);
- BRA_mps = mitk::IOUtil::Load<mitk::PointSet>(inputdir + "/" + bra_mps_name);
-
- unsigned int num_points = CSF_mps->GetSize() + LES_mps->GetSize() + BRA_mps->GetSize();
- MITK_INFO << "Found #" << num_points << " points over all classes.";
-
- ProcessFeatureImages(raw_image, class_mask);
-
- std::map<unsigned int, unsigned int> tmpMap;
- tmpMap[0] = 0;
- tmpMap[1] = 1;
- tmpMap[2] = 1;
- tmpMap[3] = 1;
- tmpMap[4] = 2;
- tmpMap[5] = 3;
- tmpMap[6] = 3;
- mitk::CLUtil::MergeLabels( class_mask, tmpMap);
- class_mask_sampled = class_mask->Clone();
- itk::Image<short,3>::Pointer itk_classmask_sampled;
- mitk::CastToItkImage(class_mask_sampled,itk_classmask_sampled);
- itk::ImageRegionIteratorWithIndex<itk::Image<short,3> >::IndexType index;
- itk::ImageRegionIteratorWithIndex<itk::Image<short,3> > iit(itk_classmask_sampled,itk_classmask_sampled->GetLargestPossibleRegion());
-
- std::ofstream myfile;
- myfile.open (inputdir + "/results_3.csv");
-
- Eigen::MatrixXd X_test;
-
- unsigned int count_test = 0;
- mitk::CLUtil::CountVoxel(class_mask, count_test);
- X_test = Eigen::MatrixXd(count_test, m_FeatureImageVector.size());
-
- unsigned int pos = 0;
- for( const auto & image : m_FeatureImageVector)
- {
- X_test.col(pos) = mitk::CLUtil::Transform<double>(image,class_mask);
- ++pos;
- }
-
- std::random_device rnd;
-
- unsigned int runs = 20;
- for(unsigned int k = 0 ; k < runs; k++)
- {
- auto CSF_vec = PointSetToVector(CSF_mps);
- auto LES_vec = PointSetToVector(LES_mps);
- auto BRA_vec = PointSetToVector(BRA_mps);
-
- itk_classmask_sampled->FillBuffer(0);
-
- // initial draws
- std::shuffle(CSF_vec.begin(), CSF_vec.end(), std::mt19937(rnd()));
- class_mask->GetGeometry()->WorldToIndex(CSF_vec.back(),index);
- iit.SetIndex(index);
- iit.Set(1);
- CSF_vec.pop_back();
-
- std::shuffle(LES_vec.begin(), LES_vec.end(), std::mt19937(rnd()));
- class_mask->GetGeometry()->WorldToIndex(LES_vec.back(),index);
- iit.SetIndex(index);
- iit.Set(2);
- LES_vec.pop_back();
-
- std::shuffle(BRA_vec.begin(), BRA_vec.end(), std::mt19937(rnd()));
- class_mask->GetGeometry()->WorldToIndex(BRA_vec.back(),index);
- iit.SetIndex(index);
- iit.Set(3);
- BRA_vec.pop_back();
-
- std::stringstream ss;
-
- while(!(CSF_vec.empty() && LES_vec.empty() && BRA_vec.empty()))
- {
- mitk::CastToMitkImage(itk_classmask_sampled, class_mask_sampled);
-
- // Train forest
- mitk::VigraRandomForestClassifier::Pointer classifier = mitk::VigraRandomForestClassifier::New();
- classifier->SetTreeCount(40);
- classifier->SetSamplesPerTree(0.66);
-
- Eigen::MatrixXd X_train;
-
- unsigned int count_train = 0;
- mitk::CLUtil::CountVoxel(class_mask_sampled, count_train);
- X_train = Eigen::MatrixXd(count_train, m_FeatureImageVector.size() );
-
- unsigned int pos = 0;
- for( const auto & image : m_FeatureImageVector)
- {
- X_train.col(pos) = mitk::CLUtil::Transform<double>(image,class_mask_sampled);
- ++pos;
- }
-
- Eigen::MatrixXi Y = mitk::CLUtil::Transform<int>(class_mask_sampled,class_mask_sampled);
- classifier->Train(X_train,Y);
-
- Eigen::MatrixXi Y_test = classifier->Predict(X_test);
-
- mitk::Image::Pointer result_mask = mitk::CLUtil::Transform<int>(Y_test, class_mask);
- itk::Image<short,3>::Pointer itk_result_mask, itk_class_mask;
-
- mitk::CastToItkImage(result_mask,itk_result_mask);
- mitk::CastToItkImage(class_mask, itk_class_mask);
-
- itk::LabelOverlapMeasuresImageFilter<itk::Image<short,3> >::Pointer overlap_filter = itk::LabelOverlapMeasuresImageFilter<itk::Image<short,3> >::New();
- overlap_filter->SetInput(0,itk_result_mask);
- overlap_filter->SetInput(1,itk_class_mask);
- overlap_filter->Update();
-
- MITK_INFO << "DICE (" << num_points - (CSF_vec.size() + LES_vec.size() + BRA_vec.size()) << "): " << overlap_filter->GetDiceCoefficient();
- ss << overlap_filter->GetDiceCoefficient() <<",";
-
- // random class selection
-
- if(!CSF_vec.empty())
- {
- std::shuffle(CSF_vec.begin(), CSF_vec.end(), std::mt19937(rnd()));
- class_mask->GetGeometry()->WorldToIndex(CSF_vec.back(),index);
- iit.SetIndex(index);
- iit.Set(1);
- CSF_vec.pop_back();
- }
-
- if(!LES_vec.empty())
- {
- std::shuffle(LES_vec.begin(), LES_vec.end(), std::mt19937(rnd()));
- class_mask->GetGeometry()->WorldToIndex(LES_vec.back(),index);
- iit.SetIndex(index);
- iit.Set(2);
- LES_vec.pop_back();
- }
-
- if(!BRA_vec.empty())
- {
- std::shuffle(BRA_vec.begin(), BRA_vec.end(), std::mt19937(rnd()));
- class_mask->GetGeometry()->WorldToIndex(BRA_vec.back(),index);
- iit.SetIndex(index);
- iit.Set(3);
- BRA_vec.pop_back();
- }
- }
-
- myfile << ss.str() << "\n";
- myfile.flush();
- }
-
- myfile.close();
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/NativeHeadCTSegmentation.cpp b/Modules/Classification/CLMiniApps/NativeHeadCTSegmentation.cpp
deleted file mode 100644
index 1a24f9157a..0000000000
--- a/Modules/Classification/CLMiniApps/NativeHeadCTSegmentation.cpp
+++ /dev/null
@@ -1,232 +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 <mitkCoreObjectFactory.h>
-#include "mitkImage.h"
-#include <mitkLexicalCast.h>
-#include "mitkCommandLineParser.h"
-#include <mitkIOUtil.h>
-#include <itksys/SystemTools.hxx>
-#include <mitkITKImageImport.h>
-#include <mitkImageCast.h>
-#include <mitkProperties.h>
-
-// ITK
-#include <itkImageRegionIterator.h>
-
-// MITK
-#include <mitkIOUtil.h>
-
-// Classification
-#include <mitkCLUtil.h>
-#include <mitkVigraRandomForestClassifier.h>
-#include <mitkAbstractFileReader.h>
-
-#include <QDir>
-#include <QString>
-#include <QStringList>
-
-#include <mitkImageAccessByItk.h>
-
-using namespace mitk;
-
-typedef unsigned int uint;
-void ReadMitkProjectImageAndMask(std::string input_file, mitk::Image::Pointer & raw_image, mitk::Image::Pointer & class_mask, Image::Pointer &brain_mask);
-std::map<unsigned int, double> VolumeUnderMaskByLabel(mitk::Image::Pointer mask);
-
-/**
-*
-*/
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
-
- // required params
- parser.addArgument("inputdir", "i", mitkCommandLineParser::Directory, "Input Directory", "Contains input feature files.", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("outputdir", "o", mitkCommandLineParser::Directory, "Output Directory", "Destination of output files.", us::Any(), false, false, false, mitkCommandLineParser::Output);
-
- // optional params
- parser.addArgument("select", "s", mitkCommandLineParser::String, "Item selection", "Using Regular expression, seperated by space e.g.: '*.nrrd *.vtk *test*'",std::string("*.mitk"),true);
- // parser.addArgument("treecount", "tc", mitkCommandLineParser::Int, "Treecount", "Number of trees.",50,true);
- // parser.addArgument("treedepth", "td", mitkCommandLineParser::Int, "Treedepth", "Maximal tree depth.",50,true);
- // parser.addArgument("minsplitnodesize", "min", mitkCommandLineParser::Int, "Minimum split node size.", "Minimum split node size.",2,true);
- // parser.addArgument("precision", "p", mitkCommandLineParser::Float, "Split precision.", "Precision.", mitk::eps,true);
- // parser.addArgument("fraction", "f", mitkCommandLineParser::Float, "Fraction of samples per tree.", "Fraction of samples per tree.", 0.6f,true);
- // parser.addArgument("replacment", "r", mitkCommandLineParser::Bool, "Sample with replacement.", "Sample with replacement.", true,true);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Native Head CT Segmentation");
- parser.setDescription("Using vigra random forest");
- parser.setContributor("Jonas Cordes");
-
- // Params parsing
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- std::string inputdir = us::any_cast<std::string>(parsedArgs["inputdir"]);
- std::string outputdir = us::any_cast<std::string>(parsedArgs["outputdir"]);
-
- // int treecount = parsedArgs.count("treecount") ? us::any_cast<int>(parsedArgs["treecount"]) : 50;
- // int treedepth = parsedArgs.count("treedepth") ? us::any_cast<int>(parsedArgs["treedepth"]) : 50;
- // int minsplitnodesize = parsedArgs.count("minsplitnodesize") ? us::any_cast<int>(parsedArgs["minsplitnodesize"]) : 2;
- // float precision = parsedArgs.count("precision") ? us::any_cast<float>(parsedArgs["precision"]) : mitk::eps;
- // float fraction = parsedArgs.count("fraction") ? us::any_cast<float>(parsedArgs["fraction"]) : 0.6;
- // bool withreplacement = parsedArgs.count("replacment") ? us::any_cast<float>(parsedArgs["replacment"]) : true;
- std::string filt_select = parsedArgs.count("select") ? us::any_cast<std::string>(parsedArgs["select"]) : "*.mitk";
-
- QString filter(filt_select.c_str());
- QDir dir(inputdir.c_str());
- auto strl = dir.entryList(filter.split(" "),QDir::Files);
-
- // create the one
- mitk::VigraRandomForestClassifier::Pointer classifier = mitk::VigraRandomForestClassifier::New();
- uint n_samples = 45000;
- uint n_samples_per_image = n_samples / strl.size();
- uint n_features = 2;
-
- {// Training
- Eigen::MatrixXd feature_matrix(n_samples, n_features);
- Eigen::MatrixXi label_matrix(n_samples, 1);
-
- uint pos = 0;
-
- for(auto entry : strl)
- {
- mitk::Image::Pointer raw_image, class_mask, brain_mask;
- ReadMitkProjectImageAndMask(inputdir + entry.toStdString(), raw_image, class_mask, brain_mask);
-
- mitk::Image::Pointer brain_mask_sampled;
- AccessFixedDimensionByItk_2(brain_mask, mitk::CLUtil::itkSampleLabel, 3, brain_mask_sampled, n_samples_per_image);
-
- mitk::Image::Pointer csf_prob;
- mitk::CLUtil::ProbabilityMap(raw_image,13.9, 8.3,csf_prob);
- mitk::CLUtil::ErodeGrayscale(csf_prob,1,mitk::CLUtil::Axial,csf_prob);
- mitk::CLUtil::DilateGrayscale(csf_prob,3,mitk::CLUtil::Axial,csf_prob);
- mitk::CLUtil::FillHoleGrayscale(csf_prob,csf_prob);
-
- feature_matrix.block(pos, 0, n_samples_per_image, 1) = mitk::CLUtil::Transform<double>(raw_image,brain_mask_sampled);
- feature_matrix.block(pos, 1, n_samples_per_image, 1) = mitk::CLUtil::Transform<double>(csf_prob,brain_mask_sampled);
-
- label_matrix.block(pos, 0, n_samples_per_image, 1) = mitk::CLUtil::Transform<int>(class_mask, brain_mask_sampled);
- pos += n_samples_per_image;
- }
- classifier->Train(feature_matrix, label_matrix);
- classifier->PrintParameter();
- }
-
- std::map<std::string, std::pair<double, double> > map_error;
-
- for(auto entry: strl)
- {
- mitk::Image::Pointer raw_image, class_mask, brain_mask;
- ReadMitkProjectImageAndMask(inputdir + entry.toStdString(), raw_image, class_mask, brain_mask);
-
- auto map_true = VolumeUnderMaskByLabel(class_mask);
-
- mitk::Image::Pointer csf_prob;
- mitk::CLUtil::ProbabilityMap(raw_image,13.9, 8.3,csf_prob);
- mitk::CLUtil::ErodeGrayscale(csf_prob,1,mitk::CLUtil::Axial,csf_prob);
- mitk::CLUtil::DilateGrayscale(csf_prob,3,mitk::CLUtil::Axial,csf_prob);
- mitk::CLUtil::FillHoleGrayscale(csf_prob,csf_prob);
-
- uint count = 0;
- mitk::CLUtil::CountVoxel(brain_mask,count);
-
- Eigen::MatrixXd feature_matrix(count,n_features);
- feature_matrix.block(0, 0, count, 1) = mitk::CLUtil::Transform<double>(raw_image,brain_mask);
- feature_matrix.block(0, 1, count, 1) = mitk::CLUtil::Transform<double>(csf_prob,brain_mask);
-
- mitk::Image::Pointer result_mask = mitk::CLUtil::Transform<int>(classifier->Predict(feature_matrix),brain_mask);
-
- std::string name = itksys::SystemTools::GetFilenameWithoutExtension(entry.toStdString());
- mitk::IOUtil::Save(result_mask,outputdir + name + ".nrrd");
-
- auto map_pred = VolumeUnderMaskByLabel(result_mask);
-
- map_error[entry.toStdString()] = std::make_pair(std::abs(map_true[1] - map_pred[1]) / map_true[1], map_true[2] != 0 ? std::abs(map_true[2] - map_pred[2]) / map_true[2]: 0);
- }
-
- double mean_error_csf = 0;
- double mean_error_les = 0;
- double num_subjects = map_error.size();
- for(auto entry: map_error)
- {
- MITK_INFO(entry.first.c_str()) << "CSF error: " << entry.second.first << "%\t LES error: " << entry.second.second << "%";
- mean_error_csf += entry.second.first;
- mean_error_les += entry.second.second;
- }
- MITK_INFO("Mean") << "CSF error: " << mean_error_csf/num_subjects << "%\t LES error: " << mean_error_les/num_subjects << "%";
-
- return EXIT_SUCCESS;
-}
-
-void ReadMitkProjectImageAndMask(std::string input_file, mitk::Image::Pointer & raw_image, mitk::Image::Pointer & class_mask, mitk::Image::Pointer & brain_mask)
-{
- auto so = mitk::IOUtil::Load(input_file);
-
- std::map<uint, uint> map;
-
- mitk::CLUtil::CountVoxel(dynamic_cast<mitk::Image *>(so[1].GetPointer()), map);
-
- raw_image = map.size() <= 7 ? dynamic_cast<mitk::Image *>(so[0].GetPointer()) : dynamic_cast<mitk::Image *>(so[1].GetPointer());
- class_mask = map.size() <= 7 ? dynamic_cast<mitk::Image *>(so[1].GetPointer()) : dynamic_cast<mitk::Image *>(so[0].GetPointer());
-
- std::map<uint, uint> merge_instructions;// = {{0,0},{1,1},{2,1},{3,1},{4,2},{5,3},{6,3}};
- merge_instructions[0] = 0;
- merge_instructions[1] = 1;
- merge_instructions[2] = 1;
- merge_instructions[3] = 1;
- merge_instructions[4] = 2;
- merge_instructions[5] = 3;
- merge_instructions[6] = 3;
- mitk::CLUtil::MergeLabels(class_mask, merge_instructions);
-
- brain_mask = class_mask->Clone();
- //merge_instructions = {{0,0},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1}};
- merge_instructions[0] = 0;
- merge_instructions[1] = 1;
- merge_instructions[2] = 1;
- merge_instructions[3] = 1;
- merge_instructions[4] = 1;
- merge_instructions[5] = 1;
- merge_instructions[6] = 1;
- mitk::CLUtil::MergeLabels(brain_mask, merge_instructions);
-}
-
-std::map<unsigned int, double> VolumeUnderMaskByLabel(mitk::Image::Pointer mask)
-{
- itk::Image<unsigned int, 3>::Pointer img;
- mitk::CastToItkImage(mask,img);
-
- std::map<unsigned int, double> volume_map;
- itk::ImageRegionConstIterator<itk::Image<unsigned int, 3>> it(img,img->GetLargestPossibleRegion());
- while(!it.IsAtEnd())
- {
- itk::Image<unsigned int, 3>::PixelType value = it.Value();
- if(volume_map.find(value)== volume_map.end())
- volume_map[value] = 0;
- volume_map[value]++;
- ++it;
- }
-
- auto spacing = img->GetSpacing();
- double volumeUnit = spacing[0] * spacing[1] * spacing[2];
- volumeUnit *= 0.001;
-
- for(auto entry: volume_map)
- entry.second *= volumeUnit;
-
- return volume_map;
-}
diff --git a/Modules/Classification/CLMiniApps/RandomForestTraining.cpp b/Modules/Classification/CLMiniApps/RandomForestTraining.cpp
deleted file mode 100644
index 9b4c9683b9..0000000000
--- a/Modules/Classification/CLMiniApps/RandomForestTraining.cpp
+++ /dev/null
@@ -1,148 +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 <mitkCoreObjectFactory.h>
-#include "mitkImage.h"
-#include <mitkLexicalCast.h>
-#include "mitkCommandLineParser.h"
-#include <mitkIOUtil.h>
-#include <itksys/SystemTools.hxx>
-#include <mitkITKImageImport.h>
-#include <mitkImageCast.h>
-#include <mitkProperties.h>
-
-// ITK
-#include <itkImageRegionIterator.h>
-
-// MITK
-#include <mitkIOUtil.h>
-
-// Classification
-#include <mitkCLUtil.h>
-#include <mitkVigraRandomForestClassifier.h>
-
-#include <QDir>
-#include <QString>
-#include <QStringList>
-
-
-using namespace mitk;
-
-/**
- *
- */
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
- parser.setArgumentPrefix("--", "-");
-
- // required params
- parser.addArgument("inputdir", "i", mitkCommandLineParser::Directory, "Input Directory", "Contains input feature files.", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("outputdir", "o", mitkCommandLineParser::Directory, "Output Directory", "Destination of output files.", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("classmask", "m", mitkCommandLineParser::File, "Class mask image", "Contains several classes.", us::Any(), false, false, false, mitkCommandLineParser::Input);
-
- // optional params
- parser.addArgument("select", "s", mitkCommandLineParser::String, "Item selection", "Using Regular expression, seperated by space e.g.: '*.nrrd *.vtk *test*'",std::string("*.nrrd"),true);
- parser.addArgument("treecount", "tc", mitkCommandLineParser::Int, "Treecount", "Number of trees.",50,true);
- parser.addArgument("treedepth", "td", mitkCommandLineParser::Int, "Treedepth", "Maximal tree depth.",50,true);
- parser.addArgument("minsplitnodesize", "min", mitkCommandLineParser::Int, "Minimum split node size.", "Minimum split node size.",2,true);
- parser.addArgument("precision", "p", mitkCommandLineParser::Float, "Split precision.", "Precision.", mitk::eps,true);
- parser.addArgument("fraction", "f", mitkCommandLineParser::Float, "Fraction of samples per tree.", "Fraction of samples per tree.", 0.6f,true);
- parser.addArgument("replacment", "r", mitkCommandLineParser::Bool, "Sample with replacement.", "Sample with replacement.", true,true);
-
- // Miniapp Infos
- parser.setCategory("Classification Tools");
- parser.setTitle("Random Forest Training");
- parser.setDescription("Vigra RF impl.");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- // Params parsing
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- std::string inputdir = us::any_cast<std::string>(parsedArgs["inputdir"]);
- std::string outputdir = us::any_cast<std::string>(parsedArgs["outputdir"]);
- std::string classmask = us::any_cast<std::string>(parsedArgs["classmask"]);
-
- int treecount = parsedArgs.count("treecount") ? us::any_cast<int>(parsedArgs["treecount"]) : 50;
- int treedepth = parsedArgs.count("treedepth") ? us::any_cast<int>(parsedArgs["treedepth"]) : 50;
- int minsplitnodesize = parsedArgs.count("minsplitnodesize") ? us::any_cast<int>(parsedArgs["minsplitnodesize"]) : 2;
- float precision = parsedArgs.count("precision") ? us::any_cast<float>(parsedArgs["precision"]) : mitk::eps;
- float fraction = parsedArgs.count("fraction") ? us::any_cast<float>(parsedArgs["fraction"]) : 0.6;
- bool withreplacement = parsedArgs.count("replacment") ? us::any_cast<float>(parsedArgs["replacment"]) : true;
- std::string filt_select =/* parsedArgs.count("select") ? us::any_cast<std::string>(parsedArgs["select"]) :*/ "*.nrrd";
-
- QString filter(filt_select.c_str());
-
- // **** in principle repeat this block to create a feature matrix X_all for all subjects (in dir)
- // Get nrrd filepath
- QDir dir(inputdir.c_str());
- auto strl = dir.entryList(filter.split(" "),QDir::Files);
-
- // load class mask
- mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(classmask);
- unsigned int num_samples = 0;
- mitk::CLUtil::CountVoxel(mask,num_samples);
-
- // initialize featurematrix [num_samples, num_featureimages]
- Eigen::MatrixXd X(num_samples, strl.size());
-
- for(int i = 0 ; i < strl.size(); i++)
- {
- // load feature image
- mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(inputdir + strl[i].toStdString());
- // transfom it into a [num_samples, 1] vector depending on the classmask
- Eigen::MatrixXd _x = mitk::CLUtil::Transform<double>(img,mask);
- // replace i-th (empty) col with feature vector in _x
- X.block(0,i,num_samples,1) = _x;
- }
- // ****
-
- // transform classmask into the label-vector [num_samples, 1]
- Eigen::MatrixXi Y = mitk::CLUtil::Transform<int>(mask,mask);
-
- mitk::VigraRandomForestClassifier::Pointer classifier = mitk::VigraRandomForestClassifier::New();
- classifier->SetTreeCount(treecount);
- classifier->SetMaximumTreeDepth(treedepth);
- classifier->SetMinimumSplitNodeSize(minsplitnodesize);
- classifier->SetPrecision(precision);
- classifier->SetSamplesPerTree(fraction);
- classifier->UseSampleWithReplacement(withreplacement);
-
- classifier->PrintParameter();
- classifier->Train(X,Y);
-
- MITK_INFO << classifier->IsEmpty();
-
- // no metainformations are saved currently
- // only the raw vigra rf data
- mitk::IOUtil::Save(classifier, outputdir + "RandomForest.hdf5");
-
- Eigen::MatrixXi Y_pred = classifier->Predict(X);
- Eigen::MatrixXd Probs = classifier->GetPointWiseProbabilities();
-
- MITK_INFO << Y_pred.rows() << " " << Y_pred.cols();
- MITK_INFO << Probs.rows() << " " << Probs.cols();
-
- // mitk::Image::Pointer prediction = mitk::CLUtil::Transform<int>(Y_pred,mask);
- mitk::Image::Pointer probs_1 = mitk::CLUtil::Transform<double>(Probs.col(0),mask);
- mitk::Image::Pointer probs_2 = mitk::CLUtil::Transform<double>(Probs.col(1),mask);
- mitk::Image::Pointer probs_3 = mitk::CLUtil::Transform<double>(Probs.col(2),mask);
-
- mitk::IOUtil::Save(probs_1, outputdir + "probs_1.nrrd");
- mitk::IOUtil::Save(probs_2, outputdir + "probs_2.nrrd");
- mitk::IOUtil::Save(probs_3, outputdir + "probs_3.nrrd");
- // mitk::IOUtil::Save(probs_2, outputdir + "test.nrrd");
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLMiniApps/XRaxSimulationFromCT.cpp b/Modules/Classification/CLMiniApps/XRaxSimulationFromCT.cpp
deleted file mode 100644
index 6bc9e2e689..0000000000
--- a/Modules/Classification/CLMiniApps/XRaxSimulationFromCT.cpp
+++ /dev/null
@@ -1,221 +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 "mitkProperties.h"
-
-#include "mitkCommandLineParser.h"
-#include "mitkIOUtil.h"
-
-#include "itkImageRegionIterator.h"
-// MITK
-#include <mitkITKImageImport.h>
-#include <mitkImageCast.h>
-#include <mitkImageAccessByItk.h>
-
-struct Params {
- bool invert;
- float zeroValue;
-};
-template<typename TPixel, unsigned int VImageDimension>
-void
-CreateXRay(itk::Image<TPixel, VImageDimension>* itkImage, mitk::Image::Pointer mask1, std::string output, Params param)
-{
- typedef itk::Image<TPixel, VImageDimension> ImageType;
- typedef itk::Image<unsigned char, VImageDimension> MaskType;
- typedef itk::Image<double, 2 > NewImageType;
-
- typename MaskType::Pointer itkMask = MaskType::New();
- mitk::CastToItkImage(mask1, itkMask);
-
- NewImageType::SpacingType newSpacing;
- typename ImageType::SpacingType spacing;
- spacing[0] = 0;
- spacing[1] = 0;
- spacing[2] = 0;
- spacing = itkImage->GetSpacing();
-
- NewImageType::RegionType region1,region2,region3,region1m,region2m,region3m;
- NewImageType::IndexType start;
- start[0] = 0; start[1] = 0;
-
- NewImageType::SizeType size1, size2, size3;
- size1[0] = mask1->GetDimensions()[0];
- size2[0] = mask1->GetDimensions()[0];
- size3[0] = mask1->GetDimensions()[1];
- size1[1] = mask1->GetDimensions()[1];
- size2[1] = mask1->GetDimensions()[2];
- size3[1] = mask1->GetDimensions()[2];
-
- region1.SetSize(size1);
- region1m.SetSize(size1);
- region2.SetSize(size2);
- region2m.SetSize(size2);
- region3.SetSize(size3);
- region3m.SetSize(size3);
- region1.SetIndex(start);
- region1m.SetIndex(start);
- region2.SetIndex(start);
- region2m.SetIndex(start);
- region3.SetIndex(start);
- region3m.SetIndex(start);
-
- NewImageType::Pointer image1 = NewImageType::New();
- image1->SetRegions(region1);
- image1->Allocate();
- image1->FillBuffer(0);
- newSpacing[0] = spacing[0]; newSpacing[1] = spacing[1];
- image1->SetSpacing(newSpacing);
- NewImageType::Pointer image2 = NewImageType::New();
- image2->SetRegions(region2);
- image2->Allocate();
- image2->FillBuffer(0);
- newSpacing[0] = spacing[0]; newSpacing[1] = spacing[2];
- image2->SetSpacing(newSpacing);
- NewImageType::Pointer image3 = NewImageType::New();
- image3->SetRegions(region3);
- image3->Allocate();
- image3->FillBuffer(0);
- newSpacing[0] = spacing[1]; newSpacing[1] = spacing[2];
- image3->SetSpacing(newSpacing);
- NewImageType::Pointer image1m = NewImageType::New();
- image1m->SetRegions(region1m);
- image1m->Allocate();
- image1m->FillBuffer(0);
- newSpacing[0] = spacing[0]; newSpacing[1] = spacing[1];
- image1m->SetSpacing(newSpacing);
- NewImageType::Pointer image2m = NewImageType::New();
- image2m->SetRegions(region2m);
- image2m->Allocate();
- image2m->FillBuffer(0);
- newSpacing[0] = spacing[0]; newSpacing[1] = spacing[2];
- image2m->SetSpacing(newSpacing);
- NewImageType::Pointer image3m = NewImageType::New();
- image3m->SetRegions(region3m);
- image3m->Allocate();
- image3m->FillBuffer(0);
- newSpacing[0] = spacing[1]; newSpacing[1] = spacing[2];
- image3m->SetSpacing(newSpacing);
-
- for (unsigned int x = 0; x < mask1->GetDimensions()[0]; ++x)
- {
- for (unsigned int y = 0; y < mask1->GetDimensions()[1]; ++y)
- {
- for (unsigned int z = 0; z < mask1->GetDimensions()[2]; ++z)
- {
- NewImageType::IndexType newIndex;
- typename ImageType::IndexType index;
- index[0] = x; index[1] = y; index[2] = z;
- double pixel = itkImage->GetPixel(index)+1024;
- pixel = pixel / 1000.0;
- pixel = (pixel < 0)? 0 : pixel;
- newIndex[0] = x; newIndex[1] = y;
- image1->SetPixel(newIndex, image1->GetPixel(newIndex) + pixel);
- newIndex[0] = x; newIndex[1] = z;
- image2->SetPixel(newIndex, image2->GetPixel(newIndex) + pixel);
- newIndex[0] = y; newIndex[1] = z;
- image3->SetPixel(newIndex, image3->GetPixel(newIndex) + pixel);
- if (itkMask->GetPixel(index) > 0 && !param.invert)
- {
- pixel = param.zeroValue + 1024;
- pixel = pixel / 1000.0;
- }
- if (itkMask->GetPixel(index) < 1 && param.invert)
- {
- pixel = param.zeroValue + 1024;
- pixel = pixel / 1000.0;
- }
- pixel = (pixel < 0)? 0 : pixel;
- newIndex[0] = x; newIndex[1] = y;
- image1m->SetPixel(newIndex, image1m->GetPixel(newIndex) + pixel);
- newIndex[0] = x; newIndex[1] = z;
- image2m->SetPixel(newIndex, image2m->GetPixel(newIndex) + pixel);
- newIndex[0] = y; newIndex[1] = z;
- image3m->SetPixel(newIndex, image3m->GetPixel(newIndex) + pixel);
- }
- }
- }
-
-
- mitk::Image::Pointer img = mitk::ImportItkImage(image1);
- mitk::IOUtil::Save(img, output + "1.nrrd");
- img = mitk::ImportItkImage(image2);
- mitk::IOUtil::Save(img, output + "2.nrrd");
- img = mitk::ImportItkImage(image3);
- mitk::IOUtil::Save(img, output + "3.nrrd");
- img = mitk::ImportItkImage(image1m);
- mitk::IOUtil::Save(img, output + "1m.nrrd");
- img = mitk::ImportItkImage(image2m);
- mitk::IOUtil::Save(img, output + "2m.nrrd");
- img = mitk::ImportItkImage(image3m);
- mitk::IOUtil::Save(img, output + "3m.nrrd");
-}
-
-int main(int argc, char* argv[])
-{
- mitkCommandLineParser parser;
-
- parser.setTitle("Dicom Loader");
- parser.setCategory("Preprocessing Tools");
- parser.setDescription("");
- parser.setContributor("German Cancer Research Center (DKFZ)");
-
- parser.setArgumentPrefix("-","-");
- // Add command line argument names
- parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text");
- parser.addArgument("input", "i", mitkCommandLineParser::Directory, "Input image:", "Input folder", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("mask", "m", mitkCommandLineParser::Directory, "Input mask:", "Input folder", us::Any(), false, false, false, mitkCommandLineParser::Input);
- parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file:", "Output file", us::Any(), false, false, false, mitkCommandLineParser::Output);
- parser.addArgument("invert", "invert", mitkCommandLineParser::Bool, "Input mask:", "Input folder", us::Any());
- parser.addArgument("zero_value", "zero", mitkCommandLineParser::Float, "Output file:", "Output file", us::Any());
-
- std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
-
- if (parsedArgs.size()==0)
- return EXIT_FAILURE;
-
- // Show a help message
- if ( parsedArgs.count("help") || parsedArgs.count("h"))
- {
- std::cout << parser.helpText();
- return EXIT_SUCCESS;
- }
-
- std::string inputImage = us::any_cast<std::string>(parsedArgs["input"]);
- MITK_INFO << inputImage;
- std::string inputMask = us::any_cast<std::string>(parsedArgs["mask"]);
- MITK_INFO << inputMask;
-
- Params param;
- param.invert = false;
- param.zeroValue = 0;
- if (parsedArgs.count("invert"))
- {
- param.invert = true;
- }
- if (parsedArgs.count("zero_value"))
- {
- param.zeroValue = us::any_cast<float>(parsedArgs["zero_value"]);
- }
-
-
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(inputImage);
- mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(inputMask);
-
- AccessByItk_3(image, CreateXRay, mask, parsedArgs["output"].ToString(),param);
-
- //const mitk::Image::Pointer image = *imageIter;
- //mitk::IOUtil::SaveImage(image,outFileName);
-
-
-
- return EXIT_SUCCESS;
-}
diff --git a/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter.hxx b/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter.hxx
index bb0e407288..dfd8c8383b 100644
--- a/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter.hxx
+++ b/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter.hxx
@@ -1,396 +1,396 @@
/*============================================================================
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.
============================================================================*/
/*=========================================================================
*
* Copyright Insight Software Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef __itkEnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter_hxx
#define __itkEnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter_hxx
#include "itkEnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter.h"
#include "itkConstNeighborhoodIterator.h"
#include "itkNeighborhood.h"
#include "vnl/vnl_math.h"
#include "itkMacro.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkLabelStatisticsImageFilter.h"
#include "itkScalarConnectedComponentImageFilter.h"
#include "itkRelabelComponentImageFilter.h"
#include "itkCastImageFilter.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
namespace itk
{
namespace Statistics
{
template<typename TImageType, typename THistogramFrequencyContainer>
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter() :
m_NumberOfBinsPerAxis( itkGetStaticConstMacro( DefaultBinsPerAxis ) ),
m_Min( NumericTraits<PixelType>::NonpositiveMin() ),
m_Max( NumericTraits<PixelType>::max() ),
m_MinDistance( NumericTraits<RealType>::ZeroValue() ),
m_MaxDistance( NumericTraits<RealType>::max() ),
m_InsidePixelValue( NumericTraits<PixelType>::OneValue() )
{
this->SetNumberOfRequiredInputs( 1 );
this->SetNumberOfRequiredOutputs( 1 );
const unsigned int measurementVectorSize = 1;
this->ProcessObject::SetNthOutput( 0, this->MakeOutput( 0 ) );
this->ProcessObject::SetNthOutput( 1, this->MakeOutput( 1 ) );
HistogramType *output = const_cast<HistogramType *>( this->GetOutput() );
output->SetMeasurementVectorSize( measurementVectorSize );
m_siMatrix = new double[m_NumberOfBinsPerAxis];
for(unsigned int i = 0; i < m_NumberOfBinsPerAxis; i++)
{
m_siMatrix[i] = 0;
}
this->m_LowerBound.SetSize( measurementVectorSize );
this->m_UpperBound.SetSize( measurementVectorSize );
this->m_LowerBound[0] = this->m_Min;
this->m_LowerBound[1] = this->m_MinDistance;
this->m_UpperBound[0] = this->m_Max;
this->m_UpperBound[1] = this->m_MaxDistance;
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetOffset( const OffsetType offset )
{
OffsetVectorPointer offsetVector = OffsetVector::New();
offsetVector->push_back( offset );
this->SetOffsets( offsetVector );
MITK_WARN << "We now have " << this->GetOffsets()->size() << " offsets in matrixgenerator";
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::AddOffsets( const std::vector<OffsetType> _offsets )
{
OffsetVectorPointer offsetVector = OffsetVector::New();
typename OffsetVector::ConstIterator offsets;
//MITK_WARN << "We have " << this->GetOffsets()->size() << " offsets!";
for( std::size_t i = 0; i < _offsets.size(); i++)
{
offsetVector->push_back(_offsets[i]);
auto k = _offsets[i];
this->NormalizeOffsetDirection(k);
offsetVector->push_back(k);
}
this->SetOffsets( offsetVector );
MITK_WARN << "We now have " << this->GetOffsets()->size() << " offsets in matrixgenerator";
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetInput( const ImageType *image )
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput( 0, const_cast<ImageType *>( image ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetMaskImage( const ImageType *image )
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput( 1, const_cast<ImageType *>( image ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
const TImageType *
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::GetInput() const
{
if( this->GetNumberOfInputs() < 1 )
{
return ITK_NULLPTR;
}
return static_cast<const ImageType *>( this->ProcessObject::GetInput( 0 ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
const TImageType *
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::GetMaskImage() const
{
if( this->GetNumberOfInputs() < 2 )
{
return ITK_NULLPTR;
}
return static_cast<const ImageType *>( this->ProcessObject::GetInput( 1 ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
const typename EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType,
THistogramFrequencyContainer >::HistogramType *
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::GetOutput() const
{
const HistogramType *output =
static_cast<const HistogramType *>( this->ProcessObject::GetOutput( 0 ) );
return output;
}
template<typename TImageType, typename THistogramFrequencyContainer>
double* EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::GetSiMatrix() const
{
return m_siMatrix;
}
template<typename TImageType, typename THistogramFrequencyContainer>
typename EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType,
THistogramFrequencyContainer>::DataObjectPointer
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::MakeOutput( DataObjectPointerArraySizeType itkNotUsed( idx ) )
{
return HistogramType::New().GetPointer();
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::GenerateData()
{
HistogramType *output =
static_cast<HistogramType *>( this->ProcessObject::GetOutput( 0 ) );
const ImageType * inputImage = this->GetInput();
const ImageType * maskImage = this->GetMaskImage();
// First, create an appropriate histogram with the right number of bins
// and mins and maxes correct for the image type.
typename HistogramType::SizeType size( output->GetMeasurementVectorSize() );
size.Fill( this->m_NumberOfBinsPerAxis );
this->m_LowerBound[0] = this->m_Min;
this->m_LowerBound[1] = this->m_MinDistance;
this->m_UpperBound[0] = this->m_Max;
this->m_UpperBound[1] = this->m_MaxDistance;
output->Initialize( size, this->m_LowerBound, this->m_UpperBound );
MeasurementVectorType run( output->GetMeasurementVectorSize() );
typename HistogramType::IndexType hIndex;
//Cast the image to a float image - with no respect to the incoming image
//to prevent some non-templated itk issues
typedef itk::Image<float, 3> FloatImageType;
typedef itk::CastImageFilter<ImageType, FloatImageType> CastFilterType;
typename CastFilterType::Pointer caster = CastFilterType::New();
caster->SetInput(inputImage);
caster->Update();
typename FloatImageType::Pointer floatImage = caster->GetOutput();
//Cast the mask to an unsigned short image - with no respect to the incomimg maskimage
//to prevent some non-templated itk issues
typedef unsigned short LabelPixelType;
typedef itk::Image<LabelPixelType, 3 > LabelImageType;
typedef itk::CastImageFilter<ImageType, LabelImageType> MaskCastFilterType;
typename MaskCastFilterType::Pointer maskCaster = MaskCastFilterType::New();
maskCaster->SetInput(maskImage);
maskCaster->Update();
//Set all values out of the mask to nans.
typedef itk::MaskImageFilter< FloatImageType, LabelImageType, FloatImageType > MaskFilterType;
typename MaskFilterType::Pointer maskFilter = MaskFilterType::New();
maskFilter->SetInput(floatImage);
maskFilter->SetMaskImage(maskCaster->GetOutput());
maskFilter->SetOutsideValue( std::numeric_limits<float>::quiet_NaN());
maskFilter->Update();
FloatImageType::Pointer floatImageMasked = maskFilter->GetOutput();
typedef ConstNeighborhoodIterator<ImageType> NeighborhoodIteratorType;
typename NeighborhoodIteratorType::RadiusType radius;
radius.Fill( 1 );
NeighborhoodIteratorType neighborIt( radius,
inputImage, inputImage->GetRequestedRegion() );
for( neighborIt.GoToBegin(); !neighborIt.IsAtEnd(); ++neighborIt )
{
const PixelType centerPixelIntensity = neighborIt.GetCenterPixel();
IndexType centerIndex = neighborIt.GetIndex();
FloatImageType::IndexType cIndex;
cIndex[0] = centerIndex[0];
cIndex[1] = centerIndex[1];
cIndex[2] = centerIndex[2];
float centerFloatPixel = floatImageMasked->GetPixel(cIndex);
int px = 0;
PixelType sum = 0.0;
bool canCalculate = true;
typename OffsetVector::ConstIterator offsets;
for( offsets = this->GetOffsets()->Begin();
offsets != this->GetOffsets()->End(); offsets++ )
{
OffsetType offset = offsets.Value();
IndexType index;
index = centerIndex + offset;
if(!inputImage->GetRequestedRegion().IsInside(index))
{
canCalculate = false;
break;
}
PixelType offsetPixel = inputImage->GetPixel(index);
FloatImageType::IndexType fIndex;
fIndex[0] = index[0];
fIndex[1] = index[1];
fIndex[2] = index[2];
float floatPixel = floatImageMasked->GetPixel(fIndex);
//We have a nan here
if(floatPixel != floatPixel || centerFloatPixel!= centerFloatPixel)
{
canCalculate = false;
break;
}
sum += offsetPixel;
px++;
}
//If we have a nan in the neighbourhood, continue
if(!canCalculate)
continue;
PixelType mean = sum / px;
double si = std::abs<double>(mean-centerPixelIntensity);
run[0] = centerPixelIntensity;
//Check for NaN and inf
if(run[0] == run[0] && !std::isinf(std::abs(run[0])))
{
output->GetIndex( run, hIndex );
output->IncreaseFrequencyOfIndex( hIndex, 1 );
m_siMatrix[hIndex[0]] += si;
}
//MITK_WARN << " -> In this round we added: " << centerIndex << " with value " << centerPixelIntensity << " and si = " << si;
//MITK_WARN << " -> Values are now siMatrix["<<hIndex[0]<<"]: " << m_siMatrix[hIndex[0]];
//MITK_WARN << " -> Values are now niMatrix: " << output->GetFrequency(hIndex) << "/" << run;
}
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetPixelValueMinMax( PixelType min, PixelType max )
{
if( this->m_Min != min || this->m_Max != max )
{
itkDebugMacro( "setting Min to " << min << "and Max to " << max );
this->m_Min = min;
this->m_Max = max;
this->Modified();
}
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetDistanceValueMinMax( RealType min, RealType max )
{
if( this->m_MinDistance != min || this->m_MaxDistance != max )
{
itkDebugMacro( "setting MinDistance to " << min << "and MaxDistance to "
<< max );
this->m_MinDistance = min;
this->m_MaxDistance = max;
this->Modified();
}
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::PrintSelf( std::ostream& os, Indent indent ) const
{
Superclass::PrintSelf( os,indent );
os << indent << "Offsets: " << this->GetOffsets() << std::endl;
os << indent << "Min: " << this->m_Min << std::endl;
os << indent << "Max: " << this->m_Max << std::endl;
os << indent << "Min distance: " << this->m_MinDistance << std::endl;
os << indent << "Max distance: " << this->m_MaxDistance << std::endl;
os << indent << "NumberOfBinsPerAxis: " << this->m_NumberOfBinsPerAxis
<< std::endl;
os << indent << "InsidePixelValue: " << this->m_InsidePixelValue << std::endl;
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter<TImageType, THistogramFrequencyContainer>
::NormalizeOffsetDirection(OffsetType &offset)
{
//MITK_WARN <<" -> NGTDM old offset = " << offset;
itkDebugMacro("old offset = " << offset << std::endl);
int sign = 1;
bool metLastNonZero = false;
for (int i = offset.GetOffsetDimension()-1; i>=0; i--)
{
if (metLastNonZero)
{
offset[i] *= sign;
}
else if (offset[i] != 0)
{
sign = (offset[i] > 0 ) ? 1 : -1;
metLastNonZero = true;
offset[i] *= sign;
}
}
//MITK_WARN << " ->NGTDM new offset = " << offset;
itkDebugMacro("new offset = " << offset << std::endl);
}
} // end of namespace Statistics
} // end of namespace itk
#endif
diff --git a/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToSizeZoneMatrixFilter.hxx b/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToSizeZoneMatrixFilter.hxx
index 80ecac0cd5..88389fd5d9 100644
--- a/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToSizeZoneMatrixFilter.hxx
+++ b/Modules/Classification/CLUtilities/include/itkEnhancedScalarImageToSizeZoneMatrixFilter.hxx
@@ -1,405 +1,405 @@
/*============================================================================
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.
============================================================================*/
/*=========================================================================
*
* Copyright Insight Software Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef __itkEnhancedScalarImageToSizeZoneMatrixFilter_hxx
#define __itkEnhancedScalarImageToSizeZoneMatrixFilter_hxx
#include "itkEnhancedScalarImageToSizeZoneMatrixFilter.h"
#include "itkConstNeighborhoodIterator.h"
#include "itkNeighborhood.h"
#include "vnl/vnl_math.h"
#include "itkMacro.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkLabelStatisticsImageFilter.h"
#include "itkScalarConnectedComponentImageFilter.h"
#include "itkRelabelComponentImageFilter.h"
#include "itkCastImageFilter.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
namespace itk
{
namespace Statistics
{
template<typename TImageType, typename THistogramFrequencyContainer>
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::EnhancedScalarImageToSizeZoneMatrixFilter() :
m_NumberOfBinsPerAxis( itkGetStaticConstMacro( DefaultBinsPerAxis ) ),
m_Min( NumericTraits<PixelType>::NonpositiveMin() ),
m_Max( NumericTraits<PixelType>::max() ),
m_MinDistance( NumericTraits<RealType>::ZeroValue() ),
m_MaxDistance( NumericTraits<RealType>::max() ),
m_InsidePixelValue( NumericTraits<PixelType>::OneValue() )
{
this->SetNumberOfRequiredInputs( 1 );
this->SetNumberOfRequiredOutputs( 1 );
const unsigned int measurementVectorSize = 2;
this->ProcessObject::SetNthOutput( 0, this->MakeOutput( 0 ) );
HistogramType *output = const_cast<HistogramType *>( this->GetOutput() );
output->SetMeasurementVectorSize( measurementVectorSize );
this->m_LowerBound.SetSize( measurementVectorSize );
this->m_UpperBound.SetSize( measurementVectorSize );
this->m_LowerBound[0] = this->m_Min;
this->m_LowerBound[1] = this->m_MinDistance;
this->m_UpperBound[0] = this->m_Max;
this->m_UpperBound[1] = this->m_MaxDistance;
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetOffset( const OffsetType offset )
{
OffsetVectorPointer offsetVector = OffsetVector::New();
offsetVector->push_back( offset );
this->SetOffsets( offsetVector );
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetInput( const ImageType *image )
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput( 0, const_cast<ImageType *>( image ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetMaskImage( const ImageType *image )
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput( 1, const_cast<ImageType *>( image ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
const TImageType *
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::GetInput() const
{
if( this->GetNumberOfInputs() < 1 )
{
return ITK_NULLPTR;
}
return static_cast<const ImageType *>( this->ProcessObject::GetInput( 0 ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
const TImageType *
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::GetMaskImage() const
{
if( this->GetNumberOfInputs() < 2 )
{
return ITK_NULLPTR;
}
return static_cast<const ImageType *>( this->ProcessObject::GetInput( 1 ) );
}
template<typename TImageType, typename THistogramFrequencyContainer>
const typename EnhancedScalarImageToSizeZoneMatrixFilter<TImageType,
THistogramFrequencyContainer >::HistogramType *
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::GetOutput() const
{
const HistogramType *output =
static_cast<const HistogramType *>( this->ProcessObject::GetOutput( 0 ) );
return output;
}
template<typename TImageType, typename THistogramFrequencyContainer>
typename EnhancedScalarImageToSizeZoneMatrixFilter<TImageType,
THistogramFrequencyContainer>::DataObjectPointer
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::MakeOutput( DataObjectPointerArraySizeType itkNotUsed( idx ) )
{
return HistogramType::New().GetPointer();
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::GenerateData()
{
HistogramType *output =
static_cast<HistogramType *>( this->ProcessObject::GetOutput( 0 ) );
const ImageType * inputImage = this->GetInput();
const ImageType * maskImage = this->GetMaskImage();
// First, create an appropriate histogram with the right number of bins
// and mins and maxes correct for the image type.
typename HistogramType::SizeType size( output->GetMeasurementVectorSize() );
size.Fill( this->m_NumberOfBinsPerAxis );
this->m_LowerBound[0] = this->m_Min;
this->m_LowerBound[1] = this->m_MinDistance;
this->m_UpperBound[0] = this->m_Max;
this->m_UpperBound[1] = this->m_MaxDistance;
output->Initialize( size, this->m_LowerBound, this->m_UpperBound );
MeasurementVectorType run( output->GetMeasurementVectorSize() );
typename HistogramType::IndexType hIndex;
//Cast the image to a float image - with no respect to the incoming image
//to prevent some non-templated itk issues
typedef itk::Image<float, 3> FloatImageType;
typedef itk::CastImageFilter<ImageType, FloatImageType> CastFilterType;
typename CastFilterType::Pointer caster = CastFilterType::New();
caster->SetInput(inputImage);
caster->Update();
typename FloatImageType::Pointer floatImage = caster->GetOutput();
//MITK_WARN << "InputImage casted.";
//Cast the mask to an unsigned short image - with no respect to the incomimg maskimage
//to prevent some non-templated itk issues
typedef unsigned short LabelPixelType;
typedef itk::Image<LabelPixelType, 3 > LabelImageType;
typedef itk::CastImageFilter<ImageType, LabelImageType> MaskCastFilterType;
typename MaskCastFilterType::Pointer maskCaster = MaskCastFilterType::New();
maskCaster->SetInput(maskImage);
maskCaster->Update();
//MITK_WARN << "MaskImage casted.";
//Set all values out of the mask to (m_Min + m_Max) / 2.
typedef itk::MaskImageFilter< FloatImageType, LabelImageType, FloatImageType > MaskFilterType;
typename MaskFilterType::Pointer maskFilter = MaskFilterType::New();
maskFilter->SetInput(floatImage);
maskFilter->SetMaskImage(maskCaster->GetOutput());
maskFilter->SetOutsideValue((m_Max + m_Min) / 2);
maskFilter->Update();
//MITK_WARN << "InputImage masked.";
//Rescale intensity to match the size of the histogram
typedef itk::Image< unsigned int, 3 > OutputImageType;
typedef itk::RescaleIntensityImageFilter< FloatImageType,OutputImageType> RescalerType;
typename RescalerType::Pointer rescaler = RescalerType::New();
//We use 0 for nans, all valid numbers will be 1 < x < size
rescaler->SetOutputMinimum( 1 );
rescaler->SetOutputMaximum( size[0] );
rescaler->SetInput(maskFilter->GetOutput());
rescaler->Update();
typename OutputImageType::Pointer rescaled = rescaler->GetOutput();
//MITK_WARN << "Intensities rescaled.";
//Write back the nans because they get lost during rescaling
int xx = inputImage->GetLargestPossibleRegion().GetSize()[0];
int yy = inputImage->GetLargestPossibleRegion().GetSize()[1];
int zz = inputImage->GetLargestPossibleRegion().GetSize()[2];
for (int x = 0; x < xx; x++)
{
for (int y = 0; y < yy; y++)
{
for (int z = 0; z < zz; z++)
{
FloatImageType::IndexType indexF;
indexF[0] = x;
indexF[1] = y;
indexF[2] = z;
OutputImageType::IndexType indexO;
indexO[0] = x;
indexO[1] = y;
indexO[2] = z;
//Is Pixel NaN?
if(floatImage->GetPixel(indexF) != floatImage->GetPixel(indexF))
{
rescaled->SetPixel(indexO,0);
}
}
}
}
//All nans are now 0, the valid values are within [1,numberOfBins]
/*
OutputImageType::IndexType indexO;
indexO[0] = 0;
indexO[1] = 2;
indexO[2] = 1;
MITK_WARN << "is 0: " << rescaled->GetPixel(indexO);
indexO[0] = 0;
indexO[1] = 0;
indexO[2] = 0;
MITK_WARN << "is 1: " << rescaled->GetPixel(indexO);
*/
PixelType distanceThreshold = 1 - mitk::eps;
//Calculate the connected components
typedef itk::ScalarConnectedComponentImageFilter <OutputImageType, OutputImageType, LabelImageType >
ConnectedComponentImageFilterType;
typename ConnectedComponentImageFilterType::Pointer connected = ConnectedComponentImageFilterType::New ();
connected->SetInput(rescaled);
connected->SetMaskImage(maskCaster->GetOutput());
connected->SetDistanceThreshold(distanceThreshold);
connected->Update();
/*
indexO[0] = 0;
indexO[1] = 2;
indexO[2] = 1;
MITK_WARN << "is 0: " << (connected->GetOutput())->GetPixel(indexO);
indexO[0] = 0;
indexO[1] = 0;
indexO[2] = 0;
MITK_WARN << "is 1: " << (connected->GetOutput())->GetPixel(indexO);
MITK_WARN << "Connected components calculated.";
*/
//Relabel the components
typedef itk::RelabelComponentImageFilter <OutputImageType, OutputImageType > RelabelFilterType;
typename RelabelFilterType::Pointer relabel = RelabelFilterType::New();
typename RelabelFilterType::ObjectSizeType minSize = 1;
relabel->SetInput(connected->GetOutput());
relabel->SetMinimumObjectSize(minSize);
relabel->Update();
//MITK_WARN << "Components relabeled.";
//Get the stats of the componentes
typedef itk::LabelStatisticsImageFilter< FloatImageType, OutputImageType> LabelStatisticsImageFilterType;
typename LabelStatisticsImageFilterType::Pointer labelStatisticsImageFilter =
LabelStatisticsImageFilterType::New();
labelStatisticsImageFilter->SetLabelInput( relabel->GetOutput() );
labelStatisticsImageFilter->SetInput(floatImage);
labelStatisticsImageFilter->UseHistogramsOn(); // needed to compute median
labelStatisticsImageFilter->Update();
/*
std::cout << "Number of labels: "
<< labelStatisticsImageFilter->GetNumberOfLabels() << std::endl;
std::cout << std::endl;
*/
typedef typename LabelStatisticsImageFilterType::ValidLabelValuesContainerType ValidLabelValuesType;
for(typename ValidLabelValuesType::const_iterator vIt = labelStatisticsImageFilter->GetValidLabelValues().begin();
vIt != labelStatisticsImageFilter->GetValidLabelValues().end();
++vIt)
{
if ( labelStatisticsImageFilter->HasLabel(*vIt) )
{
LabelPixelType labelValue = *vIt;
run[0] = labelStatisticsImageFilter->GetMean( labelValue );
run[1] = labelStatisticsImageFilter->GetCount( labelValue );
//Check for NaN and inf
if(run[0] == run[0] && !std::isinf(std::abs(run[0])))
{
output->GetIndex( run, hIndex );
output->IncreaseFrequencyOfIndex( hIndex, 1 );
/*
MITK_INFO << "Adding a region:";
MITK_INFO << "\tmin: "
<< labelStatisticsImageFilter->GetMinimum( labelValue );
MITK_INFO << "\tmax: "
<< labelStatisticsImageFilter->GetMaximum( labelValue );
MITK_INFO << "\tmean: "
<< labelStatisticsImageFilter->GetMean( labelValue );
MITK_INFO << "\tcount: "
<< labelStatisticsImageFilter->GetCount( labelValue );
*/
}
}
}
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetPixelValueMinMax( PixelType min, PixelType max )
{
if( this->m_Min != min || this->m_Max != max )
{
itkDebugMacro( "setting Min to " << min << "and Max to " << max );
this->m_Min = min;
this->m_Max = max;
this->Modified();
}
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::SetDistanceValueMinMax( RealType min, RealType max )
{
if( this->m_MinDistance != min || this->m_MaxDistance != max )
{
itkDebugMacro( "setting MinDistance to " << min << "and MaxDistance to "
<< max );
this->m_MinDistance = min;
this->m_MaxDistance = max;
this->Modified();
}
}
template<typename TImageType, typename THistogramFrequencyContainer>
void
EnhancedScalarImageToSizeZoneMatrixFilter<TImageType, THistogramFrequencyContainer>
::PrintSelf( std::ostream& os, Indent indent ) const
{
Superclass::PrintSelf( os,indent );
os << indent << "Offsets: " << this->GetOffsets() << std::endl;
os << indent << "Min: " << this->m_Min << std::endl;
os << indent << "Max: " << this->m_Max << std::endl;
os << indent << "Min distance: " << this->m_MinDistance << std::endl;
os << indent << "Max distance: " << this->m_MaxDistance << std::endl;
os << indent << "NumberOfBinsPerAxis: " << this->m_NumberOfBinsPerAxis
<< std::endl;
os << indent << "InsidePixelValue: " << this->m_InsidePixelValue << std::endl;
}
} // end of namespace Statistics
} // end of namespace itk
#endif
diff --git a/Modules/Classification/CLUtilities/test/files.cmake b/Modules/Classification/CLUtilities/test/files.cmake
index a2d8b7b28d..08b44d0fcc 100644
--- a/Modules/Classification/CLUtilities/test/files.cmake
+++ b/Modules/Classification/CLUtilities/test/files.cmake
@@ -1,18 +1,16 @@
set(MODULE_TESTS
mitkGIFCooc2Test.cpp
mitkGIFCurvatureStatisticTest.cpp
mitkGIFFirstOrderHistogramStatisticsTest.cpp
mitkGIFFirstOrderNumericStatisticsTest.cpp
mitkGIFFirstOrderStatisticsTest.cpp
mitkGIFGreyLevelDistanceZoneTest.cpp
mitkGIFGreyLevelSizeZoneTest.cpp
mitkGIFImageDescriptionFeaturesTest.cpp
mitkGIFIntensityVolumeHistogramTest.cpp
mitkGIFLocalIntensityTest.cpp
mitkGIFNeighbourhoodGreyToneDifferenceFeaturesTest.cpp
mitkGIFNeighbouringGreyLevelDependenceFeatureTest.cpp
mitkGIFVolumetricDensityStatisticsTest.cpp
mitkGIFVolumetricStatisticsTest.cpp
- #mitkSmoothedClassProbabilitesTest.cpp
- #mitkGlobalFeaturesTest.cpp
)
diff --git a/Modules/Classification/CLUtilities/test/mitkGlobalFeaturesTest.cpp b/Modules/Classification/CLUtilities/test/mitkGlobalFeaturesTest.cpp
deleted file mode 100644
index aca52a5499..0000000000
--- a/Modules/Classification/CLUtilities/test/mitkGlobalFeaturesTest.cpp
+++ /dev/null
@@ -1,312 +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 <mitkTestingMacros.h>
-#include <mitkTestFixture.h>
-#include "mitkIOUtil.h"
-
-#include <mitkImageCast.h>
-#include <mitkGIFFirstOrderStatistics.h>
-#include <mitkGIFCooccurenceMatrix.h>
-#include <mitkGIFGreyLevelRunLength.h>
-#include <cmath>
-
-#include <mitkImageGenerator.h>
-
-template <typename TPixelType>
-static mitk::Image::Pointer GenerateMaskImage(unsigned int dimX,
- unsigned int dimY,
- unsigned int dimZ,
- float spacingX = 1,
- float spacingY = 1,
- float spacingZ = 1)
-{
- typedef itk::Image< TPixelType, 3 > ImageType;
- typename ImageType::RegionType imageRegion;
- imageRegion.SetSize(0, dimX);
- imageRegion.SetSize(1, dimY);
- imageRegion.SetSize(2, dimZ);
- typename ImageType::SpacingType spacing;
- spacing[0] = spacingX;
- spacing[1] = spacingY;
- spacing[2] = spacingZ;
-
- mitk::Point3D origin; origin.Fill(0.0);
- itk::Matrix<double, 3, 3> directionMatrix; directionMatrix.SetIdentity();
-
- typename ImageType::Pointer image = ImageType::New();
- image->SetSpacing( spacing );
- image->SetOrigin( origin );
- image->SetDirection( directionMatrix );
- image->SetLargestPossibleRegion( imageRegion );
- image->SetBufferedRegion( imageRegion );
- image->SetRequestedRegion( imageRegion );
- image->Allocate();
- image->FillBuffer(1);
-
- mitk::Image::Pointer mitkImage = mitk::Image::New();
- mitkImage->InitializeByItk( image.GetPointer() );
- mitkImage->SetVolume( image->GetBufferPointer() );
- return mitkImage;
-}
-
-template <typename TPixelType>
-static mitk::Image::Pointer GenerateGradientWithDimXImage(unsigned int dimX,
- unsigned int dimY,
- unsigned int dimZ,
- float spacingX = 1,
- float spacingY = 1,
- float spacingZ = 1)
-{
- typedef itk::Image< TPixelType, 3 > ImageType;
- typename ImageType::RegionType imageRegion;
- imageRegion.SetSize(0, dimX);
- imageRegion.SetSize(1, dimY);
- imageRegion.SetSize(2, dimZ);
- typename ImageType::SpacingType spacing;
- spacing[0] = spacingX;
- spacing[1] = spacingY;
- spacing[2] = spacingZ;
-
- mitk::Point3D origin; origin.Fill(0.0);
- itk::Matrix<double, 3, 3> directionMatrix; directionMatrix.SetIdentity();
-
- typename ImageType::Pointer image = ImageType::New();
- image->SetSpacing( spacing );
- image->SetOrigin( origin );
- image->SetDirection( directionMatrix );
- image->SetLargestPossibleRegion( imageRegion );
- image->SetBufferedRegion( imageRegion );
- image->SetRequestedRegion( imageRegion );
- image->Allocate();
- image->FillBuffer(0.0);
-
- typedef itk::ImageRegionIterator<ImageType> IteratorOutputType;
- IteratorOutputType it(image, imageRegion);
- it.GoToBegin();
-
- TPixelType val = 0;
- while(!it.IsAtEnd())
- {
- it.Set(val % dimX);
- val++;
- ++it;
- }
-
- mitk::Image::Pointer mitkImage = mitk::Image::New();
- mitkImage->InitializeByItk( image.GetPointer() );
- mitkImage->SetVolume( image->GetBufferPointer() );
- return mitkImage;
-}
-
-
-class mitkGlobalFeaturesTestSuite : public mitk::TestFixture
-{
- CPPUNIT_TEST_SUITE(mitkGlobalFeaturesTestSuite );
-
- MITK_TEST(FirstOrder_SinglePoint);
- MITK_TEST(FirstOrder_QubicArea);
- //MITK_TEST(RunLenght_QubicArea);
- MITK_TEST(Coocurrence_QubicArea);
- //MITK_TEST(TestFirstOrderStatistic);
- // MITK_TEST(TestThreadedDecisionForest);
-
- CPPUNIT_TEST_SUITE_END();
-
-private:
-
- typedef itk::Image<double,3> ImageType;
- typedef itk::Image<unsigned char,3> MaskType;
-
- mitk::Image::Pointer m_Image,m_Mask,m_Mask1;
- ImageType::Pointer m_ItkImage;
- MaskType::Pointer m_ItkMask,m_ItkMask1;
-
- mitk::Image::Pointer m_GradientImage, m_GradientMask;
-
-public:
-
- void setUp(void) override
- {
- // Load Image Data
- m_Image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Pic3D.nrrd"));
- mitk::CastToItkImage(m_Image,m_ItkImage);
-
- // Create a single mask with only one pixel within the regions
- mitk::Image::Pointer mask1 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Pic3D.nrrd"));
- mitk::CastToItkImage(mask1,m_ItkMask);
- m_ItkMask->FillBuffer(0);
- MaskType::IndexType index;
- index[0]=88;index[1]=81;index[2]=13;
- m_ItkMask->SetPixel(index, 1);
- MITK_INFO << "Pixel Value: "<<m_ItkImage->GetPixel(index);
- mitk::CastToMitkImage(m_ItkMask, m_Mask);
-
- // Create a mask with a covered region
- mitk::Image::Pointer lmask1 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Pic3D.nrrd"));
- mitk::CastToItkImage(lmask1,m_ItkMask1);
- m_ItkMask1->FillBuffer(0);
- int range=2;
- for (int x = 88-range;x < 88+range+1;++x)
- {
- for (int y=81-range;y<81+range+1;++y)
- {
- for (int z=13-range;z<13+range+1;++z)
- {
- index[0] = x;
- index[1] = y;
- index[2] = z;
- //MITK_INFO << "Pixel: " <<m_ItkImage->GetPixel(index);
- m_ItkMask1->SetPixel(index, 1);
- }
- }
- }
- mitk::CastToMitkImage(m_ItkMask1, m_Mask1);
-
- m_GradientImage=GenerateGradientWithDimXImage<unsigned char>(5,5,5);
- m_GradientMask = GenerateMaskImage<unsigned char>(5,5,5);
- }
-
- void FirstOrder_SinglePoint()
- {
- mitk::GIFFirstOrderStatistics::Pointer calculator = mitk::GIFFirstOrderStatistics::New();
- //calculator->SetHistogramSize(4096);
- //calculator->SetUseCtRange(true);
- auto features = calculator->CalculateFeatures(m_Image, m_Mask);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
-
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range of a single pixel should be 0",0.0, results["FirstOrder Range"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",1.0, results["FirstOrder Uniformity"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",0.0, results["FirstOrder Entropy"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",352.0, results["FirstOrder RMS"], 0.01);
- CPPUNIT_ASSERT_EQUAL_MESSAGE("The Kurtosis of a single pixel should be undefined",results["FirstOrder Kurtosis"]==results["FirstOrder Kurtosis"], false);
- CPPUNIT_ASSERT_EQUAL_MESSAGE("The Skewness of a single pixel should be undefined",results["FirstOrder Skewness"]==results["FirstOrder Skewness"], false);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",0, results["FirstOrder Mean absolute deviation"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0, results["FirstOrder Covered Image Intensity Range"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-352, results["FirstOrder Minimum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",-352, results["FirstOrder Maximum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-352, results["FirstOrder Mean"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",0, results["FirstOrder Variance"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-352, results["FirstOrder Sum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-352, results["FirstOrder Median"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",0, results["FirstOrder Standard deviation"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",1, results["FirstOrder No. of Voxel"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",352*352, results["FirstOrder Energy"], 0.0);
- // MITK_ASSERT_EQUAL(results["FirstOrder Range"]==0.0,true,"The range of a single pixel should be 0");
- }
-
- void FirstOrder_QubicArea()
- {
- mitk::GIFFirstOrderStatistics::Pointer calculator = mitk::GIFFirstOrderStatistics::New();
- //calculator->SetHistogramSize(4096);
- //calculator->SetUseCtRange(true);
- auto features = calculator->CalculateFeatures(m_Image, m_Mask1);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
-
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range should be 981",981, results["FirstOrder Range"], 0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",402.895778, results["FirstOrder RMS"], 0.01);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-937, results["FirstOrder Minimum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",44, results["FirstOrder Maximum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-304.448, results["FirstOrder Mean"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-38056, results["FirstOrder Sum"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-202, results["FirstOrder Median"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",125, results["FirstOrder No. of Voxel"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",264.949066, results["FirstOrder Standard deviation"], 0.000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",20290626, results["FirstOrder Energy"], 0.0);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",0.0088960, results["FirstOrder Uniformity"], 0.0000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",-6.853784285, results["FirstOrder Entropy"], 0.000000005);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",70198.0074, results["FirstOrder Variance"], 0.0001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Kurtosis of a single pixel should be 0",2.63480121, results["FirstOrder Kurtosis"], 0.0001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Skewness of a single pixel should be 0",-0.91817318, results["FirstOrder Skewness"], 0.00001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",219.348608, results["FirstOrder Mean absolute deviation"], 0.000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0.41149329, results["FirstOrder Covered Image Intensity Range"], 0.000001);
- }
-
- void RunLenght_QubicArea()
- {
- mitk::GIFGreyLevelRunLength::Pointer calculator = mitk::GIFGreyLevelRunLength::New();
- //calculator->SetHistogramSize(4096);
- auto features = calculator->CalculateFeatures(m_Image, m_Mask1);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
- }
-
- void Coocurrence_QubicArea()
- {
- /*
- * Expected Matrix: (Direction 0,0,1)
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 0 | 20 | 0 | 0 | 0 |
- * |------------------------|
- * | 0 | 0 | 20 | 0 | 0 |
- * |------------------------|
- * | 0 | 0 | 0 | 20 | 0 |
- * |------------------------|
- * | 0 | 0 | 0 | 0 | 20 |
- * |------------------------|
-
- * Expected Matrix: (Direction (1,0,0),(0,1,0))
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- * | 20 | 0 | 0 | 0 | 0 |
- * |------------------------|
- */
-
- mitk::GIFCooccurenceMatrix::Pointer calculator = mitk::GIFCooccurenceMatrix::New();
- //calculator->SetHistogramSize(4096);
- //calculator->SetUseCtRange(true);
- //calculator->SetRange(981);
- calculator->SetDirection(1);
- auto features = calculator->CalculateFeatures(m_GradientImage, m_GradientMask);
-
- std::map<std::string, double> results;
- for (auto iter=features.begin(); iter!=features.end();++iter)
- {
- results[(*iter).first]=(*iter).second;
- MITK_INFO << (*iter).first << " : " << (*iter).second;
- }
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean energy value should be 0.2",0.2, results["co-occ. (1) Energy Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean entropy value should be 0.2",2.321928, results["co-occ. (1) Entropy Means"], 0.000001);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean contrast value should be 0.0",0, results["co-occ. (1) Contrast Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean dissimilarity value should be 0.0",0, results["co-occ. (1) Dissimilarity Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean homogenity1 value should be 1.0",1, results["co-occ. (1) Homogeneity1 Means"], mitk::eps);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean InverseDifferenceMoment value should be 1.0",1, results["co-occ. (1) InverseDifferenceMoment Means"], mitk::eps);
- }
-};
-
-MITK_TEST_SUITE_REGISTRATION(mitkGlobalFeatures)
diff --git a/Modules/Classification/CLUtilities/test/mitkSmoothedClassProbabilitesTest.cpp b/Modules/Classification/CLUtilities/test/mitkSmoothedClassProbabilitesTest.cpp
deleted file mode 100644
index a7b7e977fd..0000000000
--- a/Modules/Classification/CLUtilities/test/mitkSmoothedClassProbabilitesTest.cpp
+++ /dev/null
@@ -1,90 +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 <mitkTestingMacros.h>
-#include <mitkTestFixture.h>
-#include "mitkIOUtil.h"
-
-#include <itkSmoothedClassProbabilites.h>
-#include <mitkImageCast.h>
-
-class mitkSmoothedClassProbabilitesTestSuite : public mitk::TestFixture
-{
-
- CPPUNIT_TEST_SUITE(mitkSmoothedClassProbabilitesTestSuite );
-
- MITK_TEST(TrainSVMClassifier);
- // MITK_TEST(TestThreadedDecisionForest);
-
- CPPUNIT_TEST_SUITE_END();
-
-private:
-
- typedef itk::Image<double,3> ImageType;
- mitk::Image::Pointer p1,p2,p3,pmask;
- ImageType::Pointer i1,i2,i3,imask;
-
-public:
-
-
- void setUp(void)
- {
-
- // Load Image Data
- p1 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/ResultProb_Class-0_0.nrrd"));
- p2 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/ResultProb_Class-1_0.nrrd"));
- p3 = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/ResultProb_Class-2_0.nrrd"));
- pmask = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Classification/Algorithm/mask.nrrd"));
-
- mitk::CastToItkImage(p1,i1);
- mitk::CastToItkImage(p2,i2);
- mitk::CastToItkImage(p3,i3);
- mitk::CastToItkImage(pmask,imask);
- }
-
- void TrainSVMClassifier()
- {
- itk::SmoothedClassProbabilites<ImageType>::Pointer filter = itk::SmoothedClassProbabilites<ImageType>::New();
- filter->SetInput(0,i1);
- filter->SetInput(1,i2);
- filter->SetInput(2,i3);
- filter->SetMaskImage(imask);
- filter->SetSigma(1.0);
- filter->Update();
-
- mitk::Image::Pointer out;
- mitk::CastToMitkImage(filter->GetOutput(), out);
-
- mitk::IOUtil::Save(out, "/Users/jc/test.nrrd");
- }
-
- void TestThreadedDecisionForest()
- {
- // m_LoadedDecisionForest->SetCollection(m_TrainDatacollection);
- // m_LoadedDecisionForest->SetModalities(m_Selected_items);
- // m_LoadedDecisionForest->SetMaskName("ClassMask");
- // m_LoadedDecisionForest->SetResultMask("ResultMask");
- // m_LoadedDecisionForest->SetResultProb("ResultProb");
- // m_LoadedDecisionForest->TestThreaded();
-
- // mitk::DataCollection::Pointer res_col = dynamic_cast<mitk::DataCollection *>(dynamic_cast<mitk::DataCollection *>(m_TrainDatacollection->GetData("Test-Study").GetPointer())->GetData("Test-Subject").GetPointer());
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultMask"),"/Users/jc/res_mask.nrrd");
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultProb_Class-0"),"/Users/jc/res_prob_0.nrrd");
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultProb_Class-1"),"/Users/jc/res_prob_1.nrrd");
- // mitk::IOUtil::Save(res_col->GetMitkImage("ResultProb_Class-2"),"/Users/jc/res_prob_2.nrrd");
- }
-
-};
-
-MITK_TEST_SUITE_REGISTRATION(mitkSmoothedClassProbabilites)
-
-
diff --git a/Modules/Classification/CLVigraRandomForest/CMakeLists.txt b/Modules/Classification/CLVigraRandomForest/CMakeLists.txt
deleted file mode 100644
index e16e415d6a..0000000000
--- a/Modules/Classification/CLVigraRandomForest/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-MITK_CREATE_MODULE(
- DEPENDS MitkCLCore MitkCLUtilities MitkSceneSerializationBase
- #AUTOLOAD_WITH MitkCore
- PACKAGE_DEPENDS
- PRIVATE ITK|IONRRD Vigra
-)
-
-add_subdirectory(test)
diff --git a/Modules/Classification/CLVigraRandomForest/files.cmake b/Modules/Classification/CLVigraRandomForest/files.cmake
deleted file mode 100644
index 358f417862..0000000000
--- a/Modules/Classification/CLVigraRandomForest/files.cmake
+++ /dev/null
@@ -1,25 +0,0 @@
-file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
-
-set(CPP_FILES
-
- mitkModuleActivator.cpp
-
- Classifier/mitkVigraRandomForestClassifier.cpp
- Classifier/mitkPURFClassifier.cpp
-
- Algorithm/itkHessianMatrixEigenvalueImageFilter.cpp
- Algorithm/itkStructureTensorEigenvalueImageFilter.cpp
-
- Splitter/mitkAdditionalRFData.cpp
- Splitter/mitkImpurityLoss.cpp
- Splitter/mitkPUImpurityLoss.cpp
- Splitter/mitkLinearSplitting.cpp
- Splitter/mitkThresholdSplit.cpp
-
- IO/mitkRandomForestIO.cpp
- IO/mitkVigraRandomForestClassifierSerializer.cpp
- IO/mitkDummyLsetReader.cpp
-)
-
-set( TOOL_FILES
-)
diff --git a/Modules/Classification/CLVigraRandomForest/include/itkHessianMatrixEigenvalueImageFilter.h b/Modules/Classification/CLVigraRandomForest/include/itkHessianMatrixEigenvalueImageFilter.h
deleted file mode 100644
index e6b028b2cd..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/itkHessianMatrixEigenvalueImageFilter.h
+++ /dev/null
@@ -1,57 +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.
-
-============================================================================*/
-
-#ifndef ITKHESSIANMATRIXEIGENVALUEIMAGEFILTER_H
-#define ITKHESSIANMATRIXEIGENVALUEIMAGEFILTER_H
-
-#include <itkImageToImageFilter.h>
-
-namespace itk
-{
- template< class TInputImageType, class TOutputImageType = TInputImageType, class TMaskImageType = itk::Image<short,3> >
- class HessianMatrixEigenvalueImageFilter
- : public itk::ImageToImageFilter<TInputImageType, TOutputImageType>
- {
- public:
-
- typedef HessianMatrixEigenvalueImageFilter< TInputImageType, TOutputImageType > Self;
- typedef SmartPointer<Self> Pointer;
- typedef SmartPointer<const Self> ConstPointer;
- typedef ImageToImageFilter< TInputImageType, TOutputImageType > Superclass;
-
- itkFactorylessNewMacro(Self);
- itkCloneMacro(Self);
-
- void SetImageMask(TMaskImageType * maskimage);
-
- itkSetMacro(Sigma,double);
-
- itkGetMacro(Sigma,double);
-
- private:
-
- typename TMaskImageType::Pointer m_ImageMask;
- double m_Sigma;
-
- void GenerateData() override;
- void GenerateOutputInformation() override;
-
- HessianMatrixEigenvalueImageFilter();
- ~HessianMatrixEigenvalueImageFilter() override;
- };
-}
-
-#ifndef ITK_MANUAL_INSTANTIATION
-#include "../src/Algorithm/itkHessianMatrixEigenvalueImageFilter.cpp"
-#endif
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/itkStructureTensorEigenvalueImageFilter.h b/Modules/Classification/CLVigraRandomForest/include/itkStructureTensorEigenvalueImageFilter.h
deleted file mode 100644
index 734fb0ca00..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/itkStructureTensorEigenvalueImageFilter.h
+++ /dev/null
@@ -1,63 +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.
-
-============================================================================*/
-
-#ifndef ITKSTRUCTURETENSOREIGENVALUEIMAGEFILTER_H
-#define ITKSTRUCTURETENSOREIGENVALUEIMAGEFILTER_H
-
-#include <itkImageToImageFilter.h>
-
-namespace itk
-{
- template< class TInputImageType,
- class TOutputImageType = TInputImageType,
- class TMaskImageType = itk::Image<short,3> >
- class StructureTensorEigenvalueImageFilter
- : public itk::ImageToImageFilter<TInputImageType, TOutputImageType>
- {
- public:
-
- typedef StructureTensorEigenvalueImageFilter< TInputImageType, TOutputImageType > Self;
- typedef SmartPointer<Self> Pointer;
- typedef SmartPointer<const Self> ConstPointer;
- typedef ImageToImageFilter< TInputImageType, TOutputImageType > Superclass;
-
- itkFactorylessNewMacro(Self);
- itkCloneMacro(Self);
-
- void SetImageMask(TMaskImageType * maskimage);
-
- itkSetMacro(InnerScale,double);
-
- itkGetMacro(InnerScale,double);
-
- itkSetMacro(OuterScale,double);
-
- itkGetMacro(OuterScale,double);
-
- private:
-
- typename TMaskImageType::Pointer m_ImageMask;
- double m_InnerScale, m_OuterScale;
-
- void GenerateData() override;
- void GenerateOutputInformation() override;
-
- StructureTensorEigenvalueImageFilter();
- ~StructureTensorEigenvalueImageFilter() override;
- };
-}
-
-#ifndef ITK_MANUAL_INSTANTIATION
-#include "../src/Algorithm/itkStructureTensorEigenvalueImageFilter.cpp"
-#endif
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkAdditionalRFData.h b/Modules/Classification/CLVigraRandomForest/include/mitkAdditionalRFData.h
deleted file mode 100644
index e357154fc7..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkAdditionalRFData.h
+++ /dev/null
@@ -1,45 +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.
-
-============================================================================*/
-
-#ifndef mitkAdditionalRFData_h
-#define mitkAdditionalRFData_h
-
-#include <vigra/multi_array.hxx>
-
-
-namespace mitk
-{
- class AdditionalRFDataAbstract
- {
- public:
- // This function is necessary to be able to do dynamic casts
- virtual void NoFunction() = 0;
- virtual ~AdditionalRFDataAbstract() {};
- };
-
- class NoRFData : public AdditionalRFDataAbstract
- {
- public:
- void NoFunction() override { return; }
- ~NoRFData() override {};
- };
-
- class PURFData : public AdditionalRFDataAbstract
- {
- public:
- vigra::ArrayVector<double> m_Kappa;
- void NoFunction() override;
- ~PURFData() override {};
- };
-}
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkDummyLsetReader.h b/Modules/Classification/CLVigraRandomForest/include/mitkDummyLsetReader.h
deleted file mode 100644
index 6bf169120b..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkDummyLsetReader.h
+++ /dev/null
@@ -1,48 +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.
-
-============================================================================*/
-
-#ifndef mitkDummyLsetReader_h
-#define mitkDummyLsetReader_h
-
-#include <mitkAbstractFileReader.h>
-
-namespace mitk
-{
-
-/**
- * Read deprecated *.lset format (Multilabel Image format 2014)
- * @ingroup Process
- */
-class DummyLsetFileReader : public mitk::AbstractFileReader
-{
-public:
-
- DummyLsetFileReader();
- DummyLsetFileReader(const mitk::DummyLsetFileReader& other);
- ~DummyLsetFileReader() override;
-
- using AbstractFileReader::Read;
-
-protected:
- std::vector<itk::SmartPointer<BaseData>> DoRead() override;
-
-
- private:
- DummyLsetFileReader * Clone() const override;
-
-
-};
-
-
-} // end of namespace mitk
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkImpurityLoss.h b/Modules/Classification/CLVigraRandomForest/include/mitkImpurityLoss.h
deleted file mode 100644
index 4a44accc58..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkImpurityLoss.h
+++ /dev/null
@@ -1,69 +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.
-
-============================================================================*/
-
-#ifndef mitkImpurityLoss_h
-#define mitkImpurityLoss_h
-
-#include <vigra/multi_array.hxx>
-#include <vigra/random_forest.hxx>
-#include <mitkAdditionalRFData.h>
-
-namespace mitk
-{
- template <class TLossFunction = vigra::GiniCriterion, class TLabelContainer = vigra::MultiArrayView<2, int>, class TWeightContainer = vigra::MultiArrayView<2, double> >
- class ImpurityLoss
- {
- public:
- typedef TLabelContainer LabelContainerType;
- typedef TWeightContainer WeightContainerType;
-
- template <class T>
- ImpurityLoss(TLabelContainer const &labels,
- vigra::ProblemSpec<T> const &ext,
- AdditionalRFDataAbstract *data);
-
- void Reset();
-
- template <class TDataIterator>
- double Increment(TDataIterator begin, TDataIterator end);
-
- template <class TDataIterator>
- double Decrement(TDataIterator begin, TDataIterator end);
-
- template <class TArray>
- double Init(TArray initCounts);
-
- vigra::ArrayVector<double> const& Response();
-
- void UsePointWeights(bool useWeights);
- bool IsUsingPointWeights();
-
- void SetPointWeights(TWeightContainer weight);
- WeightContainerType GetPointWeights();
-
- private:
- bool m_UsePointWeights;
- TWeightContainer m_PointWeights;
-
- //Variable of origin
- TLabelContainer const& m_Labels;
- vigra::ArrayVector<double> m_Counts;
- vigra::ArrayVector<double> m_ClassWeights;
- double m_TotalCount;
- TLossFunction m_LossFunction;
- };
-
-}
-
-#include <../src/Splitter/mitkImpurityLoss.cpp>
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkLinearSplitting.h b/Modules/Classification/CLVigraRandomForest/include/mitkLinearSplitting.h
deleted file mode 100644
index 4f811100bb..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkLinearSplitting.h
+++ /dev/null
@@ -1,103 +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.
-
-============================================================================*/
-
-#ifndef mitkLinearSplitting_h
-#define mitkLinearSplitting_h
-
-#include <vigra/multi_array.hxx>
-#include <vigra/random_forest.hxx>
-#include <mitkAdditionalRFData.h>
-
-namespace mitk
-{
- template<class TLossAccumulator>
- class LinearSplitting
- {
- public:
- typedef typename TLossAccumulator::WeightContainerType TWeightContainer;
- typedef TWeightContainer WeightContainerType;
-
- LinearSplitting();
-
- template <class T>
- LinearSplitting(vigra::ProblemSpec<T> const &ext);
-
- void UsePointWeights(bool pointWeight);
- bool IsUsingPointWeights();
-
- void UseRandomSplit(bool randomSplit);
- bool IsUsingRandomSplit();
-
- void SetPointWeights(WeightContainerType weight);
- WeightContainerType GetPointWeights();
-
- void SetAdditionalData(AdditionalRFDataAbstract* data);
- AdditionalRFDataAbstract* GetAdditionalData() const;
-
- template <class T>
- void set_external_parameters(vigra::ProblemSpec<T> const &ext);
-
- template <class TDataSourceFeature,
- class TDataSourceLabel,
- class TDataIterator,
- class TArray>
- void operator()(TDataSourceFeature const &column,
- TDataSourceLabel const &labels,
- TDataIterator &begin,
- TDataIterator &end,
- TArray const &regionResponse);
-
- template <class TDataSourceLabel,
- class TDataIterator,
- class TArray>
- double LossOfRegion(TDataSourceLabel const & labels,
- TDataIterator &begin,
- TDataIterator &end,
- TArray const & regionResponse);
-
- double GetMinimumLoss()
- {
- return m_MinimumLoss;
- }
-
- double GetMinimumThreshold()
- {
- return m_MinimumThreshold;
- }
-
- std::ptrdiff_t GetMinimumIndex()
- {
- return m_MinimumIndex;
- }
-
- vigra::ArrayVector<double>* GetBestCurrentCounts()
- {
- return m_BestCurrentCounts;
- }
-
- private:
- bool m_UsePointWeights;
- bool m_UseRandomSplit;
- WeightContainerType m_PointWeights;
- // From original code
- vigra::ArrayVector<double> m_ClassWeights;
- vigra::ArrayVector<double> m_BestCurrentCounts[2];
- double m_MinimumLoss;
- double m_MinimumThreshold;
- std::ptrdiff_t m_MinimumIndex;
- vigra::ProblemSpec<> m_ExtParameter;
- AdditionalRFDataAbstract* m_AdditionalData;
- };
-}
-
-#include <../src/Splitter/mitkLinearSplitting.cpp>
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkPUImpurityLoss.h b/Modules/Classification/CLVigraRandomForest/include/mitkPUImpurityLoss.h
deleted file mode 100644
index a91fa52a9f..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkPUImpurityLoss.h
+++ /dev/null
@@ -1,84 +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.
-
-============================================================================*/
-
-#ifndef mitkPUImpurityLoss_h
-#define mitkPUImpurityLoss_h
-
-#include <vigra/multi_array.hxx>
-#include <vigra/random_forest.hxx>
-#include <mitkAdditionalRFData.h>
-
-namespace mitk
-{
-
- template<class LabelType = double>
- class PURFProblemSpec : vigra::ProblemSpec<LabelType>
- {
- public:
- vigra::ArrayVector<double> kappa_; // if classes have different importance
- };
-
-
- template <class TLossFunction = vigra::GiniCriterion, class TLabelContainer = vigra::MultiArrayView<2, int>, class TWeightContainer = vigra::MultiArrayView<2, double> >
- class PUImpurityLoss
- {
- public:
- typedef TLabelContainer LabelContainerType;
- typedef TWeightContainer WeightContainerType;
-
- template <class T>
- PUImpurityLoss(TLabelContainer const &labels,
- vigra::ProblemSpec<T> const &ext,
- AdditionalRFDataAbstract *data);
-
- void Reset();
-
- void UpdatePUCounts();
-
- template <class TDataIterator>
- double Increment(TDataIterator begin, TDataIterator end);
-
- template <class TDataIterator>
- double Decrement(TDataIterator begin, TDataIterator end);
-
- template <class TArray>
- double Init(TArray initCounts);
-
- vigra::ArrayVector<double> const& Response();
-
- void UsePointWeights(bool useWeights);
- bool IsUsingPointWeights();
-
- void SetPointWeights(TWeightContainer weight);
- WeightContainerType GetPointWeights();
-
- private:
- bool m_UsePointWeights;
- TWeightContainer m_PointWeights;
-
- //Variable of origin
- TLabelContainer const& m_Labels;
- vigra::ArrayVector<double> m_Counts;
- vigra::ArrayVector<double> m_PUCounts;
- vigra::ArrayVector<double> m_Kappa;
- vigra::ArrayVector<double> m_ClassWeights;
- double m_TotalCount;
- double m_PUTotalCount;
- int m_ClassCount;
- TLossFunction m_LossFunction;
- };
-
-}
-
-#include <../src/Splitter/mitkPUImpurityLoss.cpp>
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkPURFClassifier.h b/Modules/Classification/CLVigraRandomForest/include/mitkPURFClassifier.h
deleted file mode 100644
index d50c177489..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkPURFClassifier.h
+++ /dev/null
@@ -1,93 +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.
-
-============================================================================*/
-
-#ifndef mitkPURFClassifier_h
-#define mitkPURFClassifier_h
-
-#include <MitkCLVigraRandomForestExports.h>
-#include <mitkAbstractClassifier.h>
-
-//#include <vigra/multi_array.hxx>
-#include <vigra/random_forest.hxx>
-
-#include <mitkBaseData.h>
-
-namespace mitk
-{
- class MITKCLVIGRARANDOMFOREST_EXPORT PURFClassifier : public AbstractClassifier
- {
- public:
-
- mitkClassMacro(PURFClassifier, AbstractClassifier);
-
- itkFactorylessNewMacro(Self);
-
- itkCloneMacro(Self);
-
- PURFClassifier();
-
- ~PURFClassifier() override;
-
- void Train(const Eigen::MatrixXd &X, const Eigen::MatrixXi &Y) override;
-
- Eigen::MatrixXi Predict(const Eigen::MatrixXd &X) override;
- Eigen::MatrixXi PredictWeighted(const Eigen::MatrixXd &X);
-
-
- bool SupportsPointWiseWeight() override;
- bool SupportsPointWiseProbability() override;
- void ConvertParameter();
- vigra::ArrayVector<double> CalculateKappa(const Eigen::MatrixXd & X_in, const Eigen::MatrixXi &Y_in);
-
- void SetRandomForest(const vigra::RandomForest<int> & rf);
- const vigra::RandomForest<int> & GetRandomForest() const;
-
- void UsePointWiseWeight(bool) override;
- void SetMaximumTreeDepth(int);
- void SetMinimumSplitNodeSize(int);
- void SetPrecision(double);
- void SetSamplesPerTree(double);
- void UseSampleWithReplacement(bool);
- void SetTreeCount(int);
- void SetWeightLambda(double);
-
- void PrintParameter(std::ostream &str = std::cout);
-
- void SetClassProbabilities(Eigen::VectorXd probabilities);
- Eigen::VectorXd GetClassProbabilites();
-
- private:
- // *-------------------
- // * THREADING
- // *-------------------
-
-
- struct TrainingData;
- struct PredictionData;
- struct EigenToVigraTransform;
- struct Parameter;
-
- vigra::MultiArrayView<2, double> m_Probabilities;
- Eigen::MatrixXd m_TreeWeights;
- Eigen::VectorXd m_ClassProbabilities;
-
- Parameter * m_Parameter;
- vigra::RandomForest<int> m_RandomForest;
-
- static itk::ITK_THREAD_RETURN_TYPE TrainTreesCallback(void *);
- static itk::ITK_THREAD_RETURN_TYPE PredictCallback(void *);
- static itk::ITK_THREAD_RETURN_TYPE PredictWeightedCallback(void *);
- static void VigraPredictWeighted(PredictionData *data, vigra::MultiArrayView<2, double> & X, vigra::MultiArrayView<2, int> & Y, vigra::MultiArrayView<2, double> & P);
- };
-}
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkRandomForestIO.h b/Modules/Classification/CLVigraRandomForest/include/mitkRandomForestIO.h
deleted file mode 100644
index f93f7f3f2a..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkRandomForestIO.h
+++ /dev/null
@@ -1,62 +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.
-
-============================================================================*/
-
-#ifndef mitkRandomForestIO_h
-#define mitkRandomForestIO_h
-
-#include <mitkAbstractFileIO.h>
-#include "vigra/random_forest.hxx"
-
-namespace mitk
-{
-
-/**
- * Writes vigra based mitk::DecisionForest
- * @ingroup Process
- */
-class RandomForestFileIO : public mitk::AbstractFileIO
-{
-public:
-
- RandomForestFileIO();
- RandomForestFileIO(const mitk::RandomForestFileIO& other);
- ~RandomForestFileIO() override;
-
- using AbstractFileIO::Write;
- void Write() override;
-
- using AbstractFileIO::Read;
-
- ConfidenceLevel GetReaderConfidenceLevel() const override;
- ConfidenceLevel GetWriterConfidenceLevel() const override;
-
-
-protected:
- std::vector<itk::SmartPointer<BaseData>> DoRead() override;
-
-
- mutable vigra::RandomForest<int> m_rf;
-// DecisionForestFileIO(const DecisionForestFileIO& other);
-// virtual mitk::DecisionForestFileIO* Clone() const;
-
- private:
- AbstractFileIO* IOClone() const override;
-
-
-
-
-};
-
-
-} // end of namespace mitk
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkThresholdSplit.h b/Modules/Classification/CLVigraRandomForest/include/mitkThresholdSplit.h
deleted file mode 100644
index 3e6b5ed86d..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkThresholdSplit.h
+++ /dev/null
@@ -1,98 +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.
-
-============================================================================*/
-
-#ifndef mitkThresholdSplit_h
-#define mitkThresholdSplit_h
-
-#include <vigra/multi_array.hxx>
-#include <vigra/random_forest.hxx>
-#include <mitkAdditionalRFData.h>
-
-namespace mitk
-{
- template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag = vigra::ClassificationTag>
- class ThresholdSplit: public vigra::SplitBase<TTag>
- {
- public:
- ThresholdSplit();
-// ThresholdSplit(const ThresholdSplit & other);
-
- void SetFeatureCalculator(TFeatureCalculator processor);
- TFeatureCalculator GetFeatureCalculator() const;
-
- void SetCalculatingFeature(bool calculate);
- bool IsCalculatingFeature() const;
-
- void UsePointBasedWeights(bool weightsOn);
- bool IsUsingPointBasedWeights() const;
-
- void UseRandomSplit(bool split) {m_UseRandomSplit = split;}
- bool IsUsingRandomSplit() const { return m_UseRandomSplit; }
-
- void SetPrecision(double value);
- double GetPrecision() const;
-
- void SetMaximumTreeDepth(int value);
- int GetMaximumTreeDepth() const override;
-
- void SetAdditionalData(AdditionalRFDataAbstract* data);
- AdditionalRFDataAbstract* GetAdditionalData() const;
-
- void SetWeights(vigra::MultiArrayView<2, double> weights);
- vigra::MultiArrayView<2, double> GetWeights() const;
-
- // From vigra::ThresholdSplit
- double minGini() const;
- int bestSplitColumn() const;
- double bestSplitThreshold() const;
-
- template<class T>
- void set_external_parameters(vigra::ProblemSpec<T> const & in);
-
- template<class T, class C, class T2, class C2, class Region, class Random>
- int findBestSplit(vigra::MultiArrayView<2, T, C> features,
- vigra::MultiArrayView<2, T2, C2> labels,
- Region & region,
- vigra::ArrayVector<Region>& childRegions,
- Random & randint);
-
- double region_gini_;
-
- private:
-
- // From vigra::ThresholdSplit
- typedef vigra::SplitBase<TTag> SB;
-
- // splitter parameters (used by copy constructor)
- bool m_CalculatingFeature;
- bool m_UseWeights;
- bool m_UseRandomSplit;
- double m_Precision;
- int m_MaximumTreeDepth;
- TFeatureCalculator m_FeatureCalculator;
- vigra::MultiArrayView<2, double> m_Weights;
-
- // variabels to work with
- vigra::ArrayVector<vigra::Int32> splitColumns;
- TColumnDecisionFunctor bgfunc;
- vigra::ArrayVector<double> min_gini_;
- vigra::ArrayVector<std::ptrdiff_t> min_indices_;
- vigra::ArrayVector<double> min_thresholds_;
- int bestSplitIndex;
- AdditionalRFDataAbstract* m_AdditionalData;
-
- };
-}
-
-
-#include <../src/Splitter/mitkThresholdSplit.cpp>
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifier.h b/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifier.h
deleted file mode 100644
index 42a8fa001e..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifier.h
+++ /dev/null
@@ -1,92 +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.
-
-============================================================================*/
-
-#ifndef mitkVigraRandomForestClassifier_h
-#define mitkVigraRandomForestClassifier_h
-
-#include <MitkCLVigraRandomForestExports.h>
-#include <mitkAbstractClassifier.h>
-
-//#include <vigra/multi_array.hxx>
-#include <vigra/random_forest.hxx>
-
-#include <mitkBaseData.h>
-
-namespace mitk
-{
- class MITKCLVIGRARANDOMFOREST_EXPORT VigraRandomForestClassifier : public AbstractClassifier
- {
- public:
-
- mitkClassMacro(VigraRandomForestClassifier, AbstractClassifier);
-
- itkFactorylessNewMacro(Self);
-
- itkCloneMacro(Self);
-
- VigraRandomForestClassifier();
-
- ~VigraRandomForestClassifier() override;
-
- void Train(const Eigen::MatrixXd &X, const Eigen::MatrixXi &Y) override;
- void OnlineTrain(const Eigen::MatrixXd &X, const Eigen::MatrixXi &Y);
- Eigen::MatrixXi Predict(const Eigen::MatrixXd &X) override;
- Eigen::MatrixXi PredictWeighted(const Eigen::MatrixXd &X);
-
-
- bool SupportsPointWiseWeight() override;
- bool SupportsPointWiseProbability() override;
- void ConvertParameter();
-
- void SetRandomForest(const vigra::RandomForest<int> & rf);
- const vigra::RandomForest<int> & GetRandomForest() const;
-
- void UsePointWiseWeight(bool) override;
- void SetMaximumTreeDepth(int);
- void SetMinimumSplitNodeSize(int);
- void SetPrecision(double);
- void SetSamplesPerTree(double);
- void UseSampleWithReplacement(bool);
- void SetTreeCount(int);
- void SetWeightLambda(double);
-
- void SetTreeWeights(Eigen::MatrixXd weights);
- void SetTreeWeight(int treeId, double weight);
- Eigen::MatrixXd GetTreeWeights() const;
-
- void PrintParameter(std::ostream &str = std::cout);
-
- private:
- // *-------------------
- // * THREADING
- // *-------------------
-
-
- struct TrainingData;
- struct PredictionData;
- struct EigenToVigraTransform;
- struct Parameter;
-
- vigra::MultiArrayView<2, double> m_Probabilities;
- Eigen::MatrixXd m_TreeWeights;
-
- Parameter * m_Parameter;
- vigra::RandomForest<int> m_RandomForest;
-
- static itk::ITK_THREAD_RETURN_TYPE TrainTreesCallback(void *);
- static itk::ITK_THREAD_RETURN_TYPE PredictCallback(void *);
- static itk::ITK_THREAD_RETURN_TYPE PredictWeightedCallback(void *);
- static void VigraPredictWeighted(PredictionData *data, vigra::MultiArrayView<2, double> & X, vigra::MultiArrayView<2, int> & Y, vigra::MultiArrayView<2, double> & P);
- };
-}
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifierSerializer.h b/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifierSerializer.h
deleted file mode 100644
index 35c6a2773a..0000000000
--- a/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifierSerializer.h
+++ /dev/null
@@ -1,39 +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.
-
-============================================================================*/
-
-#ifndef mitkVigraRandomForestClassifierSerializer_h
-#define mitkVigraRandomForestClassifierSerializer_h
-
-#include <mitkBaseDataSerializer.h>
-#include <MitkCLVigraRandomForestExports.h>
-
-namespace mitk
-{
-
-class MITKCLVIGRARANDOMFOREST_EXPORT VigraRandomForestClassifierSerializer : public BaseDataSerializer
-{
-public:
- mitkClassMacro(VigraRandomForestClassifierSerializer, BaseDataSerializer);
- itkFactorylessNewMacro(Self);
- itkCloneMacro(Self);
-
- std::string Serialize() override;
-
-protected:
-
- VigraRandomForestClassifierSerializer();
- ~VigraRandomForestClassifierSerializer() override;
-};
-
-}
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/src/Algorithm/itkHessianMatrixEigenvalueImageFilter.cpp b/Modules/Classification/CLVigraRandomForest/src/Algorithm/itkHessianMatrixEigenvalueImageFilter.cpp
deleted file mode 100644
index d5aa41ace3..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Algorithm/itkHessianMatrixEigenvalueImageFilter.cpp
+++ /dev/null
@@ -1,157 +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.
-
-============================================================================*/
-
-#ifndef ITKHESSIANMATRIXEIGENVALUEIMAGEFILTER_CPP
-#define ITKHESSIANMATRIXEIGENVALUEIMAGEFILTER_CPP
-
-#include <itkHessianMatrixEigenvalueImageFilter.h>
-#include <itkImageRegionIterator.h>
-#include <vigra/tensorutilities.hxx>
-#include <vigra/convolution.hxx>
-#include <mitkCLUtil.h>
-
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-void itk::HessianMatrixEigenvalueImageFilter<TInputImageType,TOutputImageType, TMaskImageType>::GenerateOutputInformation()
-{
- Superclass::GenerateOutputInformation();
- this->GetOutput(0)->SetDirection(this->GetInput()->GetDirection());
- this->GetOutput(0)->SetSpacing(this->GetInput()->GetSpacing());
- this->GetOutput(0)->SetRegions(this->GetInput()->GetLargestPossibleRegion());
- this->GetOutput(0)->Allocate();
-
- this->GetOutput(1)->SetDirection(this->GetInput()->GetDirection());
- this->GetOutput(1)->SetSpacing(this->GetInput()->GetSpacing());
- this->GetOutput(1)->SetRegions(this->GetInput()->GetLargestPossibleRegion());
- this->GetOutput(1)->Allocate();
-
- this->GetOutput(2)->SetDirection(this->GetInput()->GetDirection());
- this->GetOutput(2)->SetSpacing(this->GetInput()->GetSpacing());
- this->GetOutput(2)->SetRegions(this->GetInput()->GetLargestPossibleRegion());
- this->GetOutput(2)->Allocate();
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-void itk::HessianMatrixEigenvalueImageFilter<TInputImageType,TOutputImageType,TMaskImageType>::GenerateData()
-{
-
- typedef typename TInputImageType::PixelType InputPixelType;
-
- typename TInputImageType::RegionType region = this->GetInput()->GetLargestPossibleRegion();
- unsigned int xdim = region.GetSize(0);
- unsigned int ydim = region.GetSize(1);
- unsigned int zdim = region.GetSize(2);
-
- typename TInputImageType::Pointer maske_input = TInputImageType::New();
- maske_input->SetDirection(this->GetInput()->GetDirection());
- maske_input->SetSpacing(this->GetInput()->GetSpacing());
- maske_input->SetRegions(this->GetInput()->GetLargestPossibleRegion());
- maske_input->Allocate();
-
- itk::ImageRegionConstIterator<TInputImageType> iit(this->GetInput(), this->GetInput()->GetLargestPossibleRegion());
- itk::ImageRegionIterator<TInputImageType> miit(maske_input, maske_input->GetLargestPossibleRegion());
- itk::ImageRegionConstIterator<TMaskImageType> mit(m_ImageMask, m_ImageMask->GetLargestPossibleRegion());
-
- while(!miit.IsAtEnd())
- {
- if(mit.Value()!=0)
- miit.Set(iit.Value());
- else
- miit.Set(0);
-
- ++miit;
- ++mit;
- ++iit;
- }
-
-
- vigra::Shape3 shape(xdim,ydim,zdim);
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > input_image_view(
- shape ,
- maske_input->GetBufferPointer());
-
-
- vigra::MultiArray<3, vigra::TinyVector<InputPixelType, 3> > hessian_image(shape);
- vigra::MultiArray<3, vigra::TinyVector<InputPixelType, 3> > eigenvalues_image(shape);
-
- for(unsigned int i = 0 ; i < zdim; ++i )
- {
- vigra::Shape2 slice_shape(xdim,ydim);
- vigra::MultiArrayView<2, InputPixelType, vigra::StridedArrayTag > image_slice(
- slice_shape,
- input_image_view.data()+ (i*xdim*ydim));
-
- vigra::MultiArrayView<2, vigra::TinyVector<InputPixelType, 3> > hessian_slice(
- slice_shape,
- hessian_image.data() + (i*xdim*ydim));
-
- // vigra::hessianMatrixOfGaussian(input_image_slice_view, hessian_image_slice_view, sigma);
-
- // vigra::hessianMatrixOfGaussian(image_slice,hessian_slice,sigma);
- vigra::hessianMatrixOfGaussian(image_slice,
- hessian_slice.bindElementChannel(0),
- hessian_slice.bindElementChannel(1),
- hessian_slice.bindElementChannel(2),
- m_Sigma);
-
- vigra::MultiArrayView<2, vigra::TinyVector<InputPixelType, 3> > eigenvalues_image_slice_view(
- slice_shape,
- eigenvalues_image.data() + (i*xdim*ydim));
-
- vigra::tensorEigenRepresentation(hessian_slice, eigenvalues_image_slice_view);
- }
-
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > ev1_image = eigenvalues_image.bindElementChannel(0);
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > ev2_image = eigenvalues_image.bindElementChannel(1);
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > ev3_image = eigenvalues_image.bindElementChannel(2);
-
-
- for(unsigned int x = 0 ; x < xdim; ++x)
- for(unsigned int y = 0 ; y < ydim; ++y)
- for(unsigned int z = 0 ; z < zdim; ++z)
- {
- itk::Index<3> indx = {{x,y,z}};
- this->GetOutput(0)->operator [](indx) = ev1_image(x,y,z);
- this->GetOutput(1)->operator [](indx) = ev2_image(x,y,z);
- this->GetOutput(2)->operator [](indx) = ev3_image(x,y,z);
- }
-
-
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-void itk::HessianMatrixEigenvalueImageFilter<TInputImageType,TOutputImageType,TMaskImageType>::SetImageMask(TMaskImageType * maskimage)
-{
- this->m_ImageMask = maskimage;
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-itk::HessianMatrixEigenvalueImageFilter<TInputImageType,TOutputImageType,TMaskImageType>::HessianMatrixEigenvalueImageFilter()
-{
- this->SetNumberOfIndexedOutputs(3);
- this->SetNumberOfIndexedInputs(1);
-
- this->SetNthOutput( 0, this->MakeOutput(0) );
- this->SetNthOutput( 1, this->MakeOutput(1) );
- this->SetNthOutput( 2, this->MakeOutput(2) );
-
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-itk::HessianMatrixEigenvalueImageFilter<TInputImageType,TOutputImageType,TMaskImageType>::~HessianMatrixEigenvalueImageFilter()
-{
-
-}
-
-
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/src/Algorithm/itkStructureTensorEigenvalueImageFilter.cpp b/Modules/Classification/CLVigraRandomForest/src/Algorithm/itkStructureTensorEigenvalueImageFilter.cpp
deleted file mode 100644
index f9fed96cba..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Algorithm/itkStructureTensorEigenvalueImageFilter.cpp
+++ /dev/null
@@ -1,128 +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.
-
-============================================================================*/
-
-#ifndef ITKSTRUCTURETENSOREIGENVALUEIMAGEFILTER_CPP
-#define ITKSTRUCTURETENSOREIGENVALUEIMAGEFILTER_CPP
-
-#include <itkStructureTensorEigenvalueImageFilter.h>
-#include <itkImageRegionIterator.h>
-#include <vigra/tensorutilities.hxx>
-#include <vigra/convolution.hxx>
-
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-void itk::StructureTensorEigenvalueImageFilter<TInputImageType,TOutputImageType, TMaskImageType>::GenerateOutputInformation()
-{
- Superclass::GenerateOutputInformation();
- this->GetOutput(0)->SetDirection(this->GetInput()->GetDirection());
- this->GetOutput(0)->SetSpacing(this->GetInput()->GetSpacing());
- this->GetOutput(0)->SetRegions(this->GetInput()->GetLargestPossibleRegion());
- this->GetOutput(0)->Allocate();
-
- this->GetOutput(1)->SetDirection(this->GetInput()->GetDirection());
- this->GetOutput(1)->SetSpacing(this->GetInput()->GetSpacing());
- this->GetOutput(1)->SetRegions(this->GetInput()->GetLargestPossibleRegion());
- this->GetOutput(1)->Allocate();
-
- this->GetOutput(2)->SetDirection(this->GetInput()->GetDirection());
- this->GetOutput(2)->SetSpacing(this->GetInput()->GetSpacing());
- this->GetOutput(2)->SetRegions(this->GetInput()->GetLargestPossibleRegion());
- this->GetOutput(2)->Allocate();
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-void itk::StructureTensorEigenvalueImageFilter<TInputImageType,TOutputImageType, TMaskImageType>::GenerateData()
-{
-
-
-
- typedef typename TInputImageType::PixelType InputPixelType;
-
- typename TInputImageType::RegionType region = this->GetInput()->GetLargestPossibleRegion();
- unsigned int xdim = region.GetSize(0);
- unsigned int ydim = region.GetSize(1);
- unsigned int zdim = region.GetSize(2);
-
-
-
- vigra::Shape3 shape(xdim,ydim,zdim);
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > input_image_view(
- shape ,
- this->GetInput()->GetBufferPointer());
-
- vigra::MultiArray<3, vigra::TinyVector<InputPixelType, 3> > structuretensor_image(shape);
- vigra::MultiArray<3, vigra::TinyVector<InputPixelType, 3> > eigenvalues_image(shape);
-
-
- for(unsigned int i = 0 ; i < zdim; ++i )
- {
- vigra::Shape2 slice_shape(xdim,ydim);
- vigra::MultiArrayView<2, InputPixelType, vigra::StridedArrayTag > input_image_slice_view(
- slice_shape,
- input_image_view.data()+ (i*xdim*ydim));
-
- vigra::MultiArrayView<2, vigra::TinyVector<InputPixelType, 3> > structuretensor_image_slice_view(
- slice_shape,
- structuretensor_image.data() + (i*xdim*ydim));
-
- vigra::structureTensor(input_image_slice_view, structuretensor_image_slice_view, m_InnerScale, m_OuterScale);
-
- vigra::MultiArrayView<2, vigra::TinyVector<InputPixelType, 3> > eigenvalues_image_slice_view(
- slice_shape,
- eigenvalues_image.data() + (i*xdim*ydim));
- vigra::tensorEigenRepresentation(structuretensor_image_slice_view, eigenvalues_image_slice_view);
- }
-
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > ev1_image = eigenvalues_image.bindElementChannel(0);
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > ev2_image = eigenvalues_image.bindElementChannel(1);
- vigra::MultiArrayView<3, InputPixelType, vigra::StridedArrayTag > ev3_image = eigenvalues_image.bindElementChannel(2);
-
- for(unsigned int x = 0 ; x < xdim; ++x)
- for(unsigned int y = 0 ; y < ydim; ++y)
- for(unsigned int z = 0 ; z < zdim; ++z)
- {
- itk::Index<3> indx = {{x,y,z}};
- this->GetOutput(0)->operator [](indx) = ev1_image(x,y,z);
- this->GetOutput(1)->operator [](indx) = ev2_image(x,y,z);
- this->GetOutput(2)->operator [](indx) = ev3_image(x,y,z);
- }
-
-
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-void itk::StructureTensorEigenvalueImageFilter<TInputImageType,TOutputImageType, TMaskImageType>::SetImageMask(TMaskImageType *maskimage)
-{
- this->m_ImageMask = maskimage;
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-itk::StructureTensorEigenvalueImageFilter<TInputImageType,TOutputImageType,TMaskImageType>::StructureTensorEigenvalueImageFilter()
-{
- this->SetNumberOfIndexedOutputs(3);
- this->SetNumberOfIndexedInputs(1);
-
- this->SetNthOutput( 0, this->MakeOutput(0) );
- this->SetNthOutput( 1, this->MakeOutput(1) );
- this->SetNthOutput( 2, this->MakeOutput(2) );
-
-}
-
-template< class TInputImageType, class TOutputImageType, class TMaskImageType>
-itk::StructureTensorEigenvalueImageFilter<TInputImageType,TOutputImageType,TMaskImageType>::~StructureTensorEigenvalueImageFilter()
-{
-
-}
-
-
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/src/Classifier/mitkPURFClassifier.cpp b/Modules/Classification/CLVigraRandomForest/src/Classifier/mitkPURFClassifier.cpp
deleted file mode 100644
index 05f8414cc7..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Classifier/mitkPURFClassifier.cpp
+++ /dev/null
@@ -1,474 +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.
-
-============================================================================*/
-
-// MITK includes
-#include <mitkPURFClassifier.h>
-#include <mitkThresholdSplit.h>
-#include <mitkPUImpurityLoss.h>
-#include <mitkImpurityLoss.h>
-#include <mitkLinearSplitting.h>
-#include <mitkProperties.h>
-
-// Vigra includes
-#include <vigra/random_forest.hxx>
-#include <vigra/random_forest/rf_split.hxx>
-
-// ITK include
-#include <itkMultiThreaderBase.h>
-#include <itkCommand.h>
-
-#include <mutex>
-
-typedef mitk::ThresholdSplit<mitk::LinearSplitting< mitk::PUImpurityLoss<> >,int,vigra::ClassificationTag> DefaultPUSplitType;
-
-struct mitk::PURFClassifier::Parameter
-{
- vigra::RF_OptionTag Stratification;
- bool SampleWithReplacement;
- bool UseRandomSplit;
- bool UsePointBasedWeights;
- int TreeCount;
- int MinimumSplitNodeSize;
- int TreeDepth;
- double Precision;
- double WeightLambda;
- double SamplesPerTree;
-};
-
-struct mitk::PURFClassifier::TrainingData
-{
- TrainingData(unsigned int numberOfTrees,
- const vigra::RandomForest<int> & refRF,
- const DefaultPUSplitType & refSplitter,
- const vigra::MultiArrayView<2, double> refFeature,
- const vigra::MultiArrayView<2, int> refLabel,
- const Parameter parameter)
- : m_ClassCount(0),
- m_NumberOfTrees(numberOfTrees),
- m_RandomForest(refRF),
- m_Splitter(refSplitter),
- m_Feature(refFeature),
- m_Label(refLabel),
- m_Parameter(parameter)
- {
- }
- vigra::ArrayVector<vigra::RandomForest<int>::DecisionTree_t> trees_;
-
- int m_ClassCount;
- unsigned int m_NumberOfTrees;
- const vigra::RandomForest<int> & m_RandomForest;
- const DefaultPUSplitType & m_Splitter;
- const vigra::MultiArrayView<2, double> m_Feature;
- const vigra::MultiArrayView<2, int> m_Label;
- std::mutex m_mutex;
- Parameter m_Parameter;
-};
-
-struct mitk::PURFClassifier::PredictionData
-{
- PredictionData(const vigra::RandomForest<int> & refRF,
- const vigra::MultiArrayView<2, double> refFeature,
- vigra::MultiArrayView<2, int> refLabel,
- vigra::MultiArrayView<2, double> refProb,
- vigra::MultiArrayView<2, double> refTreeWeights)
- : m_RandomForest(refRF),
- m_Feature(refFeature),
- m_Label(refLabel),
- m_Probabilities(refProb),
- m_TreeWeights(refTreeWeights)
- {
- }
- const vigra::RandomForest<int> & m_RandomForest;
- const vigra::MultiArrayView<2, double> m_Feature;
- vigra::MultiArrayView<2, int> m_Label;
- vigra::MultiArrayView<2, double> m_Probabilities;
- vigra::MultiArrayView<2, double> m_TreeWeights;
-};
-
-mitk::PURFClassifier::PURFClassifier()
- :m_Parameter(nullptr)
-{
- itk::SimpleMemberCommand<mitk::PURFClassifier>::Pointer command = itk::SimpleMemberCommand<mitk::PURFClassifier>::New();
- command->SetCallbackFunction(this, &mitk::PURFClassifier::ConvertParameter);
- this->GetPropertyList()->AddObserver( itk::ModifiedEvent(), command );
-}
-
-mitk::PURFClassifier::~PURFClassifier()
-{
-}
-
-void mitk::PURFClassifier::SetClassProbabilities(Eigen::VectorXd probabilities)
-{
- m_ClassProbabilities = probabilities;
-}
-
-Eigen::VectorXd mitk::PURFClassifier::GetClassProbabilites()
-{
- return m_ClassProbabilities;
-}
-
-bool mitk::PURFClassifier::SupportsPointWiseWeight()
-{
- return true;
-}
-
-bool mitk::PURFClassifier::SupportsPointWiseProbability()
-{
- return true;
-}
-
-
-vigra::ArrayVector<double> mitk::PURFClassifier::CalculateKappa(const Eigen::MatrixXd & /* X_in */, const Eigen::MatrixXi & Y_in)
-{
- int maximumValue = Y_in.maxCoeff();
- vigra::ArrayVector<double> kappa(maximumValue + 1);
- vigra::ArrayVector<double> counts(maximumValue + 1);
- for (int i = 0; i < Y_in.rows(); ++i)
- {
- counts[Y_in(i, 0)] += 1;
- }
- for (int i = 0; i < maximumValue+1; ++i)
- {
- if (counts[i] > 0)
- {
- kappa[i] = counts[0] * m_ClassProbabilities[i] / counts[i] + 1;
- }
- else
- {
- kappa[i] = 1;
- }
- }
- return kappa;
-}
-
-
-void mitk::PURFClassifier::Train(const Eigen::MatrixXd & X_in, const Eigen::MatrixXi &Y_in)
-{
- this->ConvertParameter();
-
- PURFData* purfData = new PURFData;
- purfData->m_Kappa = this->CalculateKappa(X_in, Y_in);
-
- DefaultPUSplitType splitter;
- splitter.UsePointBasedWeights(m_Parameter->UsePointBasedWeights);
- splitter.UseRandomSplit(m_Parameter->UseRandomSplit);
- splitter.SetPrecision(m_Parameter->Precision);
- splitter.SetMaximumTreeDepth(m_Parameter->TreeDepth);
- splitter.SetAdditionalData(purfData);
-
- // Weights handled as member variable
- if (m_Parameter->UsePointBasedWeights)
- {
- // Set influence of the weight (0 no influenc to 1 max influence)
- this->m_PointWiseWeight.unaryExpr([this](double t){ return std::pow(t, this->m_Parameter->WeightLambda) ;});
-
- vigra::MultiArrayView<2, double> W(vigra::Shape2(this->m_PointWiseWeight.rows(),this->m_PointWiseWeight.cols()),this->m_PointWiseWeight.data());
- splitter.SetWeights(W);
- }
-
- vigra::MultiArrayView<2, double> X(vigra::Shape2(X_in.rows(),X_in.cols()),X_in.data());
- vigra::MultiArrayView<2, int> Y(vigra::Shape2(Y_in.rows(),Y_in.cols()),Y_in.data());
-
- m_RandomForest.set_options().tree_count(1); // Number of trees that are calculated;
-
- m_RandomForest.set_options().use_stratification(m_Parameter->Stratification);
- m_RandomForest.set_options().sample_with_replacement(m_Parameter->SampleWithReplacement);
- m_RandomForest.set_options().samples_per_tree(m_Parameter->SamplesPerTree);
- m_RandomForest.set_options().min_split_node_size(m_Parameter->MinimumSplitNodeSize);
-
- m_RandomForest.learn(X, Y,vigra::rf::visitors::VisitorBase(),splitter);
-
- std::unique_ptr<TrainingData> data(new TrainingData(m_Parameter->TreeCount,m_RandomForest,splitter,X,Y, *m_Parameter));
-
- auto threader = itk::MultiThreaderBase::New();
- threader->SetSingleMethod(this->TrainTreesCallback,data.get());
- threader->SingleMethodExecute();
-
- // set result trees
- m_RandomForest.set_options().tree_count(m_Parameter->TreeCount);
- m_RandomForest.ext_param_.class_count_ = data->m_ClassCount;
- m_RandomForest.trees_ = data->trees_;
-
- // Set Tree Weights to default
- m_TreeWeights = Eigen::MatrixXd(m_Parameter->TreeCount,1);
- m_TreeWeights.fill(1.0);
- delete purfData;
-}
-
-Eigen::MatrixXi mitk::PURFClassifier::Predict(const Eigen::MatrixXd &X_in)
-{
- // Initialize output Eigen matrices
- m_OutProbability = Eigen::MatrixXd(X_in.rows(),m_RandomForest.class_count());
- m_OutProbability.fill(0);
- m_OutLabel = Eigen::MatrixXi(X_in.rows(),1);
- m_OutLabel.fill(0);
-
- // If no weights provided
- if(m_TreeWeights.rows() != m_RandomForest.tree_count())
- {
- m_TreeWeights = Eigen::MatrixXd(m_RandomForest.tree_count(),1);
- m_TreeWeights.fill(1);
- }
-
- vigra::MultiArrayView<2, double> P(vigra::Shape2(m_OutProbability.rows(),m_OutProbability.cols()),m_OutProbability.data());
- vigra::MultiArrayView<2, int> Y(vigra::Shape2(m_OutLabel.rows(),m_OutLabel.cols()),m_OutLabel.data());
- vigra::MultiArrayView<2, double> X(vigra::Shape2(X_in.rows(),X_in.cols()),X_in.data());
- vigra::MultiArrayView<2, double> TW(vigra::Shape2(m_RandomForest.tree_count(),1),m_TreeWeights.data());
-
- std::unique_ptr<PredictionData> data;
- data.reset(new PredictionData(m_RandomForest, X, Y, P, TW));
-
- auto threader = itk::MultiThreaderBase::New();
- threader->SetSingleMethod(this->PredictCallback, data.get());
- threader->SingleMethodExecute();
-
- m_Probabilities = data->m_Probabilities;
- return m_OutLabel;
-}
-
-itk::ITK_THREAD_RETURN_TYPE mitk::PURFClassifier::TrainTreesCallback(void * arg)
-{
- // Get the ThreadInfoStruct
- typedef itk::MultiThreaderBase::WorkUnitInfo ThreadInfoType;
- ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( arg );
-
- TrainingData * data = (TrainingData *)(infoStruct->UserData);
- unsigned int numberOfTreesToCalculate = 0;
-
- // define the number of tress the forest have to calculate
- numberOfTreesToCalculate = data->m_NumberOfTrees / infoStruct->NumberOfWorkUnits;
-
- // the 0th thread takes the residuals
- if(infoStruct->WorkUnitID == 0) numberOfTreesToCalculate += data->m_NumberOfTrees % infoStruct->NumberOfWorkUnits;
-
- if(numberOfTreesToCalculate != 0){
- // Copy the Treestructure defined in userData
- vigra::RandomForest<int> rf = data->m_RandomForest;
-
- // Initialize a splitter for the leraning process
- DefaultPUSplitType splitter;
- splitter.UsePointBasedWeights(data->m_Splitter.IsUsingPointBasedWeights());
- splitter.UseRandomSplit(data->m_Splitter.IsUsingRandomSplit());
- splitter.SetPrecision(data->m_Splitter.GetPrecision());
- splitter.SetMaximumTreeDepth(data->m_Splitter.GetMaximumTreeDepth());
- splitter.SetWeights(data->m_Splitter.GetWeights());
- splitter.SetAdditionalData(data->m_Splitter.GetAdditionalData());
-
- rf.trees_.clear();
- rf.set_options().tree_count(numberOfTreesToCalculate);
- rf.set_options().use_stratification(data->m_Parameter.Stratification);
- rf.set_options().sample_with_replacement(data->m_Parameter.SampleWithReplacement);
- rf.set_options().samples_per_tree(data->m_Parameter.SamplesPerTree);
- rf.set_options().min_split_node_size(data->m_Parameter.MinimumSplitNodeSize);
- rf.learn(data->m_Feature, data->m_Label,vigra::rf::visitors::VisitorBase(),splitter);
-
- data->m_mutex.lock();
-
- for(const auto & tree : rf.trees_)
- data->trees_.push_back(tree);
-
- data->m_ClassCount = rf.class_count();
- data->m_mutex.unlock();
- }
-
- return ITK_THREAD_RETURN_DEFAULT_VALUE;
-
-}
-
-itk::ITK_THREAD_RETURN_TYPE mitk::PURFClassifier::PredictCallback(void * arg)
-{
- // Get the ThreadInfoStruct
- typedef itk::MultiThreaderBase::WorkUnitInfo ThreadInfoType;
- ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( arg );
- // assigne the thread id
- const unsigned int threadId = infoStruct->WorkUnitID;
-
- // Get the user defined parameters containing all
- // neccesary informations
- PredictionData * data = (PredictionData *)(infoStruct->UserData);
- unsigned int numberOfRowsToCalculate = 0;
-
- // Get number of rows to calculate
- numberOfRowsToCalculate = data->m_Feature.shape()[0] / infoStruct->NumberOfWorkUnits;
-
- unsigned int start_index = numberOfRowsToCalculate * threadId;
- unsigned int end_index = numberOfRowsToCalculate * (threadId+1);
-
- // the last thread takes the residuals
- if(threadId == infoStruct->NumberOfWorkUnits-1) {
- end_index += data->m_Feature.shape()[0] % infoStruct->NumberOfWorkUnits;
- }
-
- vigra::MultiArrayView<2, double> split_features;
- vigra::MultiArrayView<2, int> split_labels;
- vigra::MultiArrayView<2, double> split_probability;
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index,data->m_Feature.shape(1));
- split_features = data->m_Feature.subarray(lowerBound,upperBound);
- }
-
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index, data->m_Label.shape(1));
- split_labels = data->m_Label.subarray(lowerBound,upperBound);
- }
-
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index,data->m_Probabilities.shape(1));
- split_probability = data->m_Probabilities.subarray(lowerBound,upperBound);
- }
-
- data->m_RandomForest.predictLabels(split_features,split_labels);
- data->m_RandomForest.predictProbabilities(split_features, split_probability);
-
-
- return ITK_THREAD_RETURN_DEFAULT_VALUE;
-
-}
-
-void mitk::PURFClassifier::ConvertParameter()
-{
- if(this->m_Parameter == nullptr)
- this->m_Parameter = new Parameter();
- // Get the proerty // Some defaults
-
- MITK_INFO("PURFClassifier") << "Convert Parameter";
- if(!this->GetPropertyList()->Get("usepointbasedweight",this->m_Parameter->UsePointBasedWeights)) this->m_Parameter->UsePointBasedWeights = false;
- if(!this->GetPropertyList()->Get("userandomsplit",this->m_Parameter->UseRandomSplit)) this->m_Parameter->UseRandomSplit = false;
- if(!this->GetPropertyList()->Get("treedepth",this->m_Parameter->TreeDepth)) this->m_Parameter->TreeDepth = 20;
- if(!this->GetPropertyList()->Get("treecount",this->m_Parameter->TreeCount)) this->m_Parameter->TreeCount = 100;
- if(!this->GetPropertyList()->Get("minimalsplitnodesize",this->m_Parameter->MinimumSplitNodeSize)) this->m_Parameter->MinimumSplitNodeSize = 5;
- if(!this->GetPropertyList()->Get("precision",this->m_Parameter->Precision)) this->m_Parameter->Precision = mitk::eps;
- if(!this->GetPropertyList()->Get("samplespertree",this->m_Parameter->SamplesPerTree)) this->m_Parameter->SamplesPerTree = 0.6;
- if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->SampleWithReplacement)) this->m_Parameter->SampleWithReplacement = true;
- if(!this->GetPropertyList()->Get("lambda",this->m_Parameter->WeightLambda)) this->m_Parameter->WeightLambda = 1.0; // Not used yet
- // if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->Stratification))
- this->m_Parameter->Stratification = vigra::RF_NONE; // no Property given
-}
-
-void mitk::PURFClassifier::PrintParameter(std::ostream & str)
-{
- if(this->m_Parameter == nullptr)
- {
- MITK_WARN("PURFClassifier") << "Parameters are not initialized. Please call ConvertParameter() first!";
- return;
- }
-
- this->ConvertParameter();
-
- // Get the proerty // Some defaults
- if(!this->GetPropertyList()->Get("usepointbasedweight",this->m_Parameter->UsePointBasedWeights))
- str << "usepointbasedweight\tNOT SET (default " << this->m_Parameter->UsePointBasedWeights << ")" << "\n";
- else
- str << "usepointbasedweight\t" << this->m_Parameter->UsePointBasedWeights << "\n";
-
- if(!this->GetPropertyList()->Get("userandomsplit",this->m_Parameter->UseRandomSplit))
- str << "userandomsplit\tNOT SET (default " << this->m_Parameter->UseRandomSplit << ")" << "\n";
- else
- str << "userandomsplit\t" << this->m_Parameter->UseRandomSplit << "\n";
-
- if(!this->GetPropertyList()->Get("treedepth",this->m_Parameter->TreeDepth))
- str << "treedepth\t\tNOT SET (default " << this->m_Parameter->TreeDepth << ")" << "\n";
- else
- str << "treedepth\t\t" << this->m_Parameter->TreeDepth << "\n";
-
- if(!this->GetPropertyList()->Get("minimalsplitnodesize",this->m_Parameter->MinimumSplitNodeSize))
- str << "minimalsplitnodesize\tNOT SET (default " << this->m_Parameter->MinimumSplitNodeSize << ")" << "\n";
- else
- str << "minimalsplitnodesize\t" << this->m_Parameter->MinimumSplitNodeSize << "\n";
-
- if(!this->GetPropertyList()->Get("precision",this->m_Parameter->Precision))
- str << "precision\t\tNOT SET (default " << this->m_Parameter->Precision << ")" << "\n";
- else
- str << "precision\t\t" << this->m_Parameter->Precision << "\n";
-
- if(!this->GetPropertyList()->Get("samplespertree",this->m_Parameter->SamplesPerTree))
- str << "samplespertree\tNOT SET (default " << this->m_Parameter->SamplesPerTree << ")" << "\n";
- else
- str << "samplespertree\t" << this->m_Parameter->SamplesPerTree << "\n";
-
- if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->SampleWithReplacement))
- str << "samplewithreplacement\tNOT SET (default " << this->m_Parameter->SampleWithReplacement << ")" << "\n";
- else
- str << "samplewithreplacement\t" << this->m_Parameter->SampleWithReplacement << "\n";
-
- if(!this->GetPropertyList()->Get("treecount",this->m_Parameter->TreeCount))
- str << "treecount\t\tNOT SET (default " << this->m_Parameter->TreeCount << ")" << "\n";
- else
- str << "treecount\t\t" << this->m_Parameter->TreeCount << "\n";
-
- if(!this->GetPropertyList()->Get("lambda",this->m_Parameter->WeightLambda))
- str << "lambda\t\tNOT SET (default " << this->m_Parameter->WeightLambda << ")" << "\n";
- else
- str << "lambda\t\t" << this->m_Parameter->WeightLambda << "\n";
-
- // if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->Stratification))
- // this->m_Parameter->Stratification = vigra:RF_NONE; // no Property given
-}
-
-void mitk::PURFClassifier::UsePointWiseWeight(bool val)
-{
- mitk::AbstractClassifier::UsePointWiseWeight(val);
- this->GetPropertyList()->SetBoolProperty("usepointbasedweight",val);
-}
-
-void mitk::PURFClassifier::SetMaximumTreeDepth(int val)
-{
- this->GetPropertyList()->SetIntProperty("treedepth",val);
-}
-
-void mitk::PURFClassifier::SetMinimumSplitNodeSize(int val)
-{
- this->GetPropertyList()->SetIntProperty("minimalsplitnodesize",val);
-}
-
-void mitk::PURFClassifier::SetPrecision(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("precision",val);
-}
-
-void mitk::PURFClassifier::SetSamplesPerTree(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("samplespertree",val);
-}
-
-void mitk::PURFClassifier::UseSampleWithReplacement(bool val)
-{
- this->GetPropertyList()->SetBoolProperty("samplewithreplacement",val);
-}
-
-void mitk::PURFClassifier::SetTreeCount(int val)
-{
- this->GetPropertyList()->SetIntProperty("treecount",val);
-}
-
-void mitk::PURFClassifier::SetWeightLambda(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("lambda",val);
-}
-
-void mitk::PURFClassifier::SetRandomForest(const vigra::RandomForest<int> & rf)
-{
- this->SetMaximumTreeDepth(rf.ext_param().max_tree_depth);
- this->SetMinimumSplitNodeSize(rf.options().min_split_node_size_);
- this->SetTreeCount(rf.options().tree_count_);
- this->SetSamplesPerTree(rf.options().training_set_proportion_);
- this->UseSampleWithReplacement(rf.options().sample_with_replacement_);
- this->m_RandomForest = rf;
-}
-
-const vigra::RandomForest<int> & mitk::PURFClassifier::GetRandomForest() const
-{
- return this->m_RandomForest;
-}
diff --git a/Modules/Classification/CLVigraRandomForest/src/Classifier/mitkVigraRandomForestClassifier.cpp b/Modules/Classification/CLVigraRandomForest/src/Classifier/mitkVigraRandomForestClassifier.cpp
deleted file mode 100644
index 840d58d270..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Classifier/mitkVigraRandomForestClassifier.cpp
+++ /dev/null
@@ -1,589 +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.
-
-============================================================================*/
-
-// MITK includes
-#include <mitkVigraRandomForestClassifier.h>
-#include <mitkThresholdSplit.h>
-#include <mitkImpurityLoss.h>
-#include <mitkLinearSplitting.h>
-#include <mitkProperties.h>
-
-// Vigra includes
-#include <vigra/random_forest.hxx>
-#include <vigra/random_forest/rf_split.hxx>
-
-// ITK include
-#include <itkMultiThreaderBase.h>
-#include <itkCommand.h>
-
-#include <mutex>
-
-typedef mitk::ThresholdSplit<mitk::LinearSplitting< mitk::ImpurityLoss<> >,int,vigra::ClassificationTag> DefaultSplitType;
-
-struct mitk::VigraRandomForestClassifier::Parameter
-{
- vigra::RF_OptionTag Stratification;
- bool SampleWithReplacement;
- bool UseRandomSplit;
- bool UsePointBasedWeights;
- int TreeCount;
- int MinimumSplitNodeSize;
- int TreeDepth;
- double Precision;
- double WeightLambda;
- double SamplesPerTree;
-};
-
-struct mitk::VigraRandomForestClassifier::TrainingData
-{
- TrainingData(unsigned int numberOfTrees,
- const vigra::RandomForest<int> & refRF,
- const DefaultSplitType & refSplitter,
- const vigra::MultiArrayView<2, double> refFeature,
- const vigra::MultiArrayView<2, int> refLabel,
- const Parameter parameter)
- : m_ClassCount(0),
- m_NumberOfTrees(numberOfTrees),
- m_RandomForest(refRF),
- m_Splitter(refSplitter),
- m_Feature(refFeature),
- m_Label(refLabel),
- m_Parameter(parameter)
- {
- }
- vigra::ArrayVector<vigra::RandomForest<int>::DecisionTree_t> trees_;
-
- int m_ClassCount;
- unsigned int m_NumberOfTrees;
- const vigra::RandomForest<int> & m_RandomForest;
- const DefaultSplitType & m_Splitter;
- const vigra::MultiArrayView<2, double> m_Feature;
- const vigra::MultiArrayView<2, int> m_Label;
- std::mutex m_mutex;
- Parameter m_Parameter;
-};
-
-struct mitk::VigraRandomForestClassifier::PredictionData
-{
- PredictionData(const vigra::RandomForest<int> & refRF,
- const vigra::MultiArrayView<2, double> refFeature,
- vigra::MultiArrayView<2, int> refLabel,
- vigra::MultiArrayView<2, double> refProb,
- vigra::MultiArrayView<2, double> refTreeWeights)
- : m_RandomForest(refRF),
- m_Feature(refFeature),
- m_Label(refLabel),
- m_Probabilities(refProb),
- m_TreeWeights(refTreeWeights)
- {
- }
- const vigra::RandomForest<int> & m_RandomForest;
- const vigra::MultiArrayView<2, double> m_Feature;
- vigra::MultiArrayView<2, int> m_Label;
- vigra::MultiArrayView<2, double> m_Probabilities;
- vigra::MultiArrayView<2, double> m_TreeWeights;
-};
-
-mitk::VigraRandomForestClassifier::VigraRandomForestClassifier()
- :m_Parameter(nullptr)
-{
- itk::SimpleMemberCommand<mitk::VigraRandomForestClassifier>::Pointer command = itk::SimpleMemberCommand<mitk::VigraRandomForestClassifier>::New();
- command->SetCallbackFunction(this, &mitk::VigraRandomForestClassifier::ConvertParameter);
- this->GetPropertyList()->AddObserver( itk::ModifiedEvent(), command );
-}
-
-mitk::VigraRandomForestClassifier::~VigraRandomForestClassifier()
-{
-}
-
-bool mitk::VigraRandomForestClassifier::SupportsPointWiseWeight()
-{
- return true;
-}
-
-bool mitk::VigraRandomForestClassifier::SupportsPointWiseProbability()
-{
- return true;
-}
-
-void mitk::VigraRandomForestClassifier::OnlineTrain(const Eigen::MatrixXd & X_in, const Eigen::MatrixXi &Y_in)
-{
- vigra::MultiArrayView<2, double> X(vigra::Shape2(X_in.rows(),X_in.cols()),X_in.data());
- vigra::MultiArrayView<2, int> Y(vigra::Shape2(Y_in.rows(),Y_in.cols()),Y_in.data());
- m_RandomForest.onlineLearn(X,Y,0,true);
-}
-
-void mitk::VigraRandomForestClassifier::Train(const Eigen::MatrixXd & X_in, const Eigen::MatrixXi &Y_in)
-{
- this->ConvertParameter();
-
- DefaultSplitType splitter;
- splitter.UsePointBasedWeights(m_Parameter->UsePointBasedWeights);
- splitter.UseRandomSplit(m_Parameter->UseRandomSplit);
- splitter.SetPrecision(m_Parameter->Precision);
- splitter.SetMaximumTreeDepth(m_Parameter->TreeDepth);
-
- // Weights handled as member variable
- if (m_Parameter->UsePointBasedWeights)
- {
- // Set influence of the weight (0 no influenc to 1 max influence)
- this->m_PointWiseWeight.unaryExpr([this](double t){ return std::pow(t, this->m_Parameter->WeightLambda) ;});
-
- vigra::MultiArrayView<2, double> W(vigra::Shape2(this->m_PointWiseWeight.rows(),this->m_PointWiseWeight.cols()),this->m_PointWiseWeight.data());
- splitter.SetWeights(W);
- }
-
- vigra::MultiArrayView<2, double> X(vigra::Shape2(X_in.rows(),X_in.cols()),X_in.data());
- vigra::MultiArrayView<2, int> Y(vigra::Shape2(Y_in.rows(),Y_in.cols()),Y_in.data());
-
- m_RandomForest.set_options().tree_count(1); // Number of trees that are calculated;
-
- m_RandomForest.set_options().use_stratification(m_Parameter->Stratification);
- m_RandomForest.set_options().sample_with_replacement(m_Parameter->SampleWithReplacement);
- m_RandomForest.set_options().samples_per_tree(m_Parameter->SamplesPerTree);
- m_RandomForest.set_options().min_split_node_size(m_Parameter->MinimumSplitNodeSize);
-
- m_RandomForest.learn(X, Y,vigra::rf::visitors::VisitorBase(),splitter);
-
- std::unique_ptr<TrainingData> data(new TrainingData(m_Parameter->TreeCount,m_RandomForest,splitter,X,Y, *m_Parameter));
-
- auto threader = itk::MultiThreaderBase::New();
- threader->SetSingleMethod(this->TrainTreesCallback,data.get());
- threader->SingleMethodExecute();
-
- // set result trees
- m_RandomForest.set_options().tree_count(m_Parameter->TreeCount);
- m_RandomForest.ext_param_.class_count_ = data->m_ClassCount;
- m_RandomForest.trees_ = data->trees_;
-
- // Set Tree Weights to default
- m_TreeWeights = Eigen::MatrixXd(m_Parameter->TreeCount,1);
- m_TreeWeights.fill(1.0);
-}
-
-Eigen::MatrixXi mitk::VigraRandomForestClassifier::Predict(const Eigen::MatrixXd &X_in)
-{
- // Initialize output Eigen matrices
- m_OutProbability = Eigen::MatrixXd(X_in.rows(),m_RandomForest.class_count());
- m_OutProbability.fill(0);
- m_OutLabel = Eigen::MatrixXi(X_in.rows(),1);
- m_OutLabel.fill(0);
-
- // If no weights provided
- if(m_TreeWeights.rows() != m_RandomForest.tree_count())
- {
- m_TreeWeights = Eigen::MatrixXd(m_RandomForest.tree_count(),1);
- m_TreeWeights.fill(1);
- }
-
-
- vigra::MultiArrayView<2, double> P(vigra::Shape2(m_OutProbability.rows(),m_OutProbability.cols()),m_OutProbability.data());
- vigra::MultiArrayView<2, int> Y(vigra::Shape2(m_OutLabel.rows(),m_OutLabel.cols()),m_OutLabel.data());
- vigra::MultiArrayView<2, double> X(vigra::Shape2(X_in.rows(),X_in.cols()),X_in.data());
- vigra::MultiArrayView<2, double> TW(vigra::Shape2(m_RandomForest.tree_count(),1),m_TreeWeights.data());
-
- std::unique_ptr<PredictionData> data;
- data.reset(new PredictionData(m_RandomForest, X, Y, P, TW));
-
- auto threader = itk::MultiThreaderBase::New();
- threader->SetSingleMethod(this->PredictCallback, data.get());
- threader->SingleMethodExecute();
-
- m_Probabilities = data->m_Probabilities;
- return m_OutLabel;
-}
-
-Eigen::MatrixXi mitk::VigraRandomForestClassifier::PredictWeighted(const Eigen::MatrixXd &X_in)
-{
- // Initialize output Eigen matrices
- m_OutProbability = Eigen::MatrixXd(X_in.rows(),m_RandomForest.class_count());
- m_OutProbability.fill(0);
- m_OutLabel = Eigen::MatrixXi(X_in.rows(),1);
- m_OutLabel.fill(0);
-
- // If no weights provided
- if(m_TreeWeights.rows() != m_RandomForest.tree_count())
- {
- m_TreeWeights = Eigen::MatrixXd(m_RandomForest.tree_count(),1);
- m_TreeWeights.fill(1);
- }
-
-
- vigra::MultiArrayView<2, double> P(vigra::Shape2(m_OutProbability.rows(),m_OutProbability.cols()),m_OutProbability.data());
- vigra::MultiArrayView<2, int> Y(vigra::Shape2(m_OutLabel.rows(),m_OutLabel.cols()),m_OutLabel.data());
- vigra::MultiArrayView<2, double> X(vigra::Shape2(X_in.rows(),X_in.cols()),X_in.data());
- vigra::MultiArrayView<2, double> TW(vigra::Shape2(m_RandomForest.tree_count(),1),m_TreeWeights.data());
-
- std::unique_ptr<PredictionData> data;
- data.reset( new PredictionData(m_RandomForest,X,Y,P,TW));
-
- auto threader = itk::MultiThreaderBase::New();
- threader->SetSingleMethod(this->PredictWeightedCallback,data.get());
- threader->SingleMethodExecute();
-
- return m_OutLabel;
-}
-
-
-
-void mitk::VigraRandomForestClassifier::SetTreeWeights(Eigen::MatrixXd weights)
-{
- m_TreeWeights = weights;
-}
-
-Eigen::MatrixXd mitk::VigraRandomForestClassifier::GetTreeWeights() const
-{
- return m_TreeWeights;
-}
-
-itk::ITK_THREAD_RETURN_TYPE mitk::VigraRandomForestClassifier::TrainTreesCallback(void * arg)
-{
- // Get the ThreadInfoStruct
- typedef itk::MultiThreaderBase::WorkUnitInfo ThreadInfoType;
- ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( arg );
-
- TrainingData * data = (TrainingData *)(infoStruct->UserData);
- unsigned int numberOfTreesToCalculate = 0;
-
- // define the number of tress the forest have to calculate
- numberOfTreesToCalculate = data->m_NumberOfTrees / infoStruct->NumberOfWorkUnits;
-
- // the 0th thread takes the residuals
- if(infoStruct->WorkUnitID == 0) numberOfTreesToCalculate += data->m_NumberOfTrees % infoStruct->NumberOfWorkUnits;
-
- if(numberOfTreesToCalculate != 0){
- // Copy the Treestructure defined in userData
- vigra::RandomForest<int> rf = data->m_RandomForest;
-
- // Initialize a splitter for the leraning process
- DefaultSplitType splitter;
- splitter.UsePointBasedWeights(data->m_Splitter.IsUsingPointBasedWeights());
- splitter.UseRandomSplit(data->m_Splitter.IsUsingRandomSplit());
- splitter.SetPrecision(data->m_Splitter.GetPrecision());
- splitter.SetMaximumTreeDepth(data->m_Splitter.GetMaximumTreeDepth());
- splitter.SetWeights(data->m_Splitter.GetWeights());
-
- rf.trees_.clear();
- rf.set_options().tree_count(numberOfTreesToCalculate);
- rf.set_options().use_stratification(data->m_Parameter.Stratification);
- rf.set_options().sample_with_replacement(data->m_Parameter.SampleWithReplacement);
- rf.set_options().samples_per_tree(data->m_Parameter.SamplesPerTree);
- rf.set_options().min_split_node_size(data->m_Parameter.MinimumSplitNodeSize);
- rf.learn(data->m_Feature, data->m_Label,vigra::rf::visitors::VisitorBase(),splitter);
-
- data->m_mutex.lock();
-
- for(const auto & tree : rf.trees_)
- data->trees_.push_back(tree);
-
- data->m_ClassCount = rf.class_count();
- data->m_mutex.unlock();
- }
-
- return ITK_THREAD_RETURN_DEFAULT_VALUE;
-
-}
-
-itk::ITK_THREAD_RETURN_TYPE mitk::VigraRandomForestClassifier::PredictCallback(void * arg)
-{
- // Get the ThreadInfoStruct
- typedef itk::MultiThreaderBase::WorkUnitInfo ThreadInfoType;
- ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( arg );
- // assigne the thread id
- const unsigned int threadId = infoStruct->WorkUnitID;
-
- // Get the user defined parameters containing all
- // neccesary informations
- PredictionData * data = (PredictionData *)(infoStruct->UserData);
- unsigned int numberOfRowsToCalculate = 0;
-
- // Get number of rows to calculate
- numberOfRowsToCalculate = data->m_Feature.shape()[0] / infoStruct->NumberOfWorkUnits;
-
- unsigned int start_index = numberOfRowsToCalculate * threadId;
- unsigned int end_index = numberOfRowsToCalculate * (threadId+1);
-
- // the last thread takes the residuals
- if(threadId == infoStruct->NumberOfWorkUnits-1) {
- end_index += data->m_Feature.shape()[0] % infoStruct->NumberOfWorkUnits;
- }
-
- vigra::MultiArrayView<2, double> split_features;
- vigra::MultiArrayView<2, int> split_labels;
- vigra::MultiArrayView<2, double> split_probability;
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index,data->m_Feature.shape(1));
- split_features = data->m_Feature.subarray(lowerBound,upperBound);
- }
-
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index, data->m_Label.shape(1));
- split_labels = data->m_Label.subarray(lowerBound,upperBound);
- }
-
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index,data->m_Probabilities.shape(1));
- split_probability = data->m_Probabilities.subarray(lowerBound,upperBound);
- }
-
- data->m_RandomForest.predictLabels(split_features,split_labels);
- data->m_RandomForest.predictProbabilities(split_features, split_probability);
-
-
- return ITK_THREAD_RETURN_DEFAULT_VALUE;
-
-}
-
-itk::ITK_THREAD_RETURN_TYPE mitk::VigraRandomForestClassifier::PredictWeightedCallback(void * arg)
-{
- // Get the ThreadInfoStruct
- typedef itk::MultiThreaderBase::WorkUnitInfo ThreadInfoType;
- ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( arg );
- // assigne the thread id
- const unsigned int threadId = infoStruct->WorkUnitID;
-
- // Get the user defined parameters containing all
- // neccesary informations
- PredictionData * data = (PredictionData *)(infoStruct->UserData);
- unsigned int numberOfRowsToCalculate = 0;
-
- // Get number of rows to calculate
- numberOfRowsToCalculate = data->m_Feature.shape()[0] / infoStruct->NumberOfWorkUnits;
-
- unsigned int start_index = numberOfRowsToCalculate * threadId;
- unsigned int end_index = numberOfRowsToCalculate * (threadId+1);
-
- // the last thread takes the residuals
- if(threadId == infoStruct->NumberOfWorkUnits-1) {
- end_index += data->m_Feature.shape()[0] % infoStruct->NumberOfWorkUnits;
- }
-
- vigra::MultiArrayView<2, double> split_features;
- vigra::MultiArrayView<2, int> split_labels;
- vigra::MultiArrayView<2, double> split_probability;
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index,data->m_Feature.shape(1));
- split_features = data->m_Feature.subarray(lowerBound,upperBound);
- }
-
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index, data->m_Label.shape(1));
- split_labels = data->m_Label.subarray(lowerBound,upperBound);
- }
-
- {
- vigra::TinyVector<vigra::MultiArrayIndex, 2> lowerBound(start_index,0);
- vigra::TinyVector<vigra::MultiArrayIndex, 2> upperBound(end_index,data->m_Probabilities.shape(1));
- split_probability = data->m_Probabilities.subarray(lowerBound,upperBound);
- }
-
- VigraPredictWeighted(data, split_features,split_labels,split_probability);
-
- return ITK_THREAD_RETURN_DEFAULT_VALUE;
-}
-
-
-void mitk::VigraRandomForestClassifier::VigraPredictWeighted(PredictionData * data, vigra::MultiArrayView<2, double> & X, vigra::MultiArrayView<2, int> & Y, vigra::MultiArrayView<2, double> & P)
-{
-
- int isSampleWeighted = data->m_RandomForest.options_.predict_weighted_;
-//#pragma omp parallel for
- for(int row=0; row < vigra::rowCount(X); ++row)
- {
- vigra::MultiArrayView<2, double, vigra::StridedArrayTag> currentRow(rowVector(X, row));
-
- vigra::ArrayVector<double>::const_iterator weights;
-
- //totalWeight == totalVoteCount!
- double totalWeight = 0.0;
-
- //Let each tree classify...
- for(int k=0; k<data->m_RandomForest.options_.tree_count_; ++k)
- {
- //get weights predicted by single tree
- weights = data->m_RandomForest.trees_[k /*tree_indices_[k]*/].predict(currentRow);
- double numberOfLeafObservations = (*(weights-1));
-
- //update votecount.
- for(int l=0; l<data->m_RandomForest.ext_param_.class_count_; ++l)
- {
- // Either the original weights are taken or the tree is additional weighted by the number of Observations in the leaf node.
- double cur_w = weights[l] * (isSampleWeighted * numberOfLeafObservations + (1-isSampleWeighted));
- cur_w = cur_w * data->m_TreeWeights(k,0);
- P(row, l) += (int)cur_w;
- //every weight in totalWeight.
- totalWeight += cur_w;
- }
- }
-
- //Normalise votes in each row by total VoteCount (totalWeight
- for(int l=0; l< data->m_RandomForest.ext_param_.class_count_; ++l)
- {
- P(row, l) /= vigra::detail::RequiresExplicitCast<double>::cast(totalWeight);
- }
- int erg;
- int maxCol = 0;
- for (int col=0;col<data->m_RandomForest.class_count();++col)
- {
- if (data->m_Probabilities(row,col) > data->m_Probabilities(row, maxCol))
- maxCol = col;
- }
- data->m_RandomForest.ext_param_.to_classlabel(maxCol, erg);
- Y(row,0) = erg;
- }
-}
-
-void mitk::VigraRandomForestClassifier::ConvertParameter()
-{
- if(this->m_Parameter == nullptr)
- this->m_Parameter = new Parameter();
- // Get the proerty // Some defaults
-
- MITK_INFO("VigraRandomForestClassifier") << "Convert Parameter";
- if(!this->GetPropertyList()->Get("usepointbasedweight",this->m_Parameter->UsePointBasedWeights)) this->m_Parameter->UsePointBasedWeights = false;
- if(!this->GetPropertyList()->Get("userandomsplit",this->m_Parameter->UseRandomSplit)) this->m_Parameter->UseRandomSplit = false;
- if(!this->GetPropertyList()->Get("treedepth",this->m_Parameter->TreeDepth)) this->m_Parameter->TreeDepth = 20;
- if(!this->GetPropertyList()->Get("treecount",this->m_Parameter->TreeCount)) this->m_Parameter->TreeCount = 100;
- if(!this->GetPropertyList()->Get("minimalsplitnodesize",this->m_Parameter->MinimumSplitNodeSize)) this->m_Parameter->MinimumSplitNodeSize = 5;
- if(!this->GetPropertyList()->Get("precision",this->m_Parameter->Precision)) this->m_Parameter->Precision = mitk::eps;
- if(!this->GetPropertyList()->Get("samplespertree",this->m_Parameter->SamplesPerTree)) this->m_Parameter->SamplesPerTree = 0.6;
- if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->SampleWithReplacement)) this->m_Parameter->SampleWithReplacement = true;
- if(!this->GetPropertyList()->Get("lambda",this->m_Parameter->WeightLambda)) this->m_Parameter->WeightLambda = 1.0; // Not used yet
- // if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->Stratification))
- this->m_Parameter->Stratification = vigra::RF_NONE; // no Property given
-}
-
-void mitk::VigraRandomForestClassifier::PrintParameter(std::ostream & str)
-{
- if(this->m_Parameter == nullptr)
- {
- MITK_WARN("VigraRandomForestClassifier") << "Parameters are not initialized. Please call ConvertParameter() first!";
- return;
- }
-
- this->ConvertParameter();
-
- // Get the proerty // Some defaults
- if(!this->GetPropertyList()->Get("usepointbasedweight",this->m_Parameter->UsePointBasedWeights))
- str << "usepointbasedweight\tNOT SET (default " << this->m_Parameter->UsePointBasedWeights << ")" << "\n";
- else
- str << "usepointbasedweight\t" << this->m_Parameter->UsePointBasedWeights << "\n";
-
- if(!this->GetPropertyList()->Get("userandomsplit",this->m_Parameter->UseRandomSplit))
- str << "userandomsplit\tNOT SET (default " << this->m_Parameter->UseRandomSplit << ")" << "\n";
- else
- str << "userandomsplit\t" << this->m_Parameter->UseRandomSplit << "\n";
-
- if(!this->GetPropertyList()->Get("treedepth",this->m_Parameter->TreeDepth))
- str << "treedepth\t\tNOT SET (default " << this->m_Parameter->TreeDepth << ")" << "\n";
- else
- str << "treedepth\t\t" << this->m_Parameter->TreeDepth << "\n";
-
- if(!this->GetPropertyList()->Get("minimalsplitnodesize",this->m_Parameter->MinimumSplitNodeSize))
- str << "minimalsplitnodesize\tNOT SET (default " << this->m_Parameter->MinimumSplitNodeSize << ")" << "\n";
- else
- str << "minimalsplitnodesize\t" << this->m_Parameter->MinimumSplitNodeSize << "\n";
-
- if(!this->GetPropertyList()->Get("precision",this->m_Parameter->Precision))
- str << "precision\t\tNOT SET (default " << this->m_Parameter->Precision << ")" << "\n";
- else
- str << "precision\t\t" << this->m_Parameter->Precision << "\n";
-
- if(!this->GetPropertyList()->Get("samplespertree",this->m_Parameter->SamplesPerTree))
- str << "samplespertree\tNOT SET (default " << this->m_Parameter->SamplesPerTree << ")" << "\n";
- else
- str << "samplespertree\t" << this->m_Parameter->SamplesPerTree << "\n";
-
- if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->SampleWithReplacement))
- str << "samplewithreplacement\tNOT SET (default " << this->m_Parameter->SampleWithReplacement << ")" << "\n";
- else
- str << "samplewithreplacement\t" << this->m_Parameter->SampleWithReplacement << "\n";
-
- if(!this->GetPropertyList()->Get("treecount",this->m_Parameter->TreeCount))
- str << "treecount\t\tNOT SET (default " << this->m_Parameter->TreeCount << ")" << "\n";
- else
- str << "treecount\t\t" << this->m_Parameter->TreeCount << "\n";
-
- if(!this->GetPropertyList()->Get("lambda",this->m_Parameter->WeightLambda))
- str << "lambda\t\tNOT SET (default " << this->m_Parameter->WeightLambda << ")" << "\n";
- else
- str << "lambda\t\t" << this->m_Parameter->WeightLambda << "\n";
-
- // if(!this->GetPropertyList()->Get("samplewithreplacement",this->m_Parameter->Stratification))
- // this->m_Parameter->Stratification = vigra:RF_NONE; // no Property given
-}
-
-void mitk::VigraRandomForestClassifier::UsePointWiseWeight(bool val)
-{
- mitk::AbstractClassifier::UsePointWiseWeight(val);
- this->GetPropertyList()->SetBoolProperty("usepointbasedweight",val);
-}
-
-void mitk::VigraRandomForestClassifier::SetMaximumTreeDepth(int val)
-{
- this->GetPropertyList()->SetIntProperty("treedepth",val);
-}
-
-void mitk::VigraRandomForestClassifier::SetMinimumSplitNodeSize(int val)
-{
- this->GetPropertyList()->SetIntProperty("minimalsplitnodesize",val);
-}
-
-void mitk::VigraRandomForestClassifier::SetPrecision(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("precision",val);
-}
-
-void mitk::VigraRandomForestClassifier::SetSamplesPerTree(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("samplespertree",val);
-}
-
-void mitk::VigraRandomForestClassifier::UseSampleWithReplacement(bool val)
-{
- this->GetPropertyList()->SetBoolProperty("samplewithreplacement",val);
-}
-
-void mitk::VigraRandomForestClassifier::SetTreeCount(int val)
-{
- this->GetPropertyList()->SetIntProperty("treecount",val);
-}
-
-void mitk::VigraRandomForestClassifier::SetWeightLambda(double val)
-{
- this->GetPropertyList()->SetDoubleProperty("lambda",val);
-}
-
-void mitk::VigraRandomForestClassifier::SetTreeWeight(int treeId, double weight)
-{
- m_TreeWeights(treeId,0) = weight;
-}
-
-void mitk::VigraRandomForestClassifier::SetRandomForest(const vigra::RandomForest<int> & rf)
-{
- this->SetMaximumTreeDepth(rf.ext_param().max_tree_depth);
- this->SetMinimumSplitNodeSize(rf.options().min_split_node_size_);
- this->SetTreeCount(rf.options().tree_count_);
- this->SetSamplesPerTree(rf.options().training_set_proportion_);
- this->UseSampleWithReplacement(rf.options().sample_with_replacement_);
- this->m_RandomForest = rf;
-}
-
-const vigra::RandomForest<int> & mitk::VigraRandomForestClassifier::GetRandomForest() const
-{
- return this->m_RandomForest;
-}
diff --git a/Modules/Classification/CLVigraRandomForest/src/IO/mitkDummyLsetReader.cpp b/Modules/Classification/CLVigraRandomForest/src/IO/mitkDummyLsetReader.cpp
deleted file mode 100644
index a1ae48a41a..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/IO/mitkDummyLsetReader.cpp
+++ /dev/null
@@ -1,66 +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 <mitkDummyLsetReader.h>
-#include <itksys/SystemTools.hxx>
-#include <itkImageFileReader.h>
-#include <itkNrrdImageIO.h>
-#include <mitkImageCast.h>
-#include <mitkCustomMimeType.h>
-
-typedef itk::Image<unsigned char, 3> ImageType;
-
-std::vector<itk::SmartPointer<mitk::BaseData> > mitk::DummyLsetFileReader::DoRead()
-{
-
- std::vector<itk::SmartPointer<mitk::BaseData> > result;
- typedef itk::ImageFileReader<ImageType> FileReaderType;
- FileReaderType::Pointer reader = FileReaderType::New();
- reader->SetFileName(this->GetInputLocation());
- itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
- reader->SetImageIO(io);
- reader->Update();
-
- mitk::Image::Pointer img;
- mitk::CastToMitkImage(reader->GetOutput(),img);
- result.push_back(img.GetPointer());
-
- return result;
-}
-
-
-mitk::DummyLsetFileReader::DummyLsetFileReader(const DummyLsetFileReader & other)
- : AbstractFileReader(other)
-{
-}
-
-
-mitk::DummyLsetFileReader* mitk::DummyLsetFileReader::Clone() const
-{
- return new DummyLsetFileReader(*this);
-}
-
-
-mitk::DummyLsetFileReader::~DummyLsetFileReader()
-{}
-
-
-mitk::DummyLsetFileReader::DummyLsetFileReader()
-{
- CustomMimeType mimeType(this->GetMimeTypePrefix() + "lset");
- mimeType.AddExtension("lset");
- mimeType.SetCategory("Images");
- mimeType.SetComment("Experimental MBI LabelSetImage");
- this->SetMimeType(mimeType);
- this->SetDescription("MBI LabelSetImage");
- this->RegisterService();
-}
-
diff --git a/Modules/Classification/CLVigraRandomForest/src/IO/mitkRandomForestIO.cpp b/Modules/Classification/CLVigraRandomForest/src/IO/mitkRandomForestIO.cpp
deleted file mode 100644
index 79a0e270fb..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/IO/mitkRandomForestIO.cpp
+++ /dev/null
@@ -1,218 +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.
-
-============================================================================*/
-
-#ifndef __mitkDecisionForestIO__cpp
-#define __mitkDecisionForestIO__cpp
-
-#include "mitkRandomForestIO.h"
-#include "itksys/SystemTools.hxx"
-//#include "mitkHDF5IOMimeTypes.h"
-
-#include "vigra/random_forest_hdf5_impex.hxx"
-
-#include <iostream>
-#include <fstream>
-
-#include "mitkVigraRandomForestClassifier.h"
-#include "mitkIOMimeTypes.h"
-
-#define GetAttribute(name,type)\
- type name;\
- hdf5_file.readAttribute(".",name,name);
-
-mitk::RandomForestFileIO::ConfidenceLevel mitk::RandomForestFileIO::GetReaderConfidenceLevel() const
-{
- std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetLocalFileName().c_str());
- bool is_loaded = vigra::rf_import_HDF5(m_rf, this->GetInputLocation());
- return ext == ".forest" && is_loaded == true? IFileReader::Supported : IFileReader::Unsupported;
-}
-
-mitk::RandomForestFileIO::ConfidenceLevel mitk::RandomForestFileIO::GetWriterConfidenceLevel() const
-{
- mitk::VigraRandomForestClassifier::ConstPointer input = dynamic_cast<const mitk::VigraRandomForestClassifier *>(this->GetInput());
- if (input.IsNull())
- {
- return IFileWriter::Unsupported;
- }else{
- return IFileWriter::Supported;
- }
-}
-
-mitk::RandomForestFileIO::RandomForestFileIO()
- : AbstractFileIO(mitk::VigraRandomForestClassifier::GetStaticNameOfClass())
-{
- CustomMimeType customReaderMimeType(mitk::IOMimeTypes::DEFAULT_BASE_NAME() + ".forest");
- std::string category = "Vigra Random Forest File";
- customReaderMimeType.SetComment("Vigra Random Forest");
- customReaderMimeType.SetCategory(category);
- customReaderMimeType.AddExtension("forest");
-
- // this->AbstractFileIOWriter::SetRanking(100);
- this->AbstractFileWriter::SetMimeTypePrefix(mitk::IOMimeTypes::DEFAULT_BASE_NAME() + ".forest");
- this->AbstractFileWriter::SetMimeType(customReaderMimeType);
- this->SetWriterDescription("Vigra Random Forest");
- this->AbstractFileReader::SetMimeTypePrefix(mitk::IOMimeTypes::DEFAULT_BASE_NAME() + ".forest");
- this->AbstractFileReader::SetMimeType(customReaderMimeType);
- this->SetReaderDescription("Vigra Random Forest");
-
- // this->SetReaderDescription(mitk::DecisionForestIOMimeTypes::DECISIONFOREST_MIMETYPE_DESCRIPTION());
- // this->SetWriterDescription(mitk::DecisionForestIOMimeTypes::DECISIONFOREST_MIMETYPE_DESCRIPTION());
- this->RegisterService();
-}
-
-mitk::RandomForestFileIO::RandomForestFileIO(const mitk::RandomForestFileIO& other)
- : AbstractFileIO(other)
-{
-}
-
-mitk::RandomForestFileIO::~RandomForestFileIO()
-{}
-
-std::vector<itk::SmartPointer<mitk::BaseData> >
-mitk::RandomForestFileIO::
-DoRead()
-{
- mitk::VigraRandomForestClassifier::Pointer output = mitk::VigraRandomForestClassifier::New();
- std::vector<itk::SmartPointer<mitk::BaseData> > result;
-
- if ( this->GetInputLocation().empty())
- {
- MITK_ERROR << "Sorry, filename has not been set!";
- return result;
- }
- else
- {
- const std::string& locale = "C";
- const std::string& currLocale = setlocale( LC_ALL, nullptr );
-
- if ( locale.compare(currLocale)!=0 )
- {
- try
- {
- setlocale(LC_ALL, locale.c_str());
- }
- catch(...)
- {
- MITK_INFO << "Could not set locale " << locale;
- }
- }
-
- output->SetRandomForest(m_rf);
- result.push_back(output.GetPointer());
- vigra::HDF5File hdf5_file(this->GetInputLocation() , vigra::HDF5File::Open);
-
-
- hdf5_file.cd_mk("/_mitkOptions");
-
- // ---------------------------------------------------------
- // Read tree weights
- if(hdf5_file.existsDataset("treeWeights"))
- {
- auto treeWeight = output->GetTreeWeights();
- treeWeight.resize(m_rf.tree_count(),1);
- vigra::MultiArrayView<2, double> W(vigra::Shape2(treeWeight.rows(),treeWeight.cols()),treeWeight.data());
- hdf5_file.read("treeWeights",W);
- output->SetTreeWeights(treeWeight);
- }
- // ---------------------------------------------------------
-
- // ---------------------------------------------------------
- // Read itemList
- if(hdf5_file.existsDataset("itemList")){
- std::string items_string;
- hdf5_file.read("itemList",items_string);
- auto itemlist = output->GetItemList();
-
- std::string current_item = "";
- for(auto character : items_string)
- {
- if(character == ';'){
- // skip seperator and push back item
- itemlist.push_back(current_item);
- current_item.clear();
- }else{
- current_item = current_item + character;
- }
- }
- output->SetItemList(itemlist);
- }
- // ---------------------------------------------------------
-
- hdf5_file.close();
-
- return result;
- }
-}
-
-void mitk::RandomForestFileIO::Write()
-{
- mitk::BaseData::ConstPointer input = this->GetInput();
- if (input.IsNull())
- {
- MITK_ERROR <<"Sorry, input to NrrdDiffusionImageWriter is nullptr!";
- return;
- }
- if ( this->GetOutputLocation().empty() )
- {
- MITK_ERROR << "Sorry, filename has not been set!";
- return ;
- }else{
- const std::string& locale = "C";
- const std::string& currLocale = setlocale( LC_ALL, nullptr );
-
- if ( locale.compare(currLocale)!=0 )
- {
- try
- {
- setlocale(LC_ALL, locale.c_str());
- }
- catch(...)
- {
- MITK_INFO << "Could not set locale " << locale;
- }
- }
-
- mitk::VigraRandomForestClassifier::ConstPointer mitkDC = dynamic_cast<const mitk::VigraRandomForestClassifier *>(input.GetPointer());
- //mitkDC->GetRandomForest()
- vigra::rf_export_HDF5(mitkDC->GetRandomForest(), this->GetOutputLocation());
-
- vigra::HDF5File hdf5_file(this->GetOutputLocation() , vigra::HDF5File::Open);
-
- hdf5_file.cd_mk("/_mitkOptions");
-
- // Write tree weights
- // ---------------------------------------------------------
- auto treeWeight = mitkDC->GetTreeWeights();
- vigra::MultiArrayView<2, double> W(vigra::Shape2(treeWeight.rows(),treeWeight.cols()),treeWeight.data());
- hdf5_file.write("treeWeights",W);
- // ---------------------------------------------------------
-
- // Write itemList
- // ---------------------------------------------------------
- auto items = mitkDC->GetItemList();
- std::string item_stringlist;
- for(auto entry : items)
- item_stringlist = item_stringlist + entry + ";";
-
- hdf5_file.write("itemList",item_stringlist);
- // ---------------------------------------------------------
-
- hdf5_file.close();
- }
-}
-
-mitk::AbstractFileIO* mitk::RandomForestFileIO::IOClone() const
-{
- return new RandomForestFileIO(*this);
-}
-
-#endif
diff --git a/Modules/Classification/CLVigraRandomForest/src/IO/mitkVigraRandomForestClassifierSerializer.cpp b/Modules/Classification/CLVigraRandomForest/src/IO/mitkVigraRandomForestClassifierSerializer.cpp
deleted file mode 100644
index 1c1e5c8cda..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/IO/mitkVigraRandomForestClassifierSerializer.cpp
+++ /dev/null
@@ -1,64 +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 "mitkVigraRandomForestClassifierSerializer.h"
-#include "mitkIOUtil.h"
-#include "mitkVigraRandomForestClassifier.h"
-
-#include <itksys/SystemTools.hxx>
-
-MITK_REGISTER_SERIALIZER(VigraRandomForestClassifierSerializer)
-
-mitk::VigraRandomForestClassifierSerializer::VigraRandomForestClassifierSerializer()
-{
-}
-
-mitk::VigraRandomForestClassifierSerializer::~VigraRandomForestClassifierSerializer()
-{
-}
-
-std::string mitk::VigraRandomForestClassifierSerializer::Serialize()
-{
- const mitk::VigraRandomForestClassifier* data = dynamic_cast<const mitk::VigraRandomForestClassifier*>( m_Data.GetPointer() );
- if (!data)
- {
- MITK_ERROR << " Object at " << (const void*) this->m_Data
- << " is not an mitk::ContourModelSet. Cannot serialize as contour model set.";
- return "";
- }
-
- std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
- filename += "_";
- filename += m_FilenameHint;
- filename += ".hdf5";
-
- std::string fullname(m_WorkingDirectory);
- fullname += "/";
- fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
-
- try
- {
- mitk::IOUtil::Save(const_cast<mitk::VigraRandomForestClassifier*>( data ),fullname);
- }
- catch ( const std::exception& e )
- {
- MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
- << " to "
- << fullname
- << ": "
- << e.what();
- return "";
- }
-
- return filename;
-}
-
diff --git a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkImpurityLoss.cpp b/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkImpurityLoss.cpp
deleted file mode 100644
index 01beaf1144..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkImpurityLoss.cpp
+++ /dev/null
@@ -1,124 +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.
-
-============================================================================*/
-
-#ifndef mitkImpurityLoss_cpp
-#define mitkImpurityLoss_cpp
-
-#include <mitkImpurityLoss.h>
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class T>
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::ImpurityLoss(TLabelContainer const &labels,
- vigra::ProblemSpec<T> const &ext,
- AdditionalRFDataAbstract * /*data*/) :
- m_UsePointWeights(false),
- m_Labels(labels),
- m_Counts(ext.class_count_, 0.0),
- m_ClassWeights(ext.class_weights_),
- m_TotalCount(0.0)
-{
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-void
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Reset()
-{
- m_Counts.init(0);
- m_TotalCount = 0.0;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class TDataIterator>
-double
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Increment(TDataIterator begin, TDataIterator end)
-{
- for (TDataIterator iter = begin; iter != end; ++iter)
- {
- double pointProbability = 1.0;
- if (m_UsePointWeights)
- {
- pointProbability = m_PointWeights(*iter,0);
- }
- m_Counts[m_Labels(*iter,0)] += pointProbability;
- m_TotalCount += pointProbability;
- }
- return m_LossFunction(m_Counts, m_ClassWeights, m_TotalCount);
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class TDataIterator>
-double
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Decrement(TDataIterator begin, TDataIterator end)
-{
- for (TDataIterator iter = begin; iter != end; ++iter)
- {
- double pointProbability = 1.0;
- if (m_UsePointWeights)
- {
- pointProbability = m_PointWeights(*iter,0);
- }
- m_Counts[m_Labels(*iter,0)] -= pointProbability;
- m_TotalCount -= pointProbability;
- }
- return m_LossFunction(m_Counts, m_ClassWeights, m_TotalCount);
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class TArray>
-double
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Init(TArray initCounts)
-{
- Reset();
- std::copy(initCounts.begin(), initCounts.end(), m_Counts.begin());
- m_TotalCount = std::accumulate(m_Counts.begin(), m_Counts.end(), 0.0);
- return m_LossFunction(m_Counts, m_ClassWeights, m_TotalCount);
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-vigra::ArrayVector<double> const&
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Response()
-{
- return m_Counts;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-void
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::UsePointWeights(bool useWeights)
-{
- m_UsePointWeights = useWeights;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-bool
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::IsUsingPointWeights()
-{
- return m_UsePointWeights;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-void
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::SetPointWeights(TWeightContainer weight)
-{
- m_PointWeights = weight;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-typename mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::WeightContainerType
-mitk::ImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::GetPointWeights()
-{
- return m_PointWeights;
-}
-
-
-#endif // mitkImpurityLoss_cpp
-
-
diff --git a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkLinearSplitting.cpp b/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkLinearSplitting.cpp
deleted file mode 100644
index 55fdb7ebb0..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkLinearSplitting.cpp
+++ /dev/null
@@ -1,196 +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.
-
-============================================================================*/
-
-#ifndef mitkLinearSplitting_cpp
-#define mitkLinearSplitting_cpp
-
-#include <mitkLinearSplitting.h>
-#include <mitkPUImpurityLoss.h>
-
-template<class TLossAccumulator>
-mitk::LinearSplitting<TLossAccumulator>::LinearSplitting() :
- m_UsePointWeights(false),
- m_UseRandomSplit(false),
- m_AdditionalData(nullptr)
-{
-}
-
-template<class TLossAccumulator>
-template <class T>
-mitk::LinearSplitting<TLossAccumulator>::LinearSplitting(vigra::ProblemSpec<T> const &ext) :
- m_UsePointWeights(false),
- m_UseRandomSplit(false)
-{
- set_external_parameters(ext);
-}
-
-template<class TLossAccumulator>
-void
-mitk::LinearSplitting<TLossAccumulator>::SetAdditionalData(AdditionalRFDataAbstract* data)
-{
- m_AdditionalData = data;
-}
-
-template<class TLossAccumulator>
-mitk::AdditionalRFDataAbstract *
-mitk::LinearSplitting<TLossAccumulator>::GetAdditionalData() const
-{
- return m_AdditionalData;
-}
-
-template<class TLossAccumulator>
-void
-mitk::LinearSplitting<TLossAccumulator>::UsePointWeights(bool pointWeight)
-{
- m_UsePointWeights = pointWeight;
-}
-
-template<class TLossAccumulator>
-bool
-mitk::LinearSplitting<TLossAccumulator>::IsUsingPointWeights()
-{
- return m_UsePointWeights;
-}
-
-
-template<class TLossAccumulator>
-void
-mitk::LinearSplitting<TLossAccumulator>::UseRandomSplit(bool randomSplit)
-{
- m_UseRandomSplit = randomSplit;
-}
-
-template<class TLossAccumulator>
-bool
-mitk::LinearSplitting<TLossAccumulator>::IsUsingRandomSplit()
-{
- return m_UseRandomSplit;
-}
-
-template<class TLossAccumulator>
-void
-mitk::LinearSplitting<TLossAccumulator>::SetPointWeights(WeightContainerType weight)
-{
- m_PointWeights = weight;
-}
-
-template<class TLossAccumulator>
-typename mitk::LinearSplitting<TLossAccumulator>::WeightContainerType
-mitk::LinearSplitting<TLossAccumulator>::GetPointWeights()
-{
- return m_PointWeights;
-}
-
-template<class TLossAccumulator>
-template <class T>
-void
-mitk::LinearSplitting<TLossAccumulator>::set_external_parameters(vigra::ProblemSpec<T> const &ext)
-{
- m_ExtParameter = ext;
-}
-
-template<class TLossAccumulator>
-template <class TDataSourceFeature, class TDataSourceLabel, class TDataIterator, class TArray>
-void
-mitk::LinearSplitting<TLossAccumulator>::operator()(TDataSourceFeature const &column,
- TDataSourceLabel const &labels,
- TDataIterator &begin,
- TDataIterator &end,
- TArray const &regionResponse)
-{
- typedef TLossAccumulator LineSearchLoss;
- std::sort(begin, end, vigra::SortSamplesByDimensions<TDataSourceFeature>(column, 0));
-
- LineSearchLoss left(labels, m_ExtParameter, m_AdditionalData);
- LineSearchLoss right(labels, m_ExtParameter, m_AdditionalData);
-
- if (m_UsePointWeights)
- {
- left.UsePointWeights(true);
- left.SetPointWeights(m_PointWeights);
- right.UsePointWeights(true);
- right.SetPointWeights(m_PointWeights);
- }
-
- m_MinimumLoss = right.Init(regionResponse);
- m_MinimumThreshold = *begin;
- m_MinimumIndex = 0;
-
- vigra::DimensionNotEqual<TDataSourceFeature> compareNotEqual(column, 0);
-
- if (!m_UseRandomSplit)
- {
- TDataIterator iter = begin;
- // Find the next element that are NOT equal with his neightbour!
- TDataIterator next = std::adjacent_find(iter, end, compareNotEqual);
-
- while(next != end)
- {
- // Remove or add the current segment are from the LineSearch
- double rightLoss = right.Decrement(iter, next +1);
- double leftLoss = left.Increment(iter, next +1);
- double currentLoss = rightLoss + leftLoss;
-
- if (currentLoss < m_MinimumLoss)
- {
- m_BestCurrentCounts[0] = left.Response();
- m_BestCurrentCounts[1] = right.Response();
- m_MinimumLoss = currentLoss;
- m_MinimumIndex = next - begin + 1;
- m_MinimumThreshold = (double(column(*next,0)) + double(column(*(next +1), 0)))/2.0;
- }
-
- iter = next + 1;
- next = std::adjacent_find(iter, end, compareNotEqual);
- }
- }
- else // If Random split is selected, e.g. ExtraTree behaviour
- {
- int size = end - begin + 1;
- srand(time(nullptr));
- int offset = rand() % size;
- TDataIterator iter = begin + offset;
-
- double rightLoss = right.Decrement(begin, iter+1);
- double leftLoss = left.Increment(begin, iter+1);
- double currentLoss = rightLoss + leftLoss;
-
- if (currentLoss < m_MinimumLoss)
- {
- m_BestCurrentCounts[0] = left.Response();
- m_BestCurrentCounts[1] = right.Response();
- m_MinimumLoss = currentLoss;
- m_MinimumIndex = offset + 1;
- m_MinimumThreshold = (double(column(*iter,0)) + double(column(*(iter+1), 0)))/2.0;
- }
- }
-}
-
-template<class TLossAccumulator>
-template <class TDataSourceLabel, class TDataIterator, class TArray>
-double
-mitk::LinearSplitting<TLossAccumulator>::LossOfRegion(TDataSourceLabel const & labels,
- TDataIterator &/*begin*/,
- TDataIterator &/*end*/,
- TArray const & regionResponse)
-{
- typedef TLossAccumulator LineSearchLoss;
- LineSearchLoss regionLoss(labels, m_ExtParameter, m_AdditionalData);
- if (m_UsePointWeights)
- {
- regionLoss.UsePointWeights(true);
- regionLoss.SetPointWeights(m_PointWeights);
- }
- return regionLoss.Init(regionResponse);
-}
-
-#endif //mitkLinearSplitting_cpp
diff --git a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkPUImpurityLoss.cpp b/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkPUImpurityLoss.cpp
deleted file mode 100644
index e47cbd96f7..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkPUImpurityLoss.cpp
+++ /dev/null
@@ -1,148 +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.
-
-============================================================================*/
-
-#ifndef mitkPUImpurityLoss_cpp
-#define mitkPUImpurityLoss_cpp
-
-#include <mitkPUImpurityLoss.h>
-#include <mitkAdditionalRFData.h>
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class T>
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::PUImpurityLoss(TLabelContainer const &labels,
- vigra::ProblemSpec<T> const &ext,
- AdditionalRFDataAbstract *data) :
- m_UsePointWeights(false),
- m_Labels(labels),
- //m_Kappa(ext.kappa_), // Not possible due to data type
- m_Counts(ext.class_count_, 0.0),
- m_PUCounts(ext.class_count_, 0.0),
- m_ClassWeights(ext.class_weights_),
- m_TotalCount(0.0),
- m_PUTotalCount(0.0),
- m_ClassCount(ext.class_count_)
-{
- mitk::PURFData * purfdata = dynamic_cast<PURFData *> (data);
- //const PURFProblemSpec<T> *problem = static_cast<const PURFProblemSpec<T> * > (&ext);
- m_Kappa = vigra::ArrayVector<double>(purfdata->m_Kappa);
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-void
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Reset()
-{
- m_Counts.init(0);
- m_TotalCount = 0.0;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-void
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::UpdatePUCounts()
-{
- m_PUTotalCount = 0;
- for (int i = 1; i < m_ClassCount; ++i)
- {
- m_PUCounts[i] = m_Kappa[i] * m_Counts[i];
- m_PUTotalCount += m_PUCounts[i];
- }
- m_PUCounts[0] = std::max(0.0, m_TotalCount - m_PUTotalCount);
- m_PUTotalCount += m_PUCounts[0];
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class TDataIterator>
-double
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Increment(TDataIterator begin, TDataIterator end)
-{
- for (TDataIterator iter = begin; iter != end; ++iter)
- {
- double pointProbability = 1.0;
- if (m_UsePointWeights)
- {
- pointProbability = m_PointWeights(*iter,0);
- }
- m_Counts[m_Labels(*iter,0)] += pointProbability;
- m_TotalCount += pointProbability;
- }
- UpdatePUCounts();
- return m_LossFunction(m_PUCounts, m_ClassWeights, m_PUTotalCount);
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class TDataIterator>
-double
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Decrement(TDataIterator begin, TDataIterator end)
-{
- for (TDataIterator iter = begin; iter != end; ++iter)
- {
- double pointProbability = 1.0;
- if (m_UsePointWeights)
- {
- pointProbability = m_PointWeights(*iter,0);
- }
- m_Counts[m_Labels(*iter,0)] -= pointProbability;
- m_TotalCount -= pointProbability;
- }
- UpdatePUCounts();
- return m_LossFunction(m_PUCounts, m_ClassWeights, m_PUTotalCount);
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-template <class TArray>
-double
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Init(TArray initCounts)
-{
- Reset();
- std::copy(initCounts.begin(), initCounts.end(), m_Counts.begin());
- m_TotalCount = std::accumulate(m_Counts.begin(), m_Counts.end(), 0.0);
- return m_LossFunction(m_Counts, m_ClassWeights, m_TotalCount);
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-vigra::ArrayVector<double> const&
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::Response()
-{
- return m_Counts;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-void
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::UsePointWeights(bool useWeights)
-{
- m_UsePointWeights = useWeights;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-bool
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::IsUsingPointWeights()
-{
- return m_UsePointWeights;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-void
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::SetPointWeights(TWeightContainer weight)
-{
- m_PointWeights = weight;
-}
-
-template <class TLossFunction, class TLabelContainer, class TWeightContainer>
-typename mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::WeightContainerType
-mitk::PUImpurityLoss<TLossFunction, TLabelContainer, TWeightContainer>::GetPointWeights()
-{
- return m_PointWeights;
-}
-
-
-#endif // mitkImpurityLoss_cpp
-
-
diff --git a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkThresholdSplit.cpp b/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkThresholdSplit.cpp
deleted file mode 100644
index dc5ee0e46d..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkThresholdSplit.cpp
+++ /dev/null
@@ -1,325 +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.
-
-============================================================================*/
-
-#ifndef mitkThresholdSplit_cpp
-#define mitkThresholdSplit_cpp
-
-#include <mitkThresholdSplit.h>
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::ThresholdSplit() :
- m_CalculatingFeature(false),
- m_UseWeights(false),
- m_UseRandomSplit(false),
- m_Precision(0.0),
- m_MaximumTreeDepth(1000),
- m_AdditionalData(nullptr)
-{
-}
-
-//template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-//mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::ThresholdSplit(const ThresholdSplit & /*other*/)/*:
-// m_CalculatingFeature(other.IsCalculatingFeature()),
-// m_UseWeights(other.IsUsingPointBasedWeights()),
-// m_UseRandomSplit(other.IsUsingRandomSplit()),
-// m_Precision(other.GetPrecision()),
-// m_MaximumTreeDepth(other.GetMaximumTreeDepth()),
-// m_FeatureCalculator(other.GetFeatureCalculator()),
-// m_Weights(other.GetWeights())*/
-//{
-//}
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::SetAdditionalData(AdditionalRFDataAbstract* data)
-{
- bgfunc.SetAdditionalData(data);
- m_AdditionalData = data;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-mitk::AdditionalRFDataAbstract *
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::GetAdditionalData() const
-{
- return m_AdditionalData;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::SetFeatureCalculator(TFeatureCalculator processor)
-{
- m_FeatureCalculator = processor;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-TFeatureCalculator
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::GetFeatureCalculator() const
-{
- return m_FeatureCalculator;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::SetCalculatingFeature(bool calculate)
-{
- m_CalculatingFeature = calculate;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-bool
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::IsCalculatingFeature() const
-{
- return m_CalculatingFeature;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::UsePointBasedWeights(bool weightsOn)
-{
- m_UseWeights = weightsOn;
- bgfunc.UsePointWeights(weightsOn);
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-bool
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::IsUsingPointBasedWeights() const
-{
- return m_UseWeights;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::SetPrecision(double value)
-{
- m_Precision = value;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-double
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::GetPrecision() const
-{
- return m_Precision;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::SetMaximumTreeDepth(int value)
-{
- m_MaximumTreeDepth = value;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-int
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::GetMaximumTreeDepth() const
-{
- return m_MaximumTreeDepth;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::SetWeights(vigra::MultiArrayView<2, double> weights)
-{
- m_Weights = weights;
- bgfunc.UsePointWeights(m_UseWeights);
- bgfunc.SetPointWeights(weights);
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-vigra::MultiArrayView<2, double>
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::GetWeights() const
-{
- return m_Weights;
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-double
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::minGini() const
-{
- return min_gini_[bestSplitIndex];
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-int
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::bestSplitColumn() const
-{
- return splitColumns[bestSplitIndex];
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-double
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::bestSplitThreshold() const
-{
- return min_thresholds_[bestSplitIndex];
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-template<class T>
-void
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::set_external_parameters(vigra::ProblemSpec<T> const & in)
-{
- SB::set_external_parameters(in);
- bgfunc.set_external_parameters( SB::ext_param_);
- int featureCount_ = SB::ext_param_.column_count_;
- splitColumns.resize(featureCount_);
- for(int k=0; k<featureCount_; ++k)
- splitColumns[k] = k;
- min_gini_.resize(featureCount_);
- min_indices_.resize(featureCount_);
- min_thresholds_.resize(featureCount_);
-}
-
-template<class TColumnDecisionFunctor, class TFeatureCalculator, class TTag>
-template<class T, class C, class T2, class C2, class Region, class Random>
-int
-mitk::ThresholdSplit<TColumnDecisionFunctor, TFeatureCalculator, TTag>::findBestSplit(vigra::MultiArrayView<2, T, C> features,
- vigra::MultiArrayView<2, T2, C2> labels,
- Region & region,
- vigra::ArrayVector<Region>& childRegions,
- Random & randint)
-{
- typedef typename Region::IndexIterator IndexIteratorType;
-
- if (m_CalculatingFeature)
- {
- // Do some very fance stuff here!!
-
- // This is not so simple as it might look! We need to
- // remember which feature has been used to be able to
- // use it for testing again!!
- // There, no Splitting class is used!!
- }
-
- bgfunc.UsePointWeights(m_UseWeights);
- bgfunc.UseRandomSplit(m_UseRandomSplit);
-
- vigra::detail::Correction<TTag>::exec(region, labels);
- // Create initial class count.
- for(std::size_t i = 0; i < region.classCounts_.size(); ++i)
- {
- region.classCounts_[i] = 0;
- }
- double regionSum = 0;
- for (typename Region::IndexIterator iter = region.begin(); iter != region.end(); ++iter)
- {
- double probability = 1.0;
- if (m_UseWeights)
- {
- probability = m_Weights(*iter, 0);
- }
- region.classCounts_[labels(*iter,0)] += probability;
- regionSum += probability;
- }
- region.classCountsIsValid = true;
- vigra::ArrayVector<double> vec;
-
- // Is pure region?
- region_gini_ = bgfunc.LossOfRegion(labels,
- region.begin(),
- region.end(),
- region.classCounts());
- if (region_gini_ <= m_Precision * regionSum) // Necessary to fix wrong calculation of Gini-Index
- {
- return this->makeTerminalNode(features, labels, region, randint);
- }
-
- // Randomize the order of columns
- for (int i = 0; i < SB::ext_param_.actual_mtry_; ++i)
- {
- std::swap(splitColumns[i],
- splitColumns[i+ randint(features.shape(1) - i)]);
- }
-
- // find the split with the best evaluation value
- bestSplitIndex = 0;
- double currentMiniGini = region_gini_;
- int numberOfTrials = features.shape(1);
- for (int k = 0; k < numberOfTrials; ++k)
- {
- bgfunc(columnVector(features, splitColumns[k]),
- labels,
- region.begin(), region.end(),
- region.classCounts());
- min_gini_[k] = bgfunc.GetMinimumLoss();
- min_indices_[k] = bgfunc.GetMinimumIndex();
- min_thresholds_[k] = bgfunc.GetMinimumThreshold();
-
- // removed classifier test section, because not necessary
- if (bgfunc.GetMinimumLoss() < currentMiniGini)
- {
- currentMiniGini = bgfunc.GetMinimumLoss();
- childRegions[0].classCounts() = bgfunc.GetBestCurrentCounts()[0];
- childRegions[1].classCounts() = bgfunc.GetBestCurrentCounts()[1];
- childRegions[0].classCountsIsValid = true;
- childRegions[1].classCountsIsValid = true;
-
- bestSplitIndex = k;
- numberOfTrials = SB::ext_param_.actual_mtry_;
- }
- }
-
- //If only a small improvement, make terminal node...
- if(vigra::closeAtTolerance(currentMiniGini, region_gini_))
- {
- return this->makeTerminalNode(features, labels, region, randint);
- }
-
- vigra::Node<vigra::i_ThresholdNode> node(SB::t_data, SB::p_data);
- SB::node_ = node;
- node.threshold() = min_thresholds_[bestSplitIndex];
- node.column() = splitColumns[bestSplitIndex];
-
- // partition the range according to the best dimension
- vigra::SortSamplesByDimensions<vigra::MultiArrayView<2, T, C> >
- sorter(features, node.column(), node.threshold());
- IndexIteratorType bestSplit =
- std::partition(region.begin(), region.end(), sorter);
- // Save the ranges of the child stack entries.
- childRegions[0].setRange( region.begin() , bestSplit );
- childRegions[0].rule = region.rule;
- childRegions[0].rule.push_back(std::make_pair(1, 1.0));
- childRegions[1].setRange( bestSplit , region.end() );
- childRegions[1].rule = region.rule;
- childRegions[1].rule.push_back(std::make_pair(1, 1.0));
-
- return vigra::i_ThresholdNode;
-
- return 0;
-}
-
-//template<class TRegion, class TRegionIterator, class TLabelHolder, class TWeightsHolder>
-//static void UpdateRegionCounts(TRegion & region, TRegionIterator begin, TRegionIterator end, TLabelHolder labels, TWeightsHolder weights)
-//{
-// if(std::accumulate(region.classCounts().begin(),
-// region.classCounts().end(), 0.0) != region.size())
-// {
-// RandomForestClassCounter< LabelT,
-// ArrayVector<double> >
-// counter(labels, region.classCounts());
-// std::for_each( region.begin(), region.end(), counter);
-// region.classCountsIsValid = true;
-// }
-//}
-//
-//template<class TRegion, class TLabel, class TWeights>
-//static void exec(Region & region, LabelT & labels)
-//{
-// if(std::accumulate(region.classCounts().begin(),
-// region.classCounts().end(), 0.0) != region.size())
-// {
-// RandomForestClassCounter< LabelT,
-// ArrayVector<double> >
-// counter(labels, region.classCounts());
-// std::for_each( region.begin(), region.end(), counter);
-// region.classCountsIsValid = true;
-// }
-//}
-
-#endif //mitkThresholdSplit_cpp
diff --git a/Modules/Classification/CLVigraRandomForest/src/mitkModuleActivator.cpp b/Modules/Classification/CLVigraRandomForest/src/mitkModuleActivator.cpp
deleted file mode 100644
index 2374e7e823..0000000000
--- a/Modules/Classification/CLVigraRandomForest/src/mitkModuleActivator.cpp
+++ /dev/null
@@ -1,51 +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 <usModuleActivator.h>
-#include <usModuleContext.h>
-#include <mitkRandomForestIO.h>
-#include "mitkNodePredicateDataType.h"
-#include <mitkDummyLsetReader.h>
-
-namespace mitk
-{
-
- /**
- \brief Registers services for segmentation module.
- */
- class ModuleActivator : public us::ModuleActivator
- {
- public:
-
- void Load(us::ModuleContext*) override
- {
-
- // *-----------------*
- // * IO
- // *-----------------*
-
- m_DecisionForestIO = new mitk::RandomForestFileIO();
- m_DummyLsetReader = new mitk::DummyLsetFileReader();
- }
-
- void Unload(us::ModuleContext*) override
- {
- delete m_DecisionForestIO;
- delete m_DummyLsetReader;
- }
-
- private:
- mitk::RandomForestFileIO * m_DecisionForestIO;
- mitk::DummyLsetFileReader * m_DummyLsetReader;
- };
-}
-
-US_EXPORT_MODULE_ACTIVATOR(mitk::ModuleActivator)
diff --git a/Modules/Classification/CLVigraRandomForest/test/CMakeLists.txt b/Modules/Classification/CLVigraRandomForest/test/CMakeLists.txt
deleted file mode 100644
index 5a6a2c1bf5..0000000000
--- a/Modules/Classification/CLVigraRandomForest/test/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-MITK_CREATE_MODULE_TESTS()
-
-if(TARGET ${TESTDRIVER})
- mitk_use_modules(TARGET ${TESTDRIVER} PACKAGES ITK|IOCSV)
-endif()
diff --git a/Modules/Classification/CLVigraRandomForest/test/files.cmake b/Modules/Classification/CLVigraRandomForest/test/files.cmake
deleted file mode 100644
index 3f04b16d08..0000000000
--- a/Modules/Classification/CLVigraRandomForest/test/files.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-set(MODULE_TESTS
- mitkVigraRandomForestTest.cpp
-)
diff --git a/Modules/Classification/CLVigraRandomForest/test/mitkVigraRandomForestTest.cpp b/Modules/Classification/CLVigraRandomForest/test/mitkVigraRandomForestTest.cpp
deleted file mode 100644
index b0e3a37058..0000000000
--- a/Modules/Classification/CLVigraRandomForest/test/mitkVigraRandomForestTest.cpp
+++ /dev/null
@@ -1,323 +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 <mitkTestingMacros.h>
-#include <mitkTestFixture.h>
-#include "mitkIOUtil.h"
-#include "itkArray2D.h"
-
-#include <itkCSVArray2DFileReader.h>
-#include <itkCSVArray2DDataObject.h>
-#include <mitkVigraRandomForestClassifier.h>
-#include <itkLabelSampler.h>
-#include <itkAddImageFilter.h>
-#include <mitkImageCast.h>
-#include <mitkStandaloneDataStorage.h>
-
-class mitkVigraRandomForestTestSuite : public mitk::TestFixture
-{
- CPPUNIT_TEST_SUITE(mitkVigraRandomForestTestSuite );
- // MITK_TEST(Load_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
- // MITK_TEST(Save_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
-
- // MITK_TEST(LoadWithMitkOptions_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
- // MITK_TEST(SaveWithMitkOptions_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
-
- MITK_TEST(TrainThreadedDecisionForest_MatlabDataSet_shouldReturnTrue);
- MITK_TEST(PredictWeightedDecisionForest_SetWeightsToZero_shouldReturnTrue);
- MITK_TEST(TrainThreadedDecisionForest_BreastCancerDataSet_shouldReturnTrue);
- CPPUNIT_TEST_SUITE_END();
-
-private:
-
- typedef Eigen::Matrix<double ,Eigen::Dynamic,Eigen::Dynamic> MatrixDoubleType;
- typedef Eigen::Matrix<int, Eigen::Dynamic,Eigen::Dynamic> MatrixIntType;
-
- std::pair<MatrixDoubleType, MatrixDoubleType> FeatureData_Cancer;
- std::pair<MatrixIntType, MatrixIntType> LabelData_Cancer;
-
- std::pair<MatrixDoubleType, MatrixDoubleType> FeatureData_Matlab;
- std::pair<MatrixIntType, MatrixIntType> LabelData_Matlab;
-
- mitk::VigraRandomForestClassifier::Pointer classifier;
-
-public:
-
- // ------------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------------
-
-
- void setUp() override
- {
- FeatureData_Cancer = convertCSVToMatrix<double>(GetTestDataFilePath("Classification/FeaturematrixBreastcancer.csv"),';',0.5,true);
- LabelData_Cancer = convertCSVToMatrix<int>(GetTestDataFilePath("Classification/LabelmatrixBreastcancer.csv"),';',0.5,false);
- FeatureData_Matlab = convertCSVToMatrix<double>(GetTestDataFilePath("Classification/FeaturematrixMatlab.csv"),';',0.5,true);
- LabelData_Matlab = convertCSVToMatrix<int>(GetTestDataFilePath("Classification/LabelmatrixMatlab.csv"),';',0.5,false);
- classifier = mitk::VigraRandomForestClassifier::New();
- }
-
- void tearDown() override
- {
- classifier = nullptr;
- }
-
- // ------------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------------
- /*
- Train the classifier with an exampledataset of mattlab.
- Note: The included data are gauan normaldistributed.
- */
- void TrainThreadedDecisionForest_MatlabDataSet_shouldReturnTrue()
- {
-
- auto & Features_Training = FeatureData_Matlab.first;
- auto & Labels_Training = LabelData_Matlab.first;
-
- auto & Features_Testing = FeatureData_Matlab.second;
- auto & Labels_Testing = LabelData_Matlab.second;
-
- /* Train the classifier, by giving trainingdataset for the labels and features.
- The result in an colunmvector of the labels.*/
- classifier->Train(Features_Training,Labels_Training);
- Eigen::MatrixXi classes = classifier->Predict(Features_Testing);
-
- /* Testing the matching between the calculated colunmvector and the result of the RandomForest */
- unsigned int testmatrix_rows = classes.rows();
-
- unsigned int correctly_classified_rows = 0;
- for(unsigned int i= 0; i < testmatrix_rows; i++){
- if(classes(i,0) == Labels_Testing(i,0)){
- correctly_classified_rows++;
- }
- }
-
- MITK_TEST_CONDITION(correctly_classified_rows == testmatrix_rows, "Matlab Data correctly classified");
- }
-
- // ------------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------------
- /*
- Train the classifier with the dataset of breastcancer patients from the
- LibSVM Libary
- */
- void TrainThreadedDecisionForest_BreastCancerDataSet_shouldReturnTrue()
- {
-
- auto & Features_Training = FeatureData_Cancer.first;
- auto & Features_Testing = FeatureData_Cancer.second;
- auto & Labels_Training = LabelData_Cancer.first;
- auto & Labels_Testing = LabelData_Cancer.second;
-
-
- /* Train the classifier, by giving trainingdataset for the labels and features.
- The result in an colunmvector of the labels.*/
- classifier->Train(Features_Training,Labels_Training);
- Eigen::MatrixXi classes = classifier->Predict(Features_Testing);
-
- /* Testing the matching between the calculated colunmvector and the result of the RandomForest */
- unsigned int maxrows = classes.rows();
-
- int count = 0;
-
- for(unsigned int i= 0; i < maxrows; i++){
- if(classes(i,0) == Labels_Testing(i,0)){
- count++;
- }
- }
- MITK_TEST_CONDITION(isIntervall<int>(Labels_Testing,classes,98,99),"Testvalue of cancer data set is in range.");
- }
-
- // ------------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------------
-
- void PredictWeightedDecisionForest_SetWeightsToZero_shouldReturnTrue()
- {
-
- auto & Features_Training = FeatureData_Matlab.first;
- auto & Features_Testing = FeatureData_Matlab.second;
- auto & Labels_Training = LabelData_Matlab.first;
-// auto & Labels_Testing = LabelData_Matlab.second;
-
- classifier->Train(Features_Training,Labels_Training);
-
- // get weights type resize it and set all weights to zero
- auto weights = classifier->GetTreeWeights();
- weights.resize(classifier->GetRandomForest().tree_count(),1);
- weights.fill(0);
-
- classifier->SetTreeWeights(weights);
-
- // if all wieghts zero the missclassification rate mus be high
- Eigen::MatrixXi classes = classifier->PredictWeighted(Features_Testing);
-
- /* Testing the matching between the calculated colunmvector and the result of the RandomForest */
- unsigned int maxrows = classes.rows();
- unsigned int count = 0;
-
- // check if all predictions are of class 1
- for(unsigned int i= 0; i < maxrows; i++)
- if(classes(i,0) == 1)
- count++;
-
- MITK_TEST_CONDITION( (count == maxrows) ,"Weighted prediction - weights applied (all weights = 0).");
- }
-
-
- // ------------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------------
- /*Reading an file, which includes the trainingdataset and the testdataset, and convert the
- content of the file into an 2dim matrixpair.
- There are an delimiter, which separates the matrix into an trainingmatrix and testmatrix */
- template<typename T>
- std::pair<Eigen::Matrix<T ,Eigen::Dynamic,Eigen::Dynamic>,Eigen::Matrix<T ,Eigen::Dynamic,Eigen::Dynamic> >convertCSVToMatrix(const std::string &path, char delimiter,double range, bool isXMatrix)
- {
- typename itk::CSVArray2DFileReader<T>::Pointer fr = itk::CSVArray2DFileReader<T>::New();
- fr->SetFileName(path);
- fr->SetFieldDelimiterCharacter(delimiter);
- fr->HasColumnHeadersOff();
- fr->HasRowHeadersOff();
- fr->Parse();
- try{
- fr->Update();
- }catch ( const itk::ExceptionObject& ex ){
- cout << "Exception caught!" << std::endl;
- cout << ex.GetDescription() << std::endl;
- }
-
- typename itk::CSVArray2DDataObject<T>::Pointer p = fr->GetOutput();
- unsigned int maxrowrange = p->GetMatrix().rows();
- unsigned int c = p->GetMatrix().cols();
- unsigned int percentRange = (unsigned int)(maxrowrange*range);
-
- if(isXMatrix == true){
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> trainMatrixX(percentRange,c);
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> testMatrixXPredict(maxrowrange-percentRange,c);
-
- for(unsigned int row = 0; row < percentRange; row++){
- for(unsigned int col = 0; col < c; col++){
- trainMatrixX(row,col) = p->GetData(row,col);
- }
- }
-
- for(unsigned int row = percentRange; row < maxrowrange; row++){
- for(unsigned int col = 0; col < c; col++){
- testMatrixXPredict(row-percentRange,col) = p->GetData(row,col);
- }
- }
-
- return std::make_pair(trainMatrixX,testMatrixXPredict);
- }
- else{
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> trainLabelMatrixY(percentRange,c);
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> testMatrixYPredict(maxrowrange-percentRange,c);
-
- for(unsigned int row = 0; row < percentRange; row++){
- for(unsigned int col = 0; col < c; col++){
- trainLabelMatrixY(row,col) = p->GetData(row,col);
- }
- }
-
- for(unsigned int row = percentRange; row < maxrowrange; row++){
- for(unsigned int col = 0; col < c; col++){
- testMatrixYPredict(row-percentRange,col) = p->GetData(row,col);
- }
- }
- return std::make_pair(trainLabelMatrixY,testMatrixYPredict);
- }
-
- }
-
- /*
- Reading an csv-data and transfer the included datas into an matrix.
- */
- template<typename T>
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> readCsvData(const std::string &path, char delimiter)
- {
- typename itk::CSVArray2DFileReader<T>::Pointer fr = itk::CSVArray2DFileReader<T>::New();
- fr->SetFileName(path);
- fr->SetFieldDelimiterCharacter(delimiter);
- fr->HasColumnHeadersOff();
- fr->HasRowHeadersOff();
- fr->Parse();
- try{
- fr->Update();
- }catch ( const itk::ExceptionObject& ex ){
- cout << "Exception caught!" << std::endl;
- cout << ex.GetDescription() << std::endl;
- }
-
- typename itk::CSVArray2DDataObject<T>::Pointer p = fr->GetOutput();
- unsigned int maxrowrange = p->GetMatrix().rows();
- unsigned int maxcols = p->GetMatrix().cols();
- Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> matrix(maxrowrange,maxcols);
-
- for(unsigned int rows = 0; rows < maxrowrange; rows++){
- for(unsigned int cols = 0; cols < maxcols; cols++ ){
- matrix(rows,cols) = p->GetData(rows,cols);
- }
- }
-
- return matrix;
- }
-
- /*
- Write the content of the array into an own csv-data in the following sequence:
- root.csv: 1 2 3 0 0 4
- writen.csv: 1 1:2 2:3 3:0 4:0 5:4
- */
- template<typename T>
- void writeMatrixToCsv(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> paramMatrix,const std::string &path)
- {
- std::ofstream outputstream (path,std::ofstream::out); // 682
-
- if(outputstream.is_open()){
- for(int i = 0; i < paramMatrix.rows(); i++){
- outputstream << paramMatrix(i,0);
- for(int j = 1; j < 11; j++){
- outputstream << " " << j << ":" << paramMatrix(i,j);
- }
- outputstream << endl;
- }
- outputstream.close();
- }
- else{
- cout << "Unable to write into CSV" << endl;
- }
- }
-
- // Method for intervalltesting
- template<typename T>
- bool isIntervall(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> expected, Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> actual, double lowrange, double toprange)
- {
- bool isInIntervall = false;
- int count = 0;
- unsigned int rowRange = expected.rows();
- unsigned int colRange = expected.cols();
- for(unsigned int i = 0; i < rowRange; i++){
- for(unsigned int j = 0; j < colRange; j++){
- if(expected(i,j) == actual(i,j)){
- count++;
- }
- }
-
- double valueOfMatch = 100*count/(double)(rowRange);
- if((lowrange <= valueOfMatch) && (toprange >= valueOfMatch)){
- isInIntervall = true;
- }
- }
- return isInIntervall;
- }
-
-
-};
-
-MITK_TEST_SUITE_REGISTRATION(mitkVigraRandomForest)
diff --git a/Modules/Classification/CMakeLists.txt b/Modules/Classification/CMakeLists.txt
index 0de91abd41..e3bf00234e 100644
--- a/Modules/Classification/CMakeLists.txt
+++ b/Modules/Classification/CMakeLists.txt
@@ -1,8 +1,4 @@
add_subdirectory(CLCore)
add_subdirectory(CLUtilities)
add_subdirectory(CLMRUtilities)
-add_subdirectory(CLLibSVM)
-add_subdirectory(CLVigraRandomForest)
-add_subdirectory(DataCollection)
-add_subdirectory(CLImportanceWeighting)
add_subdirectory(CLMiniApps)
diff --git a/Modules/Classification/DataCollection/CMakeLists.txt b/Modules/Classification/DataCollection/CMakeLists.txt
deleted file mode 100644
index 4af11480be..0000000000
--- a/Modules/Classification/DataCollection/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-MITK_CREATE_MODULE(DataCollection #<-- module name
- INCLUDE_DIRS DataHolder ReaderWriter Iterators Utilities#<-- sub-folders of module
- INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL}
- DEPENDS MitkCore # MitkLegacyIO #<-- modules on which your module depends on
- PACKAGE_DEPENDS Qt5|Core Eigen
-)
-
-if(BUILD_TESTING)
- ADD_SUBDIRECTORY(Testing)
-endif()
diff --git a/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.cpp b/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.cpp
deleted file mode 100644
index 0402e93a55..0000000000
--- a/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.cpp
+++ /dev/null
@@ -1,378 +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 <mitkDataCollection.h>
-#include <mitkImageCast.h>
-
-// ITK
-#include <itkImage.h>
-#include <itkComposeImageFilter.h>
-
-mitk::DataCollection::DataCollection()
-{
-}
-
-
-mitk::DataCollection::~DataCollection()
-{
-}
-
-void
-mitk::DataCollection::Init(std::string name)
-{
- m_Name = name;
- m_Parent = nullptr;
-}
-
-size_t mitk::DataCollection::AddData(DataObject::Pointer data, std::string name, std::string filePath)
-{
- mitk::DataCollection* dc = dynamic_cast<mitk::DataCollection*>(data.GetPointer());
- if (dc) dc->SetParent(this);
-
- m_DataVector.push_back(data.GetPointer());
- m_NameVector.push_back(name);
- m_FilePathVector.push_back(filePath);
- size_t lastIndex = m_DataVector.size()-1;
- m_DataNames[name] = lastIndex;
- return lastIndex;
-}
-
-void
-mitk::DataCollection::SetName(std::string name)
-{
- m_Name = name;
-}
-
-std::string
-mitk::DataCollection::GetName() const
-{
- return m_Name;
-}
-
-std::string mitk::DataCollection::GetDataFilePath(size_t index) const
-{
- if (index >= m_FilePathVector.size())
- mitkThrow() << "No element with the given index";
- return m_FilePathVector[index];
-}
-
-
-size_t
-mitk::DataCollection::NameToIndex(std::string name)
-{
- size_t index;
- try
- {
- index = m_DataNames.at(name); // only brackets [] cause map to return std element, which in this case is 0
- }
- catch (...)
- {
- mitkThrow() << "No element with the given name: " << name;
- }
- return index;
-}
-
-std::string
-mitk::DataCollection::IndexToName(size_t index) const
-{
- if (index >= m_NameVector.size())
- {
- MITK_ERROR << "DataCollection Index does not exist";
- mitkThrow() << "No element with the given index";
- }
- return m_NameVector[index];
-}
-
-bool
-mitk::DataCollection::HasElement(std::string name)
-{
- bool isInside = (m_DataNames.find(name) != m_DataNames.end());
- return isInside;
-}
-
-bool
-mitk::DataCollection::HasElement(size_t index)
-{
- if (index >= m_NameVector.size())
- return false;
- return true;
-}
-
-size_t
-mitk::DataCollection::Size() const
-{
- return m_DataVector.size();
-}
-
-void
-mitk::DataCollection::SetData(itk::DataObject::Pointer data, size_t index)
-{
- if (!HasElement(index))
- mitkThrow() << "Unkown index. No Element with the given index";
-
- mitk::DataCollection::Pointer dc = dynamic_cast<mitk::DataCollection*>(data.GetPointer());
- if (dc)
- dc->SetParent(this);
-
- m_DataVector[index] = data;
-}
-
-void
-mitk::DataCollection::SetData(itk::DataObject::Pointer data, std::string name)
-{
- SetData(data, NameToIndex(name));
-}
-
-itk::DataObject::Pointer
-mitk::DataCollection::GetData(size_t index)
-{
- if (!HasElement(index))
- mitkThrow() << "Unkown index. No Element with the given index";
-
- return m_DataVector[index];
-}
-
-itk::DataObject::Pointer
-mitk::DataCollection::GetData(std::string name)
-{
- return GetData(NameToIndex(name));
-}
-
-template <typename TPixel>
-mitk::Image::Pointer
-ConvertItkObjectToMitkImage(itk::DataObject * itkData, mitk::Image::Pointer mitkImage)
-{
- if (mitkImage.IsNull())
- {
- typename itk::Image<TPixel, 3>::Pointer itkImage = dynamic_cast<itk::Image<TPixel, 3> *>(itkData);
- if (itkImage.IsNotNull())
- {
- mitk::CastToMitkImage(itkImage,mitkImage);
- }
- }
- if (mitkImage.IsNull())
- {
- typename itk::Image<TPixel, 2>::Pointer itkImage = dynamic_cast<itk::Image<TPixel, 2>*>(itkData);
- if (itkImage.IsNotNull())
- {
- mitk::CastToMitkImage(itkImage,mitkImage);
- }
- }
- return mitkImage;
-}
-
-
-mitk::Image::Pointer
-mitk::DataCollection::GetMitkImage(size_t index)
-{
- itk::DataObject* itkData = GetData(index).GetPointer();
- mitk::Image::Pointer mitkImage =
- dynamic_cast<mitk::Image*>(itkData);
-
- mitkImage = ConvertItkObjectToMitkImage<double>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<float>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<unsigned char>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<signed char>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<unsigned short>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<signed short>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<unsigned int>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<signed int>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<unsigned long>(itkData, mitkImage);
- mitkImage = ConvertItkObjectToMitkImage<signed long>(itkData, mitkImage);
-
- return mitkImage;
-}
-
-mitk::Image::Pointer
-mitk::DataCollection::GetMitkImage(std::string name)
-{
- return GetMitkImage(NameToIndex(name));
-}
-
-template <class ImageType>
-ImageType mitk::DataCollection::GetItkImage(size_t index, ImageType *itkImage)
-{
- Image* image = dynamic_cast<Image*> (GetData(index).GetPointer());
- if (image != nullptr)
- {
- CastToItkImage(image, itkImage );
- }
- else if (nullptr != dynamic_cast<ImageType*>(GetData(index)))
- itkImage = dynamic_cast<ImageType*>(GetData(index));
-}
-
-template <class ImageType>
-ImageType mitk::DataCollection::GetItkImage(std::string name, ImageType* itkImage)
-{
- Image* image = dynamic_cast<Image*> (GetData(NameToIndex(name)).GetPointer());
- if (image != nullptr)
- {
- CastToItkImage(image, itkImage );
- }
- else if (nullptr != dynamic_cast<ImageType*> (GetData(NameToIndex(name))))
- itkImage = dynamic_cast<ImageType*> (GetData(NameToIndex(name)));
-}
-
-itk::DataObject::Pointer&
-mitk::DataCollection::operator[](size_t index)
-{
- return m_DataVector[index];
-}
-
-itk::DataObject::Pointer&
-mitk::DataCollection::operator[](std::string &name)
-{
- return operator[](NameToIndex(name));
-}
-
-void mitk::DataCollection::SetXMLFile(std::string absoluteXMlFile)
-{
- m_XMLFile = absoluteXMlFile;
-}
-
-std::string mitk::DataCollection::GetXMLFile()
-{
- return m_XMLFile;
-}
-
-void mitk::DataCollection::SetParent(mitk::DataCollection *parent)
-{
- m_Parent = parent;
-}
-
-mitk::DataCollection*
-mitk::DataCollection::GetParent()
-{
- return m_Parent;
-}
-
-void mitk::DataCollection::SetNameForIndex(size_t index, std::string &name)
-{
- std::map<std::string, size_t>::iterator it = m_DataNames.find(m_NameVector[index]);
- m_DataNames.erase(it);
- m_DataNames[name] = index;
- m_NameVector[index] = name;
-
-}
-
-bool mitk::DataCollection::RemoveIndex(size_t index)
-{
- if (!HasElement(index))
- return false;
-
- m_DataVector.erase(m_DataVector.begin() + index);
- m_NameVector.erase(m_NameVector.begin() + index);
- m_FilePathVector.erase(m_FilePathVector.begin() + index);
-
- m_DataNames.clear();
- for (size_t i = 0; i < m_NameVector.size(); ++i)
- {
- m_DataNames[m_NameVector[i]] = i;
- }
-
- return true;
-}
-
-bool mitk::DataCollection::RemoveElement(std::string &name)
-{
- if (!HasElement(name))
- return false;
-
- return RemoveIndex(NameToIndex(name));
-}
-
-void mitk::DataCollection::Clear()
-{
- for (std::vector<itk::DataObject::Pointer>::iterator it = m_DataVector.begin(); it != m_DataVector.end(); ++it)
- {
- DataCollection* col = dynamic_cast<DataCollection*>((*it).GetPointer()) ;
- if (col != nullptr)
- col->Clear();
- else
- *it = nullptr;
-
- }
- m_Parent = nullptr;
-}
-
-/* Superclass methods, that need to be implemented */
-void mitk::DataCollection::UpdateOutputInformation()
-{
-
-}
-
-void mitk::DataCollection::SetRequestedRegionToLargestPossibleRegion()
-{
-}
-
-bool mitk::DataCollection::RequestedRegionIsOutsideOfTheBufferedRegion()
-{
- return false;
-}
-
-bool mitk::DataCollection::VerifyRequestedRegion()
-{
- return false;
-}
-
-void mitk::DataCollection::SetRequestedRegion(const itk::DataObject *)
-{
-
-}
-
-mitk::DataNode::Pointer mitk::DataCollection::GetDataNode(size_t index)
-{
- mitk::BaseData::Pointer data = dynamic_cast<mitk::BaseData*>(GetMitkImage(index).GetPointer());
-
- if (data.IsNull())
- {
- data = dynamic_cast<mitk::BaseData*>(GetData(index).GetPointer());
- }
- mitk::DataNode::Pointer node = mitk::DataNode::New();
- node->SetName(IndexToName(index));
- node->SetData(data);
-
- return node;
-}
-
-mitk::DataNode::Pointer mitk::DataCollection::GetDataNode(std::string name)
-{
- return GetDataNode(NameToIndex(name));
-}
-
-mitk::Image::Pointer mitk::DataCollection::GetProbabilityMap(std::vector<std::string> probabilityNamesVector)
-{
- typedef itk::Image<double, 3> ImageType;
- typedef itk::VectorImage<double, 3> VectorImageType;
- typedef itk::ComposeImageFilter<ImageType, VectorImageType> ComposeFilterType;
-
- ComposeFilterType::Pointer composer = ComposeFilterType::New();
- int i = 0;
- for (std::vector<std::string>::iterator it = probabilityNamesVector.begin(); it != probabilityNamesVector.end(); ++it)
- {
- ImageType* img = dynamic_cast<ImageType*>(this->GetData((*it)).GetPointer());
- if (img != nullptr)
- {
- composer->SetInput(i, img);
- ++i;
- }
- }
- composer->Update();
- VectorImageType::Pointer vecImage = composer->GetOutput();
-
- mitk::Image::Pointer probImage = mitk::Image::New();
- probImage->InitializeByItk(vecImage.GetPointer(), vecImage->GetNumberOfComponentsPerPixel());
- probImage->SetVolume(vecImage->GetBufferPointer());
-
- return probImage;
-}
diff --git a/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.h b/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.h
deleted file mode 100644
index def30e3847..0000000000
--- a/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.h
+++ /dev/null
@@ -1,287 +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.
-
-============================================================================*/
-
-#ifndef mitkDataCollection_h
-#define mitkDataCollection_h
-
-#ifdef _MSC_VER
-# pragma warning (disable : 4996)
-#endif
-
-//#include <itkLightObject.h>
-//#include <itkDataObject.h>
-//#include "itkObjectFactory.h"
-//#include "mitkCommon.h"
-#include <mitkImage.h>
-#include <mitkDataNode.h>
-
-#include<mitkBaseData.h>
-
-#include <MitkDataCollectionExports.h>
-
-/**
-* \brief DataCollection - Class to facilitate loading/accessing structured data
-*
-* Data is grouped into a collection that may contain further (sub) collections or images.
-*
-* Exemplary structure
-*
-* Collection (e.g. Patient)
-* |
-* |-- Sub-Collection1 (e.g. follow-up 1)
-* | |
-* | |-- DataItem (e.g. T1)
-* | |-- DataItem (e.g. T2)
-* |
-* |-- Sub-Collection2 (e.g. follow-up 2)
-* | |
-* | |-- DataItem (e.g. T1)
-* | |-- DataItem (e.g. T2)
-*
-*/
-
-namespace mitk
-{
- class MITKDATACOLLECTION_EXPORT DataCollection : public BaseData
- {
- public:
-
- mitkClassMacro(DataCollection, BaseData);
-
- itkFactorylessNewMacro(Self);
-
- itkCloneMacro(Self);
-
- // Needed methods from Basedata
- void UpdateOutputInformation() override;
- void SetRequestedRegionToLargestPossibleRegion() override;
- bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
- bool VerifyRequestedRegion() override;
- void SetRequestedRegion(const itk::DataObject *) override;
-
- void Init(std::string name);
-
- /**
- * @brief AddData Add a data item
- * @param data Images/Fibers/DataCollections
- * @param name name that allows identifying this data (e.g. a category T2, Segmentation , etc ...)
- * @param filePath
- * @return
- */
- size_t AddData(DataObject::Pointer data, std::string name, std::string filePath = "");
-
- /**
- * @brief SetName - Sets name of DataCollection
- * @param name
- */
- void SetName(std::string name);
-
- std::string GetName() const;
-
- std::string GetDataFilePath(size_t index) const;
-
- /**
- * @brief NameToIndex - Get index from data item name
- * @param name
- * @return
- */
-
- size_t NameToIndex(std::string name);
-
- /**
- * @brief IndexToName - Get name from index
- * @param index
- * @return
- */
- std::string IndexToName(size_t index) const;
-
- /**
- * @brief HasElement - check if element with this name exists in collection
- * @param name
- * @return
- */
- bool HasElement(std::string name);
-
- /**
- * @brief HasElement - check if element with this index exists in collection
- * @param index
- * @return
- */
-
- bool HasElement(size_t index);
-
- /**
- * @brief Size - number of data items in collection
- * @return
- */
- size_t Size() const;
-
- /**
- * @brief SetData - set/update data item by index
- * @param data
- * @param index
- */
-
- void SetData(itk::DataObject::Pointer data, size_t index);
-
- /**
- * @brief SetData - set/update data item by name
- * @param data
- * @param name
- */
-
- void SetData(itk::DataObject::Pointer data, std::string name);
-
- /**
- * @brief GetData Get original data by index
- *
- * To ensure a mitk::Image is returned use GetMitkImage
- *
- * @param index
- * @return
- */
- itk::DataObject::Pointer GetData(size_t index);
-
- /**
- * @brief GetData Get original data by name
- *
- * To ensure a mitk::Image is returned use GetMitkImage
- *
- * @param name
- * @return
- */
- itk::DataObject::Pointer GetData(std::string name);
-
- /**
- * @brief GetMitkImage - casts data to mitk::Image and returns it
- *
- * \note returns nullptr is object is no mitk::Image or itk::Image
- *
- * @param index
- * @return
- */
- mitk::Image::Pointer GetMitkImage(size_t index);
-
- /**
- * @brief GetMitkImage - casts data to mitk::Image and returns it
- *
- * \note returns nullptr is object is no mitk::Image or itk::Image
- *
- * @param name
- * @return
- */
- mitk::Image::Pointer GetMitkImage(std::string name);
-
- /**
- * @brief GetMitkImage - casts data to privided itk::Image pointer
- */
- template <class ImageType>
- ImageType GetItkImage(size_t index, ImageType* itkImage);
-
- /**
- * @brief GetMitkImage - casts data to privided itk::Image pointer
- */
- template <class ImageType>
- ImageType GetItkImage(std::string name, ImageType* itkImage);
-
- itk::DataObject::Pointer& operator[](size_t index);
-
- itk::DataObject::Pointer& operator[](std::string &name);
-
- /**
- * @brief SetNameForIndex - sets name for given data item by index
- * @param index
- * @param name
- */
- void SetNameForIndex(size_t index, std::string &name);
-
- /**
- * @brief SetXMLFile - sets xml file to which data collection is saved
- */
- void SetXMLFile(std::string absoluteXMlFile);
-
- /**
- * @brief SetXMLFile - gets xml file to which data collection is supposed to be saved
- */
- std::string GetXMLFile();
-
- /**
- * @brief SetParent - sets the parent collection
- * @param parent
- */
- void SetParent(mitk::DataCollection* parent);
-
- /**
- * @brief GetParent - returns the parent collection if available else null is returned
- * @return
- */
- mitk::DataCollection* GetParent();
-
- /**
- * @brief RemoveIndex - removes element at index
- * @param index
- * @return
- */
- bool RemoveIndex(size_t index);
-
- /**
- * @brief RemoveElement - removes element with name
- * @param name
- * @return
- */
- bool RemoveElement(std::string& name);
-
- /**
- * @brief Clear - clears the data collection
- */
- void Clear() override;
-
- /**
- * @brief GetDataNode - returns data node containing data at index
- * @param index
- * @return
- */
- mitk::DataNode::Pointer GetDataNode(size_t index);
-
- /**
- * @brief GetDataNode - returns data node containing data with name
- * @param name
- * @return
- */
- mitk::DataNode::Pointer GetDataNode(std::string name);
-
- /**
- * @brief GetProbabilityMap - returns vectorimage generated out of images with names in the probabilityNamesVector
- * @param probabilityNamesVector
- * @return
- */
- mitk::Image::Pointer GetProbabilityMap(std::vector<std::string> probabilityNamesVector);
-
- protected:
-
- DataCollection();
- ~DataCollection() override;
-
- private:
- // DATA
- std::string m_Name;
- std::vector<itk::DataObject::Pointer> m_DataVector;
- std::vector<std::string> m_NameVector;
- std::vector<std::string> m_FilePathVector;
- std::map<std::string, size_t> m_DataNames;
-
- mitk::DataCollection * m_Parent;
-
- std::string m_XMLFile; // is only filled for the hightest layer when loading a data collection
- };
-} // end namespace
-#endif
diff --git a/Modules/Classification/DataCollection/DataHolder/mitkDataCollectionUtility.cpp b/Modules/Classification/DataCollection/DataHolder/mitkDataCollectionUtility.cpp
deleted file mode 100644
index d25299af36..0000000000
--- a/Modules/Classification/DataCollection/DataHolder/mitkDataCollectionUtility.cpp
+++ /dev/null
@@ -1,12 +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.
-
-============================================================================*/
-
diff --git a/Modules/Classification/DataCollection/DataHolder/mitkDataCollectionUtility.h b/Modules/Classification/DataCollection/DataHolder/mitkDataCollectionUtility.h
deleted file mode 100644
index 27df3b2ff2..0000000000
--- a/Modules/Classification/DataCollection/DataHolder/mitkDataCollectionUtility.h
+++ /dev/null
@@ -1,75 +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.
-
-============================================================================*/
-
-
-#ifndef mitkDataCollectionUtility_h
-#define mitkDataCollectionUtility_h
-
-
-#include <mitkDataCollection.h>
-
-/**
- \brief Follow Up Storage - Class to facilitate loading/accessing structured follow-up data
-
- Data is into a collection that may contain further (sub) collections or images.
-*/
-
-namespace mitk
-{
- class DataCollectionUtility
- {
- public:
- template <class OriginImageType, class TargetImageType>
- static void EnsureImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target);
-
- static void Compile()
- {
- mitk::DataCollection::Pointer col = mitk::DataCollection::New();
- std::string blub = "haha";
- typedef itk::Image<double, 3> ImType;
- EnsureImageInCollection<ImType, ImType>(col, blub, blub);
- };
-} // end namespace
-
-template <class OriginImageType, class TargetImageType>
-void
-mitk::DataCollectionUtility::EnsureDataImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target)
-{
- typedef typename TargetImageType FeatureImage;
- typedef typename OriginImageType LabelImage;
-
- if (collection->HasElement(origin))
- {
- LabelImage::Pointer originImage = dynamic_cast<LabelImage*>(collection->GetData(origin).GetPointer());
- if (!collection->HasElement(target) && originImage.IsNotNull())
- {
- FeatureImage::Pointer image = FeatureImage::New();
- image->SetRegions(originImage->GetLargestPossibleRegion());
- image->SetSpacing(originImage->GetSpacing());
- image->SetOrigin(originImage->GetOrigin());
- image->SetDirection(originImage->GetDirection());
- image->Allocate();
-
- collection->AddData(dynamic_cast<itk::DataObject*>(image.GetPointer()),target,"");
- }
- }
- for (std::size_t i = 0; i < collection->Size();++i)
- {
- mitk::DataCollection* newCol = dynamic_cast<mitk::DataCollection*>(collection->GetData(i).GetPointer());
- if (newCol != 0)
- {
- EnsureDataImageInCollection(newCol, origin, target);
- }
- }
-};
-
-#endif
diff --git a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionImageIterator.cxx b/Modules/Classification/DataCollection/Iterators/mitkDataCollectionImageIterator.cxx
deleted file mode 100644
index 8cc871e573..0000000000
--- a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionImageIterator.cxx
+++ /dev/null
@@ -1,222 +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.
-
-============================================================================*/
-
-template <typename TDataType, int TImageDimension>
-mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- DataCollectionImageIterator(DataCollection::Pointer collection, std::string imageName) :
- m_Collection(collection), m_ImageName(imageName), m_IsAtEnd(false),
- m_IteratingImages(true), m_CurrentIndex(0),
- m_CurrentElement(0), m_CurrentCollectionIterator(nullptr)
-{
- ToBegin();
-}
-
-template <typename TDataType, int TImageDimension>
-void
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- ToBegin()
-{
- m_IsAtEnd = false;
- m_IteratingImages = false;
- m_CurrentIndex = 0;
- m_CurrentElement = 0;
- m_ImageIndex = 0;
-
- if (m_Collection->HasElement(m_ImageName))
- {
- {
- mitk::Image *image = dynamic_cast<mitk::Image*>(m_Collection->GetData(m_ImageName).GetPointer());
-
- //TODO: check whether image is valid... image != 0 if empty smart pointer was inserted into collection!!!!
- if (image != nullptr)
- {
- typename ImageType::Pointer itkImage = ImageType::New();
- mitk::CastToItkImage(image, itkImage);
- itk::DataObject::Pointer itkObject = dynamic_cast<itk::DataObject* >(itkImage.GetPointer());
- m_Collection->SetData(itkObject, m_ImageName);
- }
- }
- ImageType * image = dynamic_cast<ImageType*>(m_Collection->GetData(m_ImageName).GetPointer());
- if (image != nullptr)
- {
- m_IteratingImages = true;
- m_CurrentIterator = ImageIterator(image, image->GetLargestPossibleRegion());
- }
- }
- if (!m_IteratingImages)
- {
- if (m_CurrentCollectionIterator != nullptr)
- {
- delete m_CurrentCollectionIterator;
- m_CurrentCollectionIterator = nullptr;
- }
- m_CurrentElement = 0;
- m_CurrentCollectionIterator = GetNextDataCollectionIterator(m_CurrentElement);
- if (m_CurrentCollectionIterator == nullptr)
- {
- m_IsAtEnd = true;
- } else
- {
- m_CurrentIterator = m_CurrentCollectionIterator->GetImageIterator();
- }
- }
-}
-
-template <typename TDataType, int TImageDimension>
-bool
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- IsAtEnd()
-{
- return m_IsAtEnd;
-}
-
-template <typename TDataType, int TImageDimension>
-void
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- operator++()
-{
- ++m_CurrentIndex;
- ++m_CurrentIterator;
-
- if (m_CurrentIterator.IsAtEnd())
- {
- ++m_ImageIndex;
- NextObject();
- }
-}
-
-template <typename TDataType, int TImageDimension>
-void
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- operator++(int)
-{
- ++m_CurrentIndex;
- ++m_CurrentIterator;
-
- if (m_CurrentIterator.IsAtEnd())
- {
- ++m_ImageIndex;
- NextObject();
- }
-}
-
-template <typename TDataType, int TImageDimension>
-mitk::DataCollectionImageIterator<TDataType, TImageDimension>*
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- GetNextDataCollectionIterator(size_t start)
-{
- DataCollectionImageIterator<TDataType, TImageDimension>* iterator = nullptr;
- size_t index =start;
- while (index < m_Collection->Size() && iterator == nullptr)
- {
- DataCollection* collection;
- collection = dynamic_cast<DataCollection*>(m_Collection->GetData(index).GetPointer());
- if (collection != nullptr)
- {
- iterator = new DataCollectionImageIterator<TDataType, TImageDimension>(collection, m_ImageName);
- if (iterator->IsAtEnd())
- {
- delete iterator;
- iterator = nullptr;
- ++index;
- }
- }
- else
- {
- ++index;
- }
- }
- m_CurrentElement = index;
- return iterator;
-}
-
-template <typename TDataType, int TImageDimension>
-TDataType
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- GetVoxel()
-{
- return m_CurrentIterator.Get();
-}
-
-template <typename TDataType, int TImageDimension>
-void
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- SetVoxel(TDataType value)
-{
- m_CurrentIterator.Set(value);
-}
-
-template <typename TDataType, int TImageDimension>
-size_t
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- GetIndex()
-{
- return m_CurrentIndex;
-}
-
-template <typename TDataType, int TImageDimension>
-std::string
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::
- GetFilePrefix()
-{
- if (m_IteratingImages)
- {
- return m_ImageName;
- }
- else
- {
- return m_Collection->IndexToName(m_CurrentElement) + "/" + m_CurrentCollectionIterator->GetFilePrefix();
- }
-}
-
-template <typename TDataType, int TImageDimension>
-void mitk::DataCollectionImageIterator<TDataType, TImageDimension>::NextObject()
-{
- if (m_IteratingImages)
- {
- if (m_CurrentCollectionIterator != nullptr)
- {
- delete m_CurrentCollectionIterator;
- m_CurrentCollectionIterator = nullptr;
- }
- m_IteratingImages = false;
- m_CurrentElement = 0;
- m_CurrentCollectionIterator = GetNextDataCollectionIterator(m_CurrentElement);
- if (m_CurrentCollectionIterator == nullptr)
- {
- m_IsAtEnd = true;
- return;
- }
- }
- else
- {
- m_CurrentCollectionIterator->NextObject();
- if (m_CurrentCollectionIterator->IsAtEnd()) //Current collection is finished iterated
- {
- delete m_CurrentCollectionIterator;
- m_CurrentCollectionIterator = GetNextDataCollectionIterator(m_CurrentElement+1);
- }
- if (m_CurrentCollectionIterator == nullptr) //If no collection is known
- {
- m_IsAtEnd = true;
- return;
- }
- }
- m_CurrentIterator = m_CurrentCollectionIterator->GetImageIterator();
-}
-
-template <typename TDataType, int TImageDimension>
-typename mitk::DataCollectionImageIterator<TDataType, TImageDimension>::ImageIterator
- mitk::DataCollectionImageIterator<TDataType, TImageDimension>::GetImageIterator()
-{
- return m_CurrentIterator;
-};
diff --git a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionImageIterator.h b/Modules/Classification/DataCollection/Iterators/mitkDataCollectionImageIterator.h
deleted file mode 100644
index afedd432f6..0000000000
--- a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionImageIterator.h
+++ /dev/null
@@ -1,80 +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.
-
-============================================================================*/
-
-
-#ifndef mitkDataCollectionImageIterator_h
-#define mitkDataCollectionImageIterator_h
-
-#include <mitkImageCast.h>
-#include <mitkDataCollection.h>
-#include <itkImageRegionIterator.h>
-
-/**
- \brief Follow Up Storage - Class to facilitate loading/accessing structured follow-up data
-
- Data is into a collection that may contain further (sub) collections or images.
-*/
-
-namespace mitk
-{
- template <typename TDataType, int ImageDimension>
- class DataCollectionImageIterator
- {
- public:
- typedef itk::Image<TDataType, ImageDimension> ImageType;
- typedef typename ImageType::Pointer ImagePointerType;
- typedef itk::ImageRegionIterator<ImageType> ImageIterator;
-
- DataCollectionImageIterator(DataCollection::Pointer collection, std::string imageName);
-
- void ToBegin();
-
- bool IsAtEnd();
-
- void operator++();
-
- // TODO refactor implementation
- void operator++(int);
-
- TDataType GetVoxel();
-
- void SetVoxel(TDataType value);
-
- size_t GetIndex();
- size_t GetImageIndex () { return m_ImageIndex;}
-
- std::string GetFilePrefix();
-
- void NextObject();
-
- ImageIterator GetImageIterator();
-
- private:
- DataCollectionImageIterator<TDataType, ImageDimension>* GetNextDataCollectionIterator(size_t start);
-
- // DATA
- DataCollection::Pointer m_Collection;
- std::string m_ImageName;
-
- bool m_IsAtEnd;
- bool m_IteratingImages;
- size_t m_CurrentIndex;
- size_t m_ImageIndex;
-
- size_t m_CurrentElement;
- DataCollectionImageIterator<TDataType, ImageDimension>* m_CurrentCollectionIterator;
- ImageIterator m_CurrentIterator;
- };
-} // end namespace
-
-#include <Iterators/mitkDataCollectionImageIterator.cxx>
-#endif
diff --git a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionSingleImageIterator.cxx b/Modules/Classification/DataCollection/Iterators/mitkDataCollectionSingleImageIterator.cxx
deleted file mode 100644
index eb482ebb67..0000000000
--- a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionSingleImageIterator.cxx
+++ /dev/null
@@ -1,217 +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.
-
-============================================================================*/
-
-#ifndef mitkDataCollectionSingleImageIterator_CXX
-#define mitkDataCollectionSingleImageIterator_CXX
-
-#include <Iterators/mitkDataCollectionSingleImageIterator.h>
-#include <mitkImageCast.h>
-
-template <typename TDataType, int TImageDimension>
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-DataCollectionSingleImageIterator(DataCollection *collection, std::string imageName) :
- m_Collection(collection),
- m_ImageName(imageName),
- m_IsAtEnd(false),
- m_IteratingImages(true),
- m_CurrentIndex(0),
- m_CurrentElement(0),
- m_CurrentSingleCollectionIterator(nullptr)
-{
- ToBegin();
-}
-
-template <typename TDataType, int TImageDimension>
-void
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-ToBegin()
-{
- m_IsAtEnd = false;
- m_Image = nullptr;
- m_IteratingImages = false;
- m_CurrentIndex = 0;
- m_CurrentElement = 0;
-
- if (m_Collection->HasElement(m_ImageName))
- {
- {
- mitk::Image *image = dynamic_cast<mitk::Image*>(m_Collection->GetData(m_ImageName).GetPointer());
- if (image != nullptr)
- {
- typename ImageType::Pointer itkImage = ImageType::New();
- mitk::CastToItkImage(image, itkImage);
- itk::DataObject::Pointer itkObject = dynamic_cast<itk::DataObject* >(itkImage.GetPointer());
- m_Collection->SetData(itkObject, m_ImageName);
- }
- }
- ImageType * image = dynamic_cast<ImageType*>(m_Collection->GetData(m_ImageName).GetPointer());
- if (image != nullptr)
- {
- m_Image = image;
- }
- }
- if (m_Image == nullptr)
- {
- m_CurrentElement = 0;
- m_CurrentSingleCollectionIterator = GetNextDataCollectionIterator(m_CurrentElement);
- if (m_Image == nullptr)
- {
- m_IsAtEnd = true;
- } else
- {
- m_Image = m_CurrentSingleCollectionIterator->GetImage();
- }
- }
-}
-
-template <typename TDataType, int TImageDimension>
-bool
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-IsAtEnd()
-{
- return m_IsAtEnd;
-}
-
-template <typename TDataType, int TImageDimension>
-void
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-operator++()
-{
- ++m_CurrentIndex;
- NextObject();
-}
-
-template <typename TDataType, int TImageDimension>
-void
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-operator++(int)
-{
- ++m_CurrentIndex;
- NextObject();
-}
-
-template <typename TDataType, int TImageDimension>
-size_t
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-GetIndex()
-{
- return m_CurrentIndex;
-}
-
-template <typename TDataType, int TImageDimension>
-std::string
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-GetFilePrefix()
-{
- if (m_IteratingImages)
- {
- return m_ImageName;
- }
- else
- {
- return m_Collection->IndexToName(m_CurrentElement) + "/" + m_CurrentSingleCollectionIterator->GetFilePrefix();
- }
-}
-
-template <typename TDataType, int TImageDimension>
-void mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-NextObject()
-{
- if (m_Collection->HasElement(m_ImageName))
- {
- if (m_CurrentSingleCollectionIterator != nullptr)
- {
- delete m_CurrentSingleCollectionIterator;
- m_CurrentSingleCollectionIterator = nullptr;
- }
- m_CurrentElement = 0;
- m_Image = nullptr;
- m_CurrentSingleCollectionIterator = GetNextDataCollectionIterator(m_CurrentElement);
- if (m_CurrentSingleCollectionIterator == nullptr)
- {
- m_IsAtEnd = true;
- return;
- }
- }
- else
- {
- m_CurrentSingleCollectionIterator->NextObject();
- if (m_CurrentSingleCollectionIterator->IsAtEnd()) //Current collection is finished iterated
- {
- delete m_CurrentSingleCollectionIterator;
- m_CurrentSingleCollectionIterator = GetNextDataCollectionIterator(m_CurrentElement+1);
- }
- if (m_CurrentSingleCollectionIterator == nullptr) //If no collection is known
- {
- m_IsAtEnd = true;
- return;
- }
- }
-}
-
-template <typename TDataType, int TImageDimension>
-typename mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::ImageType *
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-GetImage()
-{
- return m_Image;
-}
-
-template <typename TDataType, int TImageDimension>
-void
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-AddImage(ImageType *image, std::string name)
-{
- if (m_Collection->HasElement(m_ImageName))
- {
- itk::DataObject::Pointer dataObject = dynamic_cast<itk::DataObject*>(image);
- m_Collection->AddData(dataObject, name);
- } else
- {
- m_CurrentSingleCollectionIterator->AddImage(image, name);
- }
-}
-
-template <typename TDataType, int TImageDimension>
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>*
-mitk::DataCollectionSingleImageIterator<TDataType, TImageDimension>::
-GetNextDataCollectionIterator(size_t start)
-{
- DataCollectionSingleImageIterator<TDataType, TImageDimension>* iterator = nullptr;
- size_t index =start;
- while (index < m_Collection->Size() && iterator == nullptr)
- {
- DataCollection* collection;
- collection = dynamic_cast<DataCollection*>(m_Collection->GetData(index).GetPointer());
- if (collection != nullptr)
- {
- iterator = new DataCollectionSingleImageIterator<TDataType, TImageDimension>(collection, m_ImageName);
- if (iterator->IsAtEnd())
- {
- delete iterator;
- iterator = nullptr;
- ++index;
- }
- }
- else
- {
- ++index;
- }
- }
- m_CurrentElement = index;
- if (iterator != nullptr)
- m_Image = iterator->GetImage();
- return iterator;
-}
-
-// mitkDataCollectionSingleImageIterator_CXX
-#endif
diff --git a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionSingleImageIterator.h b/Modules/Classification/DataCollection/Iterators/mitkDataCollectionSingleImageIterator.h
deleted file mode 100644
index 1e869ecc81..0000000000
--- a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionSingleImageIterator.h
+++ /dev/null
@@ -1,75 +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.
-
-============================================================================*/
-
-
-#ifndef mitkDataCollectionSingleImageIterator_h
-#define mitkDataCollectionSingleImageIterator_h
-
-
-#include <mitkDataCollection.h>
-#include <itkImageRegionIterator.h>
-
-/**
- \brief Follow Up Storage - Class to facilitate loading/accessing structured follow-up data
-
- Data is into a collection that may contain further (sub) collections or images.
-*/
-
-namespace mitk
-{
- template <typename TDataType, int ImageDimension>
- class DataCollectionSingleImageIterator
- {
- public:
- typedef itk::Image<TDataType, ImageDimension> ImageType;
- typedef itk::ImageRegionIterator<ImageType> ImageIterator;
-
- DataCollectionSingleImageIterator(mitk::DataCollection * collection, std::string imageName);
-
- void ToBegin();
-
- bool IsAtEnd();
-
- void operator++();
-
- // TODO refactor implementation
- void operator++(int);
-
- size_t GetIndex();
-
- std::string GetFilePrefix();
-
- void NextObject();
-
- ImageType * GetImage();
-
- void AddImage(ImageType * image, std::string name);
-
- private:
- // Variables
- DataCollection * m_Collection;
- std::string m_ImageName;
- bool m_IsAtEnd;
- bool m_IteratingImages;
- size_t m_CurrentIndex;
- size_t m_CurrentElement;
- ImageType * m_Image;
- DataCollectionSingleImageIterator<TDataType, ImageDimension>* m_CurrentSingleCollectionIterator;
-
- // Methods
- DataCollectionSingleImageIterator<TDataType, ImageDimension>* GetNextDataCollectionIterator(size_t start);
-
- };
-} // end namespace
-
-#include <Iterators/mitkDataCollectionSingleImageIterator.cxx>
-#endif
diff --git a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionVectorImageIterator.cxx b/Modules/Classification/DataCollection/Iterators/mitkDataCollectionVectorImageIterator.cxx
deleted file mode 100644
index c17bda3c5f..0000000000
--- a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionVectorImageIterator.cxx
+++ /dev/null
@@ -1,105 +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 "mitkDataCollectionVectorImageIterator.h"
-
-#include "itkImageRegionConstIterator.h"
-
-#include "itkComposeImageFilter.h"
-
-template<typename TDataType, int ImageDimension>
-inline
-mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::DataCollectionVectorImageIterator(
- DataCollection::Pointer collection, std::vector<std::string> featureNames) :
- m_Collection(collection)
- {
- for(std::vector<std::string>::iterator featureNameIterator = featureNames.begin();
- featureNameIterator != featureNames.end();
- ++featureNameIterator)
- {
- SingleImageIterator featureIterator(collection, *featureNameIterator);
- m_FeatureIterators.push_back(featureIterator);
- }
- }
-
-template<typename TDataType, int ImageDimension>
-inline void
-mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::ToBegin()
-{
- for(typename DataCollectionSingleImageIterators::iterator it = m_FeatureIterators.begin();
- it != m_FeatureIterators.end();
- ++it)
- {
- it->ToBegin();
- }
-}
-
-template<typename TDataType, int ImageDimension>
-inline bool
-mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::IsAtEnd()
-{
- return m_FeatureIterators.at(0).IsAtEnd();
-}
-
-template<typename TDataType, int ImageDimension>
-inline mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>&
-mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::operator ++()
-{
- for(typename DataCollectionSingleImageIterators::iterator it = m_FeatureIterators.begin();
- it != m_FeatureIterators.end();
- ++it)
- {
- ++(*it);
- }
- return *this;
-}
-
-template<typename TDataType, int ImageDimension>
-inline mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>
-mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::operator ++(int)
-{
- mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension> result (*this);
- ++result;
- return result;
-}
-
-
-
-template<typename TDataType, int ImageDimension>
-inline typename mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::VectorImagePointerType
-mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::GetVectorImage()
-{
- typedef typename itk::Image<TDataType, ImageDimension> ImageType;
-
- typename itk::ComposeImageFilter<ImageType, VectorImageType>::Pointer composeImageFilter =
- itk::ComposeImageFilter<ImageType, VectorImageType>::New();
-
- // create image iterators from collection iterators
- for (unsigned i = 0; i < m_FeatureIterators.size(); i++)
- {
- composeImageFilter->SetInput(i, m_FeatureIterators.at(i).GetImage());
- }
-
- composeImageFilter->Update();
-
- composeImageFilter->GetOutput()->SetRequestedRegionToLargestPossibleRegion();
-
- return composeImageFilter->GetOutput();
-}
-
-template<typename TDataType, int ImageDimension>
-inline void
-mitk::DataCollectionVectorImageIterator<TDataType, ImageDimension>::AddImage(
- typename itk::Image<TDataType, ImageDimension>::Pointer image, std::string name)
- {
- m_FeatureIterators.at(m_FeatureIterators.size()-1).AddImage(image, name);
- }
diff --git a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionVectorImageIterator.h b/Modules/Classification/DataCollection/Iterators/mitkDataCollectionVectorImageIterator.h
deleted file mode 100644
index 412ce24c4a..0000000000
--- a/Modules/Classification/DataCollection/Iterators/mitkDataCollectionVectorImageIterator.h
+++ /dev/null
@@ -1,72 +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.
-
-============================================================================*/
-
-#ifndef mitkDataCollectionVectorImageIterator_h
-#define mitkDataCollectionVectorImageIterator_h
-#include <mitkDataCollection.h>
-#include <mitkDataCollectionSingleImageIterator.h>
-
-#include "itkImage.h"
-
-namespace mitk
-{
-
- /*
- * Iterate over a data collection and return a vector image for all selected
- * modalities.
- * TODO SW: this class needs a module test urgently.
- */
- template <typename TDataType, int ImageDimension>
- class DataCollectionVectorImageIterator
- {
-
- public:
- typedef itk::VectorImage<TDataType, ImageDimension> VectorImageType;
- typedef typename VectorImageType::Pointer VectorImagePointerType;
- typedef itk::ImageRegionIterator<VectorImageType> VectorImageIteratorType;
-
- DataCollectionVectorImageIterator(DataCollection::Pointer collection, std::vector<std::string> featureNames);
-
- void ToBegin();
-
- bool IsAtEnd();
-
- DataCollectionVectorImageIterator& operator++();
-
- DataCollectionVectorImageIterator operator++(int);
-
- /**
- * Get the itk::VectorImage summarizing all the components of the collection. Attention:
- * this is a copy. Each component is one modality.
- *
- * @return the itk::VectorImage
- */
- VectorImagePointerType GetVectorImage();
-
- void
- AddImage(typename itk::Image<TDataType, ImageDimension>::Pointer image, std::string name);
-
- typedef typename mitk::DataCollectionSingleImageIterator<TDataType, ImageDimension> SingleImageIterator;
- typedef typename std::vector< SingleImageIterator > DataCollectionSingleImageIterators;
-
- private:
-
- DataCollection::Pointer m_Collection;
- DataCollectionSingleImageIterators m_FeatureIterators;
- };
-
-} /* namespace mitk */
-
-
-#include <Iterators/mitkDataCollectionVectorImageIterator.cxx>
-
-#endif
diff --git a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.cpp b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.cpp
deleted file mode 100644
index 6bfa0fb6c7..0000000000
--- a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.cpp
+++ /dev/null
@@ -1,388 +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.
-
-============================================================================*/
-#ifdef _MSC_VER
-# pragma warning (disable : 4996)
-#endif
-
-#include "mitkCollectionReader.h"
-#include <vtkXMLDataElement.h>
-
-#include <mitkIOUtil.h>
-//#include <mitkBaseDataIOFactory.h>
-
-#include <QDir>
-
-//XML StateMachine Tags
-// Objects
-const std::string COLLECTION = "col";
-const std::string SUBCOLLECTION = "subcol";
-const std::string DATA = "data";
-const std::string ITEM = "item";
-// Properties
-const std::string NAME = "name";
-const std::string ID = "id";
-const std::string FILEPATH = "description";
-const std::string LINK = "link";
-
-
-static std::string GetName(std::string fileName,std::string suffix)
-{
- fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString();
- return fileName.substr(0,fileName.length() -suffix.length()-9); // 8 = date length
-}
-
-static std::string GetDate(std::string fileName,std::string suffix)
-{
- fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString();
- fileName = fileName.substr(fileName.length() - suffix.length()-8,8); // 8 = date length
- fileName.insert(6,"-");
- fileName.insert(4,"-");
- return fileName;
-}
-
-
-mitk::CollectionReader::CollectionReader()
- : m_Collection(nullptr),
- m_SubCollection(nullptr),
- m_DataItemCollection(nullptr),
- m_ColIgnore(false), m_ItemIgnore(false)
-{
-}
-
-mitk::CollectionReader::~CollectionReader()
-{
- this->Clear();
-}
-
-
-/**
- * @brief Loads the xml file filename and generates the necessary instances.
- **/
-mitk::DataCollection::Pointer mitk::CollectionReader::LoadCollection(const std::string& xmlFileName)
-{
- QDir fileName = QFileInfo(xmlFileName.c_str()).absoluteDir();
- m_BaseDir = fileName.path().toStdString() + QDir::separator().toLatin1();
- this->SetFileName(xmlFileName.c_str());
- this->Parse();
- if (m_Collection.IsNotNull())
- m_Collection->SetXMLFile(xmlFileName);
- return m_Collection;
-}
-
-void mitk::CollectionReader::AddDataElementIds(std::vector<std::string> dataElemetIds)
-{
- m_SelectedDataItemIds.insert( m_SelectedDataItemIds.end(), dataElemetIds.begin(), dataElemetIds.end() );
-}
-
-void mitk::CollectionReader::AddSubColIds(std::vector<std::string> subColIds)
-{
- m_SelectedSubColIds.insert( m_SelectedSubColIds.end(), subColIds.begin(), subColIds.end() );
-}
-
-void mitk::CollectionReader::SetDataItemNames(std::vector<std::string> itemNames)
-{
- m_SelectedDataItemNames = itemNames;
-}
-
-void mitk::CollectionReader::ClearDataElementIds()
-{
- m_SelectedDataItemIds.clear();
-}
-
-void mitk::CollectionReader::ClearSubColIds()
-{
- m_SelectedSubColIds.clear();
-}
-
-void mitk::CollectionReader::Clear()
-{
- m_DataItemCollection = nullptr;
- m_SubCollection = nullptr;
- m_Collection = nullptr;
-}
-
-mitk::DataCollection::Pointer mitk::CollectionReader::FolderToCollection(std::string folder, std::vector<std::string> suffixes,std::vector<std::string> seriesNames, bool allowGaps)
-{
- // Parse folder and look up all data,
- // after sanitation only fully available groups are included (that is all suffixes are found)
- FileListType fileList = SanitizeFileList(GenerateFileLists(folder, suffixes, allowGaps));
-
- if (fileList.size() <= 0)
- return nullptr;
-
- DataCollection::Pointer collection = DataCollection::New();
- collection->SetName(GetName(fileList.at(0).at(0),suffixes.at(0)));
-
- for (unsigned int k=0; k < fileList.at(0).size(); ++k) // all groups have the same amount of items, so looking at 0 is ok.
- {
- DataCollection::Pointer subCollection = DataCollection::New();
- for (unsigned int i=0; i< suffixes.size(); ++i)
- {
- auto image = IOUtil::Load<Image>(fileList.at(i).at(k));
- subCollection->AddData(image.GetPointer(),seriesNames.at(i), fileList.at(i).at(k));
- }
- std::string sDate = GetDate(fileList.at(0).at(k),suffixes.at(0));
- collection->AddData(subCollection.GetPointer(),sDate,"--");
- }
- return collection;
-}
-
-void mitk::CollectionReader::StartElement(const char* elementName, const char **atts)
-{
- std::string name(elementName);
-
- if (name == COLLECTION)
- {
- m_Collection = DataCollection::New();
- std::string colName = ReadXMLStringAttribut(NAME, atts);
- m_Collection->SetName(colName);
- }
- else if (name == SUBCOLLECTION)
- {
- m_ColIgnore = false;
- m_ItemIgnore = false;
-
- std::string subColName = ReadXMLStringAttribut(NAME, atts);
- std::string subColId = ReadXMLStringAttribut(ID, atts);
-
- if (m_SelectedSubColIds.size() > 0 && std::find(m_SelectedSubColIds.begin(), m_SelectedSubColIds.end(), subColId) == m_SelectedSubColIds.end() )
- { // a) a selection list is provided AND b) the item is not in the list
- m_ColIgnore = true;
- return;
- }
-
- // Create subcollection
- m_SubCollection = DataCollection::New();
- m_SubCollection->Init(subColName);
- }
- else if (name == DATA)
- {
- if (m_ColIgnore)
- return;
-
- std::string dataId = ReadXMLStringAttribut(ID, atts);
- if (m_SelectedDataItemIds.size() > 0 && std::find(m_SelectedDataItemIds.begin(), m_SelectedDataItemIds.end(), dataId) == m_SelectedDataItemIds.end() )
- { // a) a selection list is provided AND b) the item is not in the list
- m_ItemIgnore = true;
- return;
- }
- m_ItemIgnore = false;
- std::string dataName = ReadXMLStringAttribut(NAME, atts);
-
- m_DataItemCollection = DataCollection::New();
- m_DataItemCollection->Init(dataName);
- }
- else if (name == ITEM)
- {
- if (m_ColIgnore || m_ItemIgnore)
- return;
-
-
- std::string relativeItemLink = ReadXMLStringAttribut(LINK, atts);
- std::string itemLink = m_BaseDir + relativeItemLink;
- std::string itemName = ReadXMLStringAttribut(NAME, atts);
-
- // if item names are provided and name is not in list, do not load it
- if (m_SelectedDataItemNames.size() != 0 && std::find(m_SelectedDataItemNames.begin(), m_SelectedDataItemNames.end(), itemName) == m_SelectedDataItemNames.end() )
- return;
-
- // Populate Sub-Collection
- auto image = IOUtil::Load<Image>(itemLink);
- if (image.IsNotNull())
- m_DataItemCollection->AddData(image.GetPointer(),itemName,relativeItemLink);
- else
- MITK_ERROR << "File could not be loaded: " << itemLink << ". Wihtin Sub-Collection " << m_SubCollection->GetName() << ", within " << m_DataItemCollection->GetName() ;
- }
- else
- MITK_WARN<< "Malformed description ? -- unknown tag: " << name;
-}
-
-void mitk::CollectionReader::EndElement(const char* elementName)
-{
- std::string name(elementName);
- if (name == SUBCOLLECTION)
- {
- if (m_SubCollection.IsNull())
- return;
- if (m_ColIgnore || m_SubCollection->Size() == 0)
- return;
-
- m_Collection->AddData(m_SubCollection.GetPointer(),m_SubCollection->GetName());
- m_SubCollection = DataCollection::New();
- }
- if (name == DATA)
- {
- if (m_DataItemCollection.IsNull())
- return;
- if (m_DataItemCollection->Size() == 0)
- return;
-
- m_SubCollection->AddData(m_DataItemCollection.GetPointer(),m_DataItemCollection->GetName());
- m_DataItemCollection = DataCollection::New();
- }
-}
-
-std::string mitk::CollectionReader::ReadXMLStringAttribut(std::string name, const char** atts)
-{
- if (atts)
- {
- const char** attsIter = atts;
-
- while (*attsIter)
- {
- if (name == *attsIter)
- {
- attsIter++;
- return *attsIter;
- }
- attsIter++;
- attsIter++;
- }
- }
- return std::string();
-}
-
-bool mitk::CollectionReader::ReadXMLBooleanAttribut(std::string name, const char** atts)
-{
- std::string s = ReadXMLStringAttribut(name, atts);
- std::transform(s.begin(), s.end(), s.begin(), ::toupper);
- if (s == "TRUE")
- return true;
- else
- return false;
-}
-
-
-int mitk::CollectionReader::ReadXMLIntegerAttribut(std::string name, const char** atts)
-{
- std::string s = ReadXMLStringAttribut(name, atts);
- return atoi(s.c_str());
-}
-
-
-
-mitk::CollectionReader::FileListType mitk::CollectionReader::GenerateFileLists(std::string folder, std::vector<std::string> suffixes, bool allowGaps)
-{
- FileListType fileList;
- QString qFolder = QString::fromStdString(folder);
- if (!QFileInfo(qFolder).isDir())
- {
- MITK_ERROR << "Folder does not exist.";
- return fileList;
- }
- // Add vector for each suffix
- for (unsigned int i=0; i< suffixes.size(); ++i)
- {
- std::vector<std::string> list;
- fileList.push_back(list);
- }
-
- // if gaps are allowed, file names are build up from reference file (first suffix)
- // else all lists a file, file by file with regular sorting of the files,
- // if one suffix has more/less images than the others loading is aborted
- if (allowGaps)
- {
- QDir parseDir;
- parseDir.setFilter(QDir::Files);
- parseDir.setPath(qFolder);
- QStringList filterMorph;
- filterMorph << "*" + QString::fromStdString( suffixes.at(0) );
- parseDir.setNameFilters( filterMorph );
-
- QFileInfoList qFileList = parseDir.entryInfoList();
-
- // now populate lists with files names, non-existing files will be marked with an empty string
- for (int i = 0; i < qFileList.size(); ++i)
- {
- std::string baseFileName = qFileList.at(i).absoluteFilePath().toStdString();
- fileList.at(0).push_back( baseFileName );
-
- //check for different suffixes
- for (unsigned int suffNo=1; suffNo < suffixes.size(); ++suffNo)
- {
- std::string derivedFileName = baseFileName.substr(0,baseFileName.length() -suffixes.at(0).length()) + suffixes.at(suffNo);
-
- // checking if file exists
- if (QFileInfo(QString::fromStdString(derivedFileName)).isFile())
- fileList.at(suffNo).push_back(derivedFileName);
- else
- fileList.at(suffNo).push_back("");
- }
- }
- }
- else
- {
- int numberOfFiles=-1;
- for (unsigned int i=0; i< suffixes.size(); ++i)
- {
- QDir parseDir;
- parseDir.setFilter(QDir::Files);
- parseDir.setPath(qFolder);
- QStringList filterMorph;
- filterMorph << "*" + QString::fromStdString( suffixes.at(i) );
- parseDir.setNameFilters( filterMorph );
-
- QFileInfoList qFileList = parseDir.entryInfoList();
- if (numberOfFiles == -1)
- numberOfFiles = qFileList.size();
-
- if (numberOfFiles != qFileList.size() )
- {
- MITK_ERROR << "Series contain different number of images. Loading aborting.";
- fileList.clear();
- break;
- }
-
- for (int fileNo=0; fileNo<qFileList.size(); ++fileNo)
- {
- fileList.at(i).push_back(qFileList.at(fileNo).absoluteFilePath().toStdString());
- }
- }
- }
- return fileList;
-}
-
-mitk::CollectionReader::FileListType mitk::CollectionReader::SanitizeFileList(mitk::CollectionReader::FileListType list)
-{
- std::vector<int> indexRemoval;
- // Parse through all items and check for empty strings, if one occurs mark this index
- // for removal.
- int modalities = list.size();
- int timeSteps = list.at(0).size();
- MITK_INFO << "Modalities " << modalities;
- MITK_INFO << "TimeSteps " << timeSteps;
- if (timeSteps == 0)
- MITK_ERROR << "No files found. Fatal.";
- for (int listIndex = 0 ; listIndex < timeSteps; listIndex++)
- {
- for (int modalityIndex = 0 ; modalityIndex < modalities; modalityIndex++)
- {
- if (list.at(modalityIndex).at(listIndex) == "")
- {
- MITK_INFO << "Marked Index " << listIndex << " for removal.";
- indexRemoval.push_back(listIndex);
- break;
- }
- }
- }
-
-
- for (int listIndex = indexRemoval.size()-1 ; listIndex >= 0; --listIndex)
- {
- for (int i = 0 ; i < modalities; i++)
- {
- list.at(i).erase(list.at(i).begin()+indexRemoval.at(listIndex)) ;
- }
- }
- MITK_INFO << "Time Steps after sanitizing: " << list.at(0).size();
- return list;
-}
diff --git a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.h b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.h
deleted file mode 100644
index 060a2520a5..0000000000
--- a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.h
+++ /dev/null
@@ -1,143 +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.
-
-============================================================================*/
-
-#ifndef mitkCollectionReader_h
-#define mitkCollectionReader_h
-
-#include "mitkCommon.h"
-#include "mitkDataCollection.h"
-#include <MitkDataCollectionExports.h>
-
-// VTK
-#include <vtkXMLParser.h>
-
-namespace mitk {
- class MITKDATACOLLECTION_EXPORT CollectionReader : public vtkXMLParser
- {
- public:
-
- typedef std::vector<std::vector<std::string> > FileListType;
-
- /**
- * @brief Build up a mitk::DataCollection from a XML resource
- *
- **/
- DataCollection::Pointer LoadCollection(const std::string& xmlFileName);
-
- void AddDataElementIds(std::vector<std::string> dataElemetIds);
- void AddSubColIds(std::vector<std::string> subColIds);
-
- void SetDataItemNames(std::vector<std::string> itemNames);
-
- void ClearDataElementIds();
- void ClearSubColIds();
-
- void Clear();
-
- /**
- * @brief Build up a mitk::DataCollection from a folder providing suffixes to group the files
- *
- **/
- static DataCollection::Pointer FolderToCollection(std::string folder, std::vector<std::string> suffixes,std::vector<std::string> seriesNames, bool allowGaps);
-
- /**
- * @brief GenerateFileLists Returns a collection of lists with valid files names in a folder
- *
- * The first suffix entry in the vector is used for the reference images which are put in the first list,
- * then the suffixes are interchanged and checked if the file exists; for each suffix a list is returned with filenames,
- * if a file is expected but does not exist an empty string "" is added instead.
- *
- * @param folder
- * @param suffixes
- * @param allowGaps
- * @return
- */
- static FileListType GenerateFileLists(std::string folder, std::vector<std::string> suffixes, bool allowGaps = false);
-
- /**
- * @brief SanitizeFileList Removes all entries that are lacking at least one modality
- * @param list - sanitized list
- * @return
- */
-
- static FileListType SanitizeFileList(FileListType list);
-
- CollectionReader();
- ~CollectionReader() override;
- protected:
-
- /**
- * @brief Derived from XMLReader
- **/
- void StartElement (const char* elementName, const char **atts) override;
- /**
- * @brief Derived from XMLReader
- **/
- void EndElement (const char* elementName) override;
-
- private:
- /**
- * @brief Derived from XMLReader
- **/
- std::string ReadXMLStringAttribut( std::string name, const char** atts);
- /**
- * @brief Derived from XMLReader
- **/
- bool ReadXMLBooleanAttribut( std::string name, const char** atts );
- /**
- * @brief Derived from XMLReader
- **/
- int ReadXMLIntegerAttribut( std::string name, const char** atts );
-
- /**
- * @brief m_DataCollection
- * Stores a data collection during build of
- */
- DataCollection::Pointer m_Collection;
- DataCollection::Pointer m_SubCollection;
- DataCollection::Pointer m_DataItemCollection;
-
- /**
- * @brief m_SelectedIds
- *
- * Stores ids which are to be considered during loading, if this is provided all
- * all data sets not matching an ID in this list are skipped.
- */
- std::vector<std::string> m_SelectedSubColIds;
-
- std::vector<std::string> m_SelectedDataItemIds;
-
- /**
- * @brief m_SelectedDataItemNames
- * Lists names of items to be loaded, rest is ignored
- */
-
- std::vector<std::string> m_SelectedDataItemNames;
-
- /**
- * @brief m_Ignore
- *
- * Determines if current sub-collection is ignored
- */
- bool m_ColIgnore;
- bool m_ItemIgnore;
-
- /**
- * @brief m_BaseDir
- *
- * Stores Base directory to allow XML links with relative paths
- */
- std::string m_BaseDir;
- };
-} // namespace mitk
-
-#endif
diff --git a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.cpp b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.cpp
deleted file mode 100755
index 076dcb9e82..0000000000
--- a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.cpp
+++ /dev/null
@@ -1,416 +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.
-
-============================================================================*/
-#ifdef _MSC_VER
-# pragma warning (disable : 4996)
-#endif
-
-#include "mitkCollectionWriter.h"
-
-#include <mitkIOUtil.h>
-
-#include "mitkImageCast.h"
-#include "itkNrrdImageIO.h"
-#include "itkImageFileWriter.h"
-#include "mitkCoreObjectFactory.h"
-
-
-#include <iostream>
-#include <fstream>
-
-#include <QDir>
-
-//XML StateMachine Tags
-// Objects
-const std::string COLLECTION = "col";
-const std::string SUBCOLLECTION = "subcol";
-const std::string DATA = "data";
-const std::string ITEM = "item";
-// Properties
-const std::string NAME = "name";
-const std::string ID = "id";
-const std::string FILEPATH = "filepath";
-const std::string LINK = "link";
-
-
-static std::string GetName(std::string fileName,std::string suffix, bool longName = false)
-{
- fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString();
- if (longName)
- return fileName.substr(0,fileName.length() -suffix.length()-11); // 10 = date length
- else
- return fileName.substr(0,fileName.length() -suffix.length()-9); // 8 = date length
-}
-
-static std::string GetDate(std::string fileName,std::string suffix, bool longName = false)
-{
- fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString();
- if (longName)
- fileName = fileName.substr(fileName.length() - suffix.length()-10,10); // 8 = date length
- else
- fileName = fileName.substr(fileName.length() - suffix.length()-8,8); // 8 = date length
- if (!longName)
- {
- fileName.insert(6,"-");
- fileName.insert(4,"-");
- }
- return fileName;
-}
-
-
-
-
-bool mitk::CollectionWriter::ExportCollectionToFolder(DataCollection *dataCollection, std::string xmlFile, std::vector<std::string> filter)
-{
- // Quick and Dirty: Assumes three level DataCollection
- QDir fileName = QFileInfo(xmlFile.c_str()).absoluteDir();
- std::string outputFolder = fileName.path().toStdString() + QDir::separator().toLatin1();
- QDir baseFolder(outputFolder.c_str());
- baseFolder.mkpath(outputFolder.c_str());
-
- std::ofstream xmlFileStream;
- xmlFileStream.open (xmlFile.c_str());
- xmlFileStream << "<!-- MITK - DataCollection - File Version 1.0 --> \n";
- xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << dataCollection->GetName() << "\" >\n";
- unsigned int subColId = 0;
-
- unsigned int dataId = 0;
-
- QDir dir(QString::fromStdString(outputFolder));
- for (size_t i = 0 ; i < dataCollection->Size(); ++i)
- {
- // Write Subcollection tag
- xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << dataCollection->IndexToName(i) << "\" " << FILEPATH << "=\"" << dataCollection->GetDataFilePath(i) << "\" id=\"Col" << subColId << "\" >\n";
- // Create Sub-Folder
- dir.mkpath(QString::fromStdString(dataCollection->IndexToName(i)));
-
- // Herein create data folders
- DataCollection* subCollections = dynamic_cast<DataCollection*> (dataCollection->GetData(i).GetPointer());
- if (subCollections == nullptr)
- {
- MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting";
- return false;
- }
-
- for (size_t d = 0; d < subCollections->Size(); d++ )
- {
- // Create Sub Paths
- QString subPath = QString::fromStdString(dataCollection->IndexToName(i))+"/"+QString::fromStdString(subCollections->IndexToName(d));
- dir.mkpath(subPath);
- xmlFileStream << " <" << DATA << " " << NAME << "=\"" << subCollections->IndexToName(d) << "\" " << FILEPATH << "=\"" << subCollections->GetDataFilePath(d) << "\" id=\"Data" << dataId << "\" >\n";
-
- DataCollection* itemCollections = dynamic_cast<DataCollection*> (subCollections->GetData(d).GetPointer());
- if (itemCollections == nullptr)
- {
- MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting";
- return false;
- }
-
- for (size_t s = 0; s < itemCollections->Size(); s++)
- {
- if (filter.size() > 0)
- {
- bool isSelected = false;
- for (size_t f = 0; f < filter.size(); f++)
- {
- if (filter.at(f) == itemCollections->IndexToName(s) )
- {
- isSelected = true;
- break;
- }
- }
- if (isSelected == false)
- continue;
- }
-
- QString fileName = dir.path() + dir.separator() + subPath + dir.separator() + QString::fromStdString(dataCollection->IndexToName(i)) + "_" + QString::fromStdString(subCollections->IndexToName(d)) + "_" + QString::fromStdString(itemCollections->IndexToName(s));
- try
- {
- fileName += ".nrrd";
- Image::Pointer image = itemCollections->GetMitkImage(s).GetPointer();
- IOUtil::Save(image, fileName.toStdString());
- }
- catch ( const std::exception& e )
- {
- MITK_ERROR << "Caught exception: " << e.what();
- }
-
- std::string relativeFilename = baseFolder.relativeFilePath(fileName).toStdString();
- xmlFileStream << " <" << ITEM << " " << NAME << "=\"" <<itemCollections->IndexToName(s) << "\" " << FILEPATH << "=\"" << "\" " << LINK << "=\"" << relativeFilename << "\" />\n";
- }
- xmlFileStream << " </" << DATA << ">\n";
- dataId++;
- }
-
- xmlFileStream << " </" << SUBCOLLECTION << ">\n";
- subColId++;
- }
- xmlFileStream << "</" << COLLECTION << ">\n";
- xmlFileStream.flush();
- xmlFileStream.close();
- return true;
-}
-
-bool mitk::CollectionWriter::ExportCollectionToFolder(mitk::DataCollection *dataCollection, std::string xmlFile)
-{
- std::vector<std::string> mods;
- return ExportCollectionToFolder(dataCollection,xmlFile, mods);
-}
-
-bool mitk::CollectionWriter::SaveCollection(mitk::DataCollection *dataCollection, std::vector<std::string> filter, std::string xmlFile)
-{
- QDir origFilename = QFileInfo(dataCollection->GetXMLFile().c_str()).absoluteDir();
- QString originalFolder = origFilename.path() + QDir::separator();
-
- if (xmlFile == "")
- xmlFile = dataCollection->GetXMLFile();
-
- QDir fileName = QFileInfo(xmlFile.c_str()).absoluteDir();
- std::string outputFolder = fileName.path().toStdString() + QDir::separator().toLatin1();
- QDir baseFolder(outputFolder.c_str());
-
- std::ofstream xmlFileStream;
- xmlFileStream.open (xmlFile.c_str());
- xmlFileStream << "<!-- MITK - DataCollection - File Version 1.0 --> \n";
- xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << dataCollection->GetName() << "\" >\n";
- unsigned int subColId = 0;
-
- unsigned int dataId = 0;
-
- QDir dir(QString::fromStdString(outputFolder));
- for (size_t i = 0 ; i < dataCollection->Size(); ++i)
- {
- // Write Subcollection tag
- xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << dataCollection->IndexToName(i) << "\" " << FILEPATH << "=\"" << dataCollection->GetDataFilePath(i) << "\" id=\"Col" << subColId << "\" >\n";
- // Create Sub-Folder
- dir.mkpath(QString::fromStdString(dataCollection->IndexToName(i)));
-
- // Herein create data folders
- DataCollection* subCollections = dynamic_cast<DataCollection*> (dataCollection->GetData(i).GetPointer());
- if (subCollections == nullptr)
- {
- MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting";
- return false;
- }
-
- for (size_t d = 0; d < subCollections->Size(); d++ )
- {
- // Create Sub Paths
- QString subPath = QString::fromStdString(dataCollection->IndexToName(i))+"/"+QString::fromStdString(subCollections->IndexToName(d));
- dir.mkpath(subPath);
- xmlFileStream << " <" << DATA << " " << NAME << "=\"" << subCollections->IndexToName(d) << "\" " << FILEPATH << "=\"" << subCollections->GetDataFilePath(d) << "\" id=\"Data" << dataId << "\" >\n";
-
- DataCollection* itemCollections = dynamic_cast<DataCollection*> (subCollections->GetData(d).GetPointer());
- if (itemCollections == nullptr)
- {
- MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting";
- return false;
- }
-
- for (size_t s = 0; s < itemCollections->Size(); s++)
- {
- if (filter.size() > 0)
- {
- bool isSelected = false;
- for (size_t f = 0; f < filter.size(); f++)
- {
- if (filter.at(f) == itemCollections->IndexToName(s) )
- {
- isSelected = true;
- break;
- }
- }
- if (isSelected == false)
- continue;
- }
-
- QString fileName;
- bool fullName = false;
- if (itemCollections->GetDataFilePath(s) != "")
- {
- fileName = originalFolder + QString::fromStdString(itemCollections->GetDataFilePath(s));
- fullName = true;
- MITK_INFO << "original path: " << itemCollections->GetDataFilePath(s) ;
- }
- else
- fileName = dir.path() + dir.separator() + subPath + dir.separator() + QString::fromStdString(dataCollection->IndexToName(i)) + "_" + QString::fromStdString(subCollections->IndexToName(d)) + "_" + QString::fromStdString(itemCollections->IndexToName(s));
-
- try
- {
- if (!fullName)
- fileName += ".nrrd";
- Image::Pointer image = itemCollections->GetMitkImage(s).GetPointer();
- IOUtil::Save(image,fileName.toStdString());
- }
- catch ( const std::exception& e )
- {
- MITK_ERROR << "Caught exception: " << e.what();
- }
-
- std::string relativeFilename =baseFolder.relativeFilePath(fileName).toStdString();
- xmlFileStream << " <" << ITEM << " " << NAME << "=\"" <<itemCollections->IndexToName(s) << "\" " << FILEPATH << "=\"" << "\" " << LINK << "=\"" << relativeFilename << "\" />\n";
- }
- xmlFileStream << " </" << DATA << ">\n";
- dataId++;
- }
-
- xmlFileStream << " </" << SUBCOLLECTION << ">\n";
- subColId++;
- }
- xmlFileStream << "</" << COLLECTION << ">\n";
- xmlFileStream.flush();
- xmlFileStream.close();
- return true;
-}
-
-bool mitk::CollectionWriter::FolderToXml(std::string folder, std::string collectionType, std::string xmlFile, std::vector<std::string> filter, std::vector<std::string> seriesNames)
-{
- // 1) Parse for folders
-
- QDir parseDir;
- parseDir.setFilter( QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
- parseDir.setPath(QString::fromStdString(folder));
-
- QFileInfoList qFileList = parseDir.entryInfoList();
-
-
- std::ofstream xmlFileStream;
- xmlFileStream.open (xmlFile.c_str());
- xmlFileStream << "<!-- MITK - DataCollection - File Version 1.0 --> \n";
- xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << "GEN" << "\" >\n";
-
- unsigned int dataId = 0;
-
- // now populate lists with files names, non-existing files will be marked with an empty string
- for (int i = 0; i < qFileList.size(); ++i)
- {
- // 2) For Each sub folder construct collectionType sub-folder
- std::string baseFolder = qFileList.at(i).absoluteFilePath().toStdString() + QDir::separator().toLatin1() + collectionType;
-
- MITK_INFO << "Processing : " << baseFolder;
- if (!QFileInfo(QString::fromStdString(baseFolder)).isDir())
- {
- MITK_WARN << "Not a valid folder, skipping.";
- continue;
- }
-
- // 3) Parse each sub folder and extend XML file
- // Parse folder and look up all data,
- // after sanitation only fully available groups are included (that is all suffixes are found)
-
- CollectionReader::FileListType fileList = CollectionReader::SanitizeFileList(CollectionReader::GenerateFileLists(baseFolder, filter,true));
- if (fileList.size() <= 0 || fileList.at(0).size() <= 0)
- continue;
-
- // Write Subcollection tag
- // try to extract date out of filename
- std::string name = GetName(fileList.at(0).at(0),filter.at(0));
- xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << name << "\" " << FILEPATH << "=\"\" id=\"Col" << i << "\" >\n";
-
-
- for (unsigned int k=0; k < fileList.at(0).size(); ++k) // all groups have the same amount of items, so looking at 0 is ok.
- {
- std::string strDate = GetDate(fileList.at(0).at(k),filter.at(0));
- xmlFileStream << " <" << DATA << " " << NAME << "=\"" << strDate << "\" " << " id=\"Data" << dataId << "\" >\n";
- dataId++;
- for (unsigned int i=0; i< filter.size(); ++i)
- {
- std::string fileName = fileList.at(i).at(k);
- xmlFileStream << " <" << ITEM << " " << NAME << "=\"" << seriesNames.at(i) << "\" " << LINK << "=\"" << fileName << "\" />\n";
- }
- xmlFileStream << " </" << DATA << ">\n" ;
- }
- xmlFileStream << " </" << SUBCOLLECTION << ">\n";
- }
-
- xmlFileStream << "</" << COLLECTION << ">\n";
- xmlFileStream.flush();
- xmlFileStream.close();
-
- return true;
-}
-
-bool mitk::CollectionWriter::SingleFolderToXml(std::string folder, std::string xmlFile, std::vector<std::string> filter, std::vector<std::string> seriesNames, bool longDate, int skipUntil, float months)
-{
- std::ofstream xmlFileStream;
- xmlFileStream.open (xmlFile.c_str());
- xmlFileStream << "<!-- MITK - DataCollection - File Version 1.0 --> \n";
- xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << "GEN" << "\" >\n";
-
- unsigned int dataId = 0;
-
- // 1)
- // Parse folder and look up all data,
- // after sanitation only fully available groups are included (that is all suffixes are found)
-
- CollectionReader::FileListType fileList = CollectionReader::SanitizeFileList(CollectionReader::GenerateFileLists(folder, filter,true));
-
- // Write Subcollection tag
- // try to extract date out of filename
- std::string name = GetName(fileList.at(0).at(0),filter.at(0),longDate);
- xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << name << "\" " << FILEPATH << "=\"\" id=\"Col" << 0 << "\" >\n";
-
-
- for (unsigned int k=skipUntil; k < fileList.at(0).size(); ++k) // all groups have the same amount of items, so looking at 0 is ok.
- {
- std::string strDate = GetDate(fileList.at(0).at(k),filter.at(0),true);
- xmlFileStream << " <" << DATA << " " << NAME << "=\"" << strDate << "\" " << " id=\"Data" << dataId << "\" >\n";
- dataId++;
- for (unsigned int i=0; i< filter.size(); ++i)
- {
- std::string fileName = fileList.at(i).at(k);
- xmlFileStream << " <" << ITEM << " " << NAME << "=\"" << seriesNames.at(i) << "\" " << LINK << "=\"" << fileName << "\" />\n";
- }
-
- // size_t ind = GetIndexForinXMonths(fileList,months,k,filter);
- // xmlFileStream << " <" << ITEM << " " << NAME << "=\"TARGET\" " << LINK << "=\"" << fileList.at(filter.size()-1).at(ind) << "\" />\n";
-
- xmlFileStream << " </" << DATA << ">\n" ;
- // check if target still exists for next step
- if (GetIndexForinXMonths(fileList,months,k+1,filter)== 0)
- break;
- }
- xmlFileStream << " </" << SUBCOLLECTION << ">\n";
-
- xmlFileStream << "</" << COLLECTION << ">\n";
- xmlFileStream.flush();
- xmlFileStream.close();
-
- return true;
-}
-
-size_t mitk::CollectionWriter::GetIndexForinXMonths(mitk::CollectionReader::FileListType fileList,float months, size_t curIndex,std::vector<std::string> filter)
-{
- std::string strDate0 = GetDate(fileList.at(0).at(curIndex),filter.at(0),true);
-
- int year0 =std::atoi(strDate0.substr(0,4).c_str());
- int month0 =std::atoi(strDate0.substr(5,2).c_str());
- int day0 = std::atoi(strDate0.substr(8,2).c_str());
-
- size_t bestIndex = 0;
- int bestFit = 1e5;
-
- for (size_t i=curIndex+1; i < fileList.at(0).size(); ++i)
- {
- std::string strDate = GetDate(fileList.at(0).at(i),filter.at(0),true);
- int year =std::atoi(strDate.substr(0,4).c_str());
- int month =std::atoi(strDate.substr(5,2).c_str());
- int day = std::atoi(strDate.substr(8,2).c_str());
-
- int fit = std::fabs((months * 30 ) - (((year-year0)*360) +((month-month0)*30) + (day-day0))); // days difference from x months
- if (fit < bestFit)
- {
- bestFit = fit;
- bestIndex = i;
- }
- }
- return bestIndex;
-}
diff --git a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.h b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.h
deleted file mode 100755
index e286c73057..0000000000
--- a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.h
+++ /dev/null
@@ -1,69 +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.
-
-============================================================================*/
-
-#ifndef mitkCollectionWriter_h
-#define mitkCollectionWriter_h
-
-//#include "mitkCommon.h"
-#include "mitkDataCollection.h"
-#include "mitkCollectionReader.h"
-#include <MitkDataCollectionExports.h>
-
-namespace mitk {
- class MITKDATACOLLECTION_EXPORT CollectionWriter
- {
- public:
- /**
- * @brief ExportCollectionToFolder
- *
- * Creates an XML file and stores all data in the same folder as the xml file (creating sub-folders for sub-collections)
- *
- * @param dataCollection
- * @param xmlFile
- * @param filter - (optional) only items with names contained in this list are written, if list is empty all items are written
- * @return
- */
- static bool ExportCollectionToFolder(DataCollection* dataCollection, std::string xmlFile , std::vector<std::string> filter);
-
- static bool ExportCollectionToFolder(DataCollection* dataCollection, std::string xmlFile);
-
- /**
- * @brief SaveCollection - Stores data collection at original location
- *
- * Writes the collection back to the files given in the original XML file.
- * New data items are stored into the default location, which is relative to the XML file.
- *
- * If a XML file is provided the files are stored as stated above with the differences that a new XML file is generated and new files are saved
- * relative to the newly generated xml.
- *
- * @param dataCollection
- * @param filter
- * @param xmlFile
- * @return
- */
-
- static bool SaveCollection(DataCollection* dataCollection, std::vector<std::string> filter, std::string xmlFile = "");
-
- static bool FolderToXml(std::string folder, std::string collectionType, std::string xmlFile, std::vector<std::string> filter, std::vector<std::string> seriesNames);
-
- // GTV last entry in filter list, this item will be made to TARGET
- static bool SingleFolderToXml(std::string folder, std::string xmlFile, std::vector<std::string> filter, std::vector<std::string> seriesNames, bool longDate = true, int skipUntil = 0, float months = 0);
-
- protected:
-
- private:
-
- static size_t GetIndexForinXMonths(CollectionReader::FileListType fileList, float months, size_t curIndex, std::vector<std::string> filter);
- };
-} // namespace mitk
-
-#endif
diff --git a/Modules/Classification/DataCollection/Testing/CMakeLists.txt b/Modules/Classification/DataCollection/Testing/CMakeLists.txt
deleted file mode 100644
index 06d83bd7b9..0000000000
--- a/Modules/Classification/DataCollection/Testing/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-MITK_CREATE_MODULE_TESTS()
-
-IF(BUILD_TESTING AND MODULE_IS_ENABLED)
-#
-# mitkAddCustomModuleTest("mitkClassificationTest"
-# "mitkClassificationTest" "Param....")
-#
-ENDIF()
\ No newline at end of file
diff --git a/Modules/Classification/DataCollection/Testing/files.cmake b/Modules/Classification/DataCollection/Testing/files.cmake
deleted file mode 100644
index 5dda63c973..0000000000
--- a/Modules/Classification/DataCollection/Testing/files.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-SET(MODULE_TESTS
- mitkDataCollectionImageIteratorTest.cpp
-)
-
-SET(MODULE_CUSTOM_TESTS
-# mitkDataCollectionFromXMLTest.cpp
-# mitkDataCollectionImageIteratorTest.cpp
-# mitkDataCollectionBySuffix.cpp
-)
diff --git a/Modules/Classification/DataCollection/Testing/mitKnnClassificationTest.cpp b/Modules/Classification/DataCollection/Testing/mitKnnClassificationTest.cpp
deleted file mode 100644
index fd4963531a..0000000000
--- a/Modules/Classification/DataCollection/Testing/mitKnnClassificationTest.cpp
+++ /dev/null
@@ -1,280 +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 <mitkStandaloneDataStorage.h>
-#include <mitkIOUtil.h>
-#include <mitkClassification.h>
-
-#include <itkImageFileReader.h>
-#include <itkImageFileWriter.h>
-#include <itkFlipImageFilter.h>
-#include "itkImageDuplicator.h"
-#include <stdlib.h>
-#include <itkFileTools.h>
-
-#include "ml.h"
-
-#include <mitkClassResultToImageFilter.h>
-
-#include <mitkClassificationKnn.h>
-#include <mitkImageDataCollections.h>
-
-#define VDimension 3
-
-// 2 D:\\output\\ D:\\TestImages\\train1.nrrd D:\\TestImages\\train2.nrrd D:\\TestImages\\train3.nrrd D:\\TestImages\\target1.nrrd D:\\TestImages\\target2.nrrd D:\\TestImages\\target3.nrrd D:\\TestImages\\test1.nrrd D:\\TestImages\\test2.nrrd D:\\TestImages\\test3.nrrd
-
-typedef unsigned char PixelType;
-typedef itk::Image< PixelType,VDimension > ImageType;
-typedef ImageType::Pointer ImageTypePtr;
-
-typedef itk::ImageFileReader< ImageType> ReaderType;
-typedef itk::ImageFileWriter< ImageType> WriterType;
-typedef mitk::mitkClassResultToImageFilter<unsigned char,VDimension> ResultToImageType;
-typedef itk::ImageDuplicator< ImageType > DuplicatorType;
-
-//cv::Mat create2DImageFromVect(cv::Size size, cv::Mat& image )
-//{
-// unsigned long index;
-// unsigned long x = 0;
-// unsigned long y = 0;
-//
-// cv::Mat outputImage(size.height,size.width,CV_32FC1);
-//
-// if(image.cols < 0)
-// {
-// std::cout << "Can't create 2D Image" << std::endl;
-// return outputImage;
-//
-// }
-//
-// for( index = 0; index < size.width*size.height ; index++)
-// {
-// x = (int) index % (size.width);
-// float d = index / (size.width);
-// y = (int) floor( d);
-//
-// unsigned char value;
-// float val = image.at<float>(index,0);
-// value = (unsigned char) val;
-// outputImage.at<unsigned char>(y,x)= value;
-// }
-//
-// return outputImage;
-//}
-
-int mitKnnClassificationTest(int argc, char* argv[] )
-{
- if(argc < 5 )
- {
- MITK_INFO << "Please specify number of NN as first parameter, as second parameter output path and train, target and test images in abitrary order" << std::endl << " train data must start with 'train*', target with 'target*' and test with 'test.'" << std::endl<< "Usage: 3 D:\\output\\ D:\\TestImages\\train1.nrrd D:\\TestImages\\train2.nrrd D:\\TestImages\\train3.nrrd D:\\TestImages\\target1.nrrd D:\\TestImages\\target2.nrrd D:\\TestImages\\target3.nrrd D:\\TestImages\\test1.nrrd D:\\TestImages\\test2.nrrd D:\\TestImages\\test3.nrrd" << std::endl;
- exit(-1);
- }
-
- std::vector<std::string> inputFilesTrain;
- std::vector<std::string> inputFilesTarget;
- std::vector<std::string> inputFilesTest;
- std::string outputFolder;
-
- int k = atoi(argv[1]);
-
- outputFolder = argv[2];
-
- for(int i = 3; i < argc; i++)
- {
- std::string str;
- str = argv[i];
- if(str.find("train") != std::string::npos)
- {
- inputFilesTrain.push_back(str);
- }
- else if (str.find("target") != std::string::npos)
- {
- inputFilesTarget.push_back(str);
- }
- else if(str.find("test") != std::string::npos)
- {
- inputFilesTest.push_back(str);
- }
- }
-
- if( ( inputFilesTrain.size() || inputFilesTarget.size() ) <= 0)
- {
- MITK_INFO << "No test or training image set! " << std::endl;
- return -1;
- }
-
- if(inputFilesTrain.size() != inputFilesTarget.size())
- {
- MITK_INFO << "Number of training and target images are not equal - please specify same number for training " << std::endl;
- return -1;
- }
-
- std::vector<ImageTypePtr> trainImages;
- std::vector<ImageTypePtr> targetImages;
- std::vector<ImageTypePtr> testImages;
-
- ReaderType::Pointer reader = ReaderType::New();
- WriterType::Pointer writer = WriterType::New();
-
- DuplicatorType::Pointer duplicator = DuplicatorType::New();
-
- for(int i = 0; i< inputFilesTrain.size(); i++)
- {
- reader->SetFileName(inputFilesTrain.at(i));
- reader->Update();
-
- duplicator->SetInputImage(reader->GetOutput());
- duplicator->Update();
- trainImages.push_back(duplicator->GetOutput());
- }
-
- for(int i = 0; i< inputFilesTarget.size(); i++)
- {
- reader->SetFileName(inputFilesTarget.at(i));
- reader->Update();
-
- duplicator->SetInputImage(reader->GetOutput());
- duplicator->Update();
- targetImages.push_back(duplicator->GetOutput());
- }
-
- for(int i = 0; i< inputFilesTest.size(); i++)
- {
- reader->SetFileName(inputFilesTest.at(i));
- reader->Update();
-
- duplicator->SetInputImage(reader->GetOutput());
- duplicator->Update();
- testImages.push_back(duplicator->GetOutput());
- }
-
- ResultToImageType::Pointer resultToImage = ResultToImageType::New();
-
- mitk::mitkClassificationFeatureVectCreator<PixelType,VDimension>::Pointer featureVectCreator = mitk::mitkClassificationFeatureVectCreator<PixelType,VDimension>::New();
-
- // SET NUMBER OF FeaturesProperly
- featureVectCreator->SetNumberOfFeaturesPerVoxel(1);
- featureVectCreator->SetGenerateResponsEnabled(false);
-
- cv::Mat output;
-
- // Image size
- ImageType::SizeType size;
-
- size = trainImages.at(0)->GetLargestPossibleRegion().GetSize();
-
- int dim = 1;
-
- for(int i = 0; i < VDimension; i++)
- {
- dim *= size[i];
- }
-
- // generate feature matrix from input images
-
- // generate train data
- for(int i = 0; i < trainImages.size(); i++)
- {
- featureVectCreator->SetPrimaryInput(trainImages.at(i));
- featureVectCreator->Update();
- }
-
- cv::Mat trainData = featureVectCreator->GetOuputCv();
-
- //for(int i = 0; i< (trainData.rows /dim) ; i++ )
- //{
- // cv::Rect roi(0, i * dim,1,dim);
- // cv::Mat image(trainData,roi);
-
- // std::cout << image << std::endl;
- //}
-
- featureVectCreator->ClearData();
-
- //generate target data for train data
- for(int i = 0; i < targetImages.size(); i++)
- {
- featureVectCreator->SetPrimaryInput(targetImages.at(i));
- featureVectCreator->Update();
- }
-
- cv::Mat targetData = featureVectCreator->GetOuputCv();
-
- //for(int i = 0; i< (targetData.rows /dim) ; i++ )
- //{
- // cv::Rect roi(0, i * dim,1,dim);
- // cv::Mat image(targetData,roi);
-
- // std::cout << image << std::endl;
- //}
-
- // generate test data
- featureVectCreator->ClearData();
-
- for(int i = 0; i < testImages.size(); i++)
- {
- featureVectCreator->SetPrimaryInput(testImages.at(i));
- featureVectCreator->Update();
- }
-
- cv::Mat testData = featureVectCreator->GetOuputCv();
-
- //for(int i = 0; i< (testData.rows /dim) ; i++ )
- //{
- // cv::Rect roi(0, i * dim,1,dim);
- // cv::Mat image(testData,roi);
-
- // std::cout << image << std::endl;
- //}
-
- // Classification!!
-
- // KNN
-
- // number of NearestNeighbors
-
- CvKNearest knn( trainData, targetData, cv::Mat() ,false, k);
-
- cv::Mat neighbors(1,k, CV_32FC1);
- cv::Mat result(1,k,CV_32FC1);
-
- knn.find_nearest(testData,k,result,neighbors, cv::Mat());
-
- itk::ProcessObject::DataObjectPointerArray array = resultToImage->GetOutputs();
-
- if( itksys::SystemTools::FileIsDirectory(outputFolder.c_str() ) || !itksys::SystemTools::FileExists(outputFolder.c_str(),false) )
- {
- itksys::SystemTools::MakeDirectory(outputFolder.c_str());
- }
-
- // Write result images
- for(int i = 0; i< (result.rows /dim) ; i++ )
- {
- cv::Rect roi(0, i * dim,1,dim);
- cv::Mat image(result,roi);
-
- resultToImage->setOpenCVInput(image,size);
-
- std::cout << image << std::endl;
-
- resultToImage->Update();
- ImageTypePtr img = resultToImage->GetOutput(0);
-
- std::stringstream filename;
- filename << outputFolder << "result" << i << ".nrrd";
- writer->SetFileName(filename.str());
- writer->SetInput(img);
- writer->Update();
- }
-
- return 0;
-}
diff --git a/Modules/Classification/DataCollection/Testing/mitkDataCollectionBySuffix.cpp b/Modules/Classification/DataCollection/Testing/mitkDataCollectionBySuffix.cpp
deleted file mode 100644
index 0ee3c4f088..0000000000
--- a/Modules/Classification/DataCollection/Testing/mitkDataCollectionBySuffix.cpp
+++ /dev/null
@@ -1,48 +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.
-
-============================================================================*/
-#pragma warning (disable : 4996)
-
-#include "mitkTestingMacros.h"
-#include "mitkDataCollection.h"
-#include "mitkCollectionReader.h"
-#include "mitkIOUtil.h"
-
-#include <vtkSmartPointer.h>
-
-int mitkDataCollectionBySuffix(int argc, char* argv[])
-{
- MITK_TEST_BEGIN("DataCollectionBySuffix");
-
- if(argc <= 1)
- {
- MITK_ERROR << "Provide XML File to parse.";
- return -1;
- }
-
-
- std::vector<std::string> suffixes;
- suffixes.push_back("_T2_reg.nrrd");
- suffixes.push_back("_T1_reg.nrrd");
- suffixes.push_back("_ce_reg.nrrd");
- suffixes.push_back("_gtv_reg.nrrd");
- suffixes.push_back("_reg.dwi");
-
- mitk::DataCollection::Pointer collection = mitk::CollectionReader::FolderToCollection(argv[1],suffixes,suffixes,true);
-
- MITK_INFO << "Collection No of time steps: " << collection->Size();
- mitk::DataCollection* col = dynamic_cast<mitk::DataCollection*> (collection->GetData(0).GetPointer());
- MITK_INFO << "Collection No of modalities: " << col->Size();
-
-
-
- MITK_TEST_END();
-}
diff --git a/Modules/Classification/DataCollection/Testing/mitkDataCollectionFromXMLTest.cpp b/Modules/Classification/DataCollection/Testing/mitkDataCollectionFromXMLTest.cpp
deleted file mode 100644
index 81e6f1b19c..0000000000
--- a/Modules/Classification/DataCollection/Testing/mitkDataCollectionFromXMLTest.cpp
+++ /dev/null
@@ -1,124 +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.
-
-============================================================================*/
-#pragma warning (disable : 4996)
-
-#include "mitkTestingMacros.h"
-#include "mitkDataCollection.h"
-#include "mitkCollectionReader.h"
-#include "mitkCollectionWriter.h"
-#include "mitkIOUtil.h"
-
-#include <vtkSmartPointer.h>
-
-int mitkDataCollectionFromXMLTest(int argc, char* argv[])
-{
- MITK_TEST_BEGIN("DataCollectionFromXML");
-
- if(argc <= 1)
- {
- MITK_ERROR << "Provide XML File to parse.";
- return -1;
- }
-
-
- std::vector<std::string> list;
- std::vector<std::string> refSuffix;
- std::vector<std::string> seriesNames;
- list.push_back("_T2_reg.nrrd");
- list.push_back("_T1_reg.nrrd");
- //list.push_back("_gtv_reg.nrrd");
- list.push_back("_reg.dwi");
-
- refSuffix.push_back("_T2.nrrd");
- refSuffix.push_back("_T1.nrrd");
- refSuffix.push_back("_DWI.dwi");
- refSuffix.push_back("_GTV.nrrd");
- //list.push_back("_ne_reg.nrrd");
- //list.push_back("_ce_reg.nrrd");
-
- seriesNames.push_back("T2");
- seriesNames.push_back("T1");
- //seriesNames.push_back("NE");
- //seriesNames.push_back("CE");
- seriesNames.push_back("DWI");
- seriesNames.push_back("GTV");
-
- // GTV has to go last -> TARGET
- mitk::CollectionWriter::SingleFolderToXml(argv[1],argv[2], refSuffix,seriesNames,true,0,0);
-
-return 0;
-mitk::CollectionWriter::FolderToXml("/home/cweber/SSD-Data/Features/Frychel_Jadwiga", "2010-10-07", "/tmp/", list,seriesNames);
-
- mitk::CollectionReader colReader;
- mitk::DataCollection::Pointer collection = colReader.LoadCollection(argv[1]);
-
-
-
- MITK_TEST_CONDITION_REQUIRED(
- collection->Size() == 2
- , "01) Size of Container is " << collection->Size() << " should be 2" );
-
-
- mitk::DataCollection* patientCol = dynamic_cast<mitk::DataCollection*> (collection->GetData("Patient2").GetPointer());
-
- MITK_TEST_CONDITION_REQUIRED(
- patientCol != nullptr
- , "02) Check if Collection: Patient2 is found" );
-
-
- MITK_TEST_CONDITION_REQUIRED(
- patientCol->GetData("TimeStep0").IsNotNull()
- , "03) Check if Patient2 contains TimeStep0" );
-
-
- mitk::DataCollection* timeStep = dynamic_cast<mitk::DataCollection*> (patientCol->GetData("TimeStep0").GetPointer());
-
- mitk::Image* image = dynamic_cast<mitk::Image*> (timeStep->GetData("T2").GetPointer());
-
-
- MITK_TEST_CONDITION_REQUIRED(
- image != nullptr
- , "04) Check if T2 image can be extracted");
-
-
- // Try saving image to disk to ensure it is a valid object
- mitk::IOUtil::Save(image, "/tmp/dump.nrrd");
-
-
- std::vector<std::string> colIds;
- colIds.push_back("patient2ID");
- colReader.AddSubColIds(colIds);
-
- collection = colReader.LoadCollection(argv[1]);
-
- MITK_TEST_CONDITION_REQUIRED(
- collection->Size() == 1
- , "05) Partial Read: Size of Container is " << collection->Size() << " should be 1" );
-
-
- colReader.ClearSubColIds();
-
- colIds.push_back("oma");
- colReader.AddSubColIds(colIds);
-
- collection = colReader.LoadCollection(argv[1]);
-
- MITK_TEST_CONDITION_REQUIRED(
- collection->Size() == 2
- , "06) Partial Read: Size of Container is " << collection->Size() << " should be 2 again" );
-
- std::vector<std::string> filter;
- filter.push_back("GTV");
- mitk::CollectionWriter::ExportCollectionToFolder(collection, "/tmp/test.xml", filter);
-
- MITK_TEST_END();
-}
diff --git a/Modules/Classification/DataCollection/Testing/mitkDataCollectionImageIteratorTest.cpp b/Modules/Classification/DataCollection/Testing/mitkDataCollectionImageIteratorTest.cpp
deleted file mode 100644
index b599a14383..0000000000
--- a/Modules/Classification/DataCollection/Testing/mitkDataCollectionImageIteratorTest.cpp
+++ /dev/null
@@ -1,162 +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 <itkImageFileWriter.h>
-#include <mitkCollectionWriter.h>
-#include <mitkTestingMacros.h>
-
-#include <mitkDataCollection.h>
-#include <mitkDataCollectionImageIterator.h>
-#include <mitkDataCollectionSingleImageIterator.h>
-
-#include <mitkImageGenerator.h>
-#include <mitkImageCast.h>
-#include <mitkImagePixelReadAccessor.h>
-#include <mitkImageToItk.h>
-#include <mitkIOUtil.h>
-
-#include "mitkNumericTypes.h"
-class mitkDataCollectionTestClass
-{
-private:
- mitk::Image::Pointer im1;
- mitk::Image::Pointer im2;
- mitk::Image::Pointer im3;
- mitk::Image::Pointer im4;
-
- mitk::DataCollection::Pointer dataCol1;
- mitk::DataCollection::Pointer dataCol2;
-
- mitk::DataCollection::Pointer col1;
-
-
-public:
- mitk::DataCollection::Pointer m_Collection;
-
-
- void Init()
- {
-
- im1 = mitk::ImageGenerator::GenerateRandomImage<double>(2,2,2,1,2,2,2,1,0);
- im2 = mitk::ImageGenerator::GenerateRandomImage<double>(3,3,3,1,3,3,3,3,2);
- im3 = mitk::ImageGenerator::GenerateRandomImage<double>(4,4,4,1,4,4,4,5,4);
- im4 = mitk::ImageGenerator::GenerateRandomImage<double>(5,5,5,1,5,5,5,7,6);
-
- dataCol1 = mitk::DataCollection::New();
- dataCol2 = mitk::DataCollection::New();
-
- dataCol1->AddData(im1.GetPointer(),"T1");
-
- dataCol1->AddData(im2.GetPointer(),"T2");
-
- dataCol2->AddData(im3.GetPointer(),"T1");
- dataCol2->AddData(im4.GetPointer(),"T2");
-
- col1 = mitk::DataCollection::New();
-
- col1->SetName("GnaBla");
- col1->AddData(dataCol1.GetPointer(), "0001");
- col1->AddData(dataCol2.GetPointer(), "0002");
-
- m_Collection = mitk::DataCollection::New();
-
- m_Collection->SetName("DummyCollection");
- m_Collection->AddData(col1.GetPointer(), "C1");
-
-
- }
-
- void IteratorReachesEnd()
- {
- Init();
- mitk::DataCollectionSingleImageIterator<double, 3> iter(m_Collection, "T1");
- int count = 0;
- while ( ! iter.IsAtEnd())
- {
- ++iter;
- ++count;
- }
- MITK_TEST_CONDITION_REQUIRED(count == 2, "Number of Iterations match number of elements");
- }
-
- void IteratorGivesRightFirstImage()
- {
- Init();
- mitk::DataCollectionSingleImageIterator<double, 3> iter(m_Collection, "T1");
-
- int spacing = iter.GetImage()->GetSpacing()[0];
-
- MITK_INFO << "Spacing: " << spacing;
- MITK_TEST_CONDITION_REQUIRED(spacing == 2, "Image is the first image (Checked by Spacing)");
- }
-
- void IteratorGivesRightSecondImage()
- {
- Init();
- mitk::DataCollectionSingleImageIterator<double, 3> iter(m_Collection, "T1");
- ++iter;
-
- int spacing = iter.GetImage()->GetSpacing()[0];
- MITK_INFO << "Spacing: " << spacing;
- MITK_TEST_CONDITION_REQUIRED(spacing == 4, "Image is the second image (Checked by Spacing)");
- }
-
- void AddingImageAtFirstPositionIsPossible()
- {
- Init();
- mitk::DataCollectionSingleImageIterator<double, 3> iter(m_Collection, "T1");
-
- mitk::Image::Pointer im = mitk::ImageGenerator::GenerateRandomImage<double>(6,6,6,1,6,6,6,9,8);
- itk::Image<double, 3>::Pointer itkImage;
- mitk::CastToItkImage(im,itkImage);
- iter.AddImage(itkImage,"T3");
-
- itk::DataObject::Pointer obj = (dynamic_cast<mitk::DataCollection*> (col1->GetData("0001").GetPointer()))->GetData("T3");
- int spacing = dynamic_cast<itk::Image<double, 3> *> (obj.GetPointer())->GetSpacing()[0];
-// MITK_INFO << "Spacing: " << spacing;
- MITK_TEST_CONDITION_REQUIRED(spacing == 6, "Image is the first image (Checked by Spacing)");
- }
-
- void AddingImageAtSecondPositionIsPossible()
- {
- Init();
- mitk::DataCollectionSingleImageIterator<double, 3> iter(m_Collection, "T1");
- ++iter;
-
- mitk::Image::Pointer im = mitk::ImageGenerator::GenerateRandomImage<double>(6,6,6,1,6,6,6,9,8);
- itk::Image<double, 3>::Pointer itkImage;
- mitk::CastToItkImage(im,itkImage);
- iter.AddImage(itkImage,"T3");
-
- itk::DataObject::Pointer obj = (dynamic_cast<mitk::DataCollection*> (col1->GetData("0002").GetPointer()))->GetData("T3");
- int spacing = dynamic_cast<itk::Image<double, 3> *> (obj.GetPointer())->GetSpacing()[0];
-// MITK_INFO << "Spacing: " << spacing;
- MITK_TEST_CONDITION_REQUIRED(spacing == 6, "Image is the first image (Checked by Spacing)");
- }
-
-};
-
-int mitkDataCollectionImageIteratorTest(int, char* [])
-{
- MITK_TEST_BEGIN("mitkDataCollectionImageIteratorTest");
-
-//MITK_TEST_CONDITION_REQUIRED(true,"Here we test our condition");
- mitkDataCollectionTestClass test;
-
- test.IteratorReachesEnd();
- test.IteratorGivesRightFirstImage();
- //test.IteratorGivesRightSecondImage(); // TODO: activate this test again as soon as bug 18365 is fixed.
- test.AddingImageAtFirstPositionIsPossible();
- test.AddingImageAtSecondPositionIsPossible();
-
- MITK_TEST_END();
-}
diff --git a/Modules/Classification/DataCollection/Testing/mitkDataCollectionTest.cpp b/Modules/Classification/DataCollection/Testing/mitkDataCollectionTest.cpp
deleted file mode 100644
index f61220aafd..0000000000
--- a/Modules/Classification/DataCollection/Testing/mitkDataCollectionTest.cpp
+++ /dev/null
@@ -1,134 +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 <mitkTestingMacros.h>
-
-#include <mitkDataCollection.h>
-#include <mitkDataCollectionImageIterator.h>
-
-#include <mitkImageGenerator.h>
-#include <mitkImageCast.h>
-#include <mitkIOUtil.h>
-
-class mitkDataCollectionTestClass
-{
-public:
- mitk::DataCollection::Pointer Fill_DataCollection()
- {
- mitk::DataCollection::Pointer col = mitk::DataCollection::New();
- mitk::Image::Pointer image1 = mitk::ImageGenerator::GenerateGradientImage<float>(10,5,8);
- mitk::IOUtil::Save(image1, "d:\\tmp\\test.nrrd");
- typedef itk::Image<float, 3> ImageType;
- ImageType::Pointer iImage1;
- mitk::CastToItkImage(image1, iImage1);
- col->AddData(iImage1.GetPointer(), "t1","description");
- mitk::Image::Pointer image2 = mitk::ImageGenerator::GenerateGradientImage<float>(10,5,8);
- ImageType::Pointer iImage2;
- mitk::CastToItkImage(image2, iImage2);
- col->AddData(iImage2.GetPointer(), "t2","description");
- mitk::Image::Pointer image3 = mitk::ImageGenerator::GenerateGradientImage<float>(10,5,8);
- ImageType::Pointer iImage3;
- mitk::CastToItkImage(image3, iImage3);
- col->AddData(iImage2.GetPointer(), "t3","description");
- return col;
- };
-
-
-/* void Count_EmptyCollection_0()
- {
- mitk::mitkDataCollectionTestClass collection;
- MITK_TEST_CONDITION_REQUIRED(collection.Count()==0, "Count should return 0");
- }
-
- void Count_With3ImagesInCollection_AsPrecalculated()
- {
- mitk::Image::Pointer image1 = mitk::ImageGenerator::GenerateRandomImage<float>(10,5,8);
- mitk::Image::Pointer image2 = mitk::ImageGenerator::GenerateRandomImage<float>(30,20,5);
- mitk::Image::Pointer image3 = mitk::ImageGenerator::GenerateRandomImage<float>(7,5,1);
-
- mitk::ImageDataCollections collection;
- collection.SetNumberOfModalities(1);
- collection.SetNumberOfSets(3);
- collection.AddImage(0,0,image1);
- collection.AddImage(1,0,image2);
- collection.AddImage(2,0,image3);
-
- MITK_INFO << collection.Count();
- MITK_TEST_CONDITION_REQUIRED(collection.Count()==3435, "Count should be 3435");
- }
-
- void GetDataPoint_InImage_Possible()
- {
- mitk::Image::Pointer image1 = mitk::ImageGenerator::GenerateGradientImage<float>(10,5,8);
- mitk::ImageDataCollections coll;
- coll.SetNumberOfModalities(1);
- coll.SetNumberOfSets(1);
- coll.AddImage(0,0,image1);
- for (int i=0;i<60;i++)
- MITK_INFO << i << ": " << coll.GetDataPoint(i,0);
- mitk::IOUtil::Save(image1,"d:\\tmp\\testbld.nrrd");
- }*/
-};
-
-int mitkDataCollectionTest(int argc, char* argv[])
-{
- MITK_TEST_BEGIN("mitkDataCollectionTest")
-
- mitkDataCollectionTestClass test;
-
- mitk::DataCollection::Pointer col = test.Fill_DataCollection();
- mitk::DataCollectionImageIterator<float, 3> iter(col, "t1");
- while (!iter.IsAtEnd())
- {
- MITK_INFO << iter.GetIndex() << " -- " << iter.GetVoxel();
- ++iter;
- }
-
- int value = 400;
- iter.ToBegin();
- while (!iter.IsAtEnd())
- {
- iter.SetVoxel(value);
- ++iter;
- --value;
- }
-
- iter.ToBegin();
- while (!iter.IsAtEnd())
- {
- MITK_INFO << iter.GetIndex() << " -- " << iter.GetVoxel();
- ++iter;
- }
-
-
- mitk::DataCollection::Pointer col2 = test.Fill_DataCollection();
-
- mitk::DataCollection::Pointer col3 = mitk::DataCollection::New();
- col->SetName("Eins");
- col2->SetName("Zwei");
- col3->SetName("Drei");
- col3->AddData(col.GetPointer(),"one","desc1");
- col3->AddData(col2.GetPointer(),"two","desc2");
-
- mitk::DataCollectionImageIterator<float, 3> iter2(col3, "t1");
- int count = 0;
- while (!iter2.IsAtEnd())
- {
- MITK_INFO << iter2.GetIndex() << " -- " << iter2.GetVoxel();
- ++iter2;
- ++count;
- }
- MITK_INFO << "Blub" << count;
-
- MITK_TEST_CONDITION_REQUIRED(true, "Message");
- MITK_TEST_END();
-}
diff --git a/Modules/Classification/DataCollection/Testing/mitkGenerateFeatureVectFromImageTest.cpp b/Modules/Classification/DataCollection/Testing/mitkGenerateFeatureVectFromImageTest.cpp
deleted file mode 100644
index e152cac64d..0000000000
--- a/Modules/Classification/DataCollection/Testing/mitkGenerateFeatureVectFromImageTest.cpp
+++ /dev/null
@@ -1,151 +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 <mitkStandaloneDataStorage.h>
-#include <mitkIOUtil.h>
-#include <mitkClassification.h>
-//#include <mitkOpenCVToMitkImageFilter.h>
-#include <itkImageFileReader.h>
-#include <itkImageFileWriter.h>
-#include <itkFlipImageFilter.h>
-#include "itkImageDuplicator.h"
-
-#include <opencv2/contrib/contrib.hpp>
-#include <opencv2/core/core.hpp>
-#include <opencv2/highgui/highgui.hpp>
-
-// 2D Image
-//#define filename "D:\\gray.jpg"
-//#define VDimension 2
-
-// 3D Image
-//#define filename "D:\\pic3d.nrrd"
-#define VDimension 3
-
-int mitkGenerateFeatureVectFromImageTest(int argc, char* argv[])
-{
- typedef unsigned char PixelType;
- typedef itk::Image< PixelType,VDimension > ImageType;
- typedef ImageType::Pointer ImageTypePtr;
- typedef itk::ImageDuplicator< ImageType > DuplicatorType;
-
- typedef itk::ImageFileReader< ImageType> ReaderType;
- typedef itk::ImageFileWriter< ImageType> WriterType;
-
- if(argc < 3)
- {
- MITK_INFO << "Please specify number of features per Voxel per Input (MUST BE IMPLEMENTED) and at least one input image" << std::endl;
- MITK_INFO << " Usage: 1 d:\\pic3d.nrrd [d:\\pic3d.nrrd] .." << std::endl;
- return -1;
- }
-
- int k = atoi(argv[1]);
-
- std::vector<std::string> inputFile;
-
- for(int i = 2; i < argc; i++)
- {
- inputFile.push_back(argv[i]);
- }
-
- ReaderType::Pointer reader = ReaderType::New();
- WriterType::Pointer writer = WriterType::New();
-
- std::vector<ImageTypePtr> inputImages;
- DuplicatorType::Pointer duplicator = DuplicatorType::New();
-
- for(int i = 0; i< inputFile.size(); i++)
- {
- reader->SetFileName(inputFile.at(i));
- reader->Update();
-
- duplicator->SetInputImage(reader->GetOutput());
- duplicator->Update();
- inputImages.push_back(duplicator->GetOutput());
- }
-
- mitk::mitkClassificationFeatureVectCreator<PixelType,VDimension>::Pointer featureVectCreator = mitk::mitkClassificationFeatureVectCreator<PixelType,VDimension>::New();
-
- // SET NUMBER OF FeaturesProperly
- featureVectCreator->SetNumberOfFeaturesPerVoxel(k);
-
- for(int i = 0; i < inputImages.size(); i++)
- {
- featureVectCreator->SetNthInput(i,inputImages.at(i));
- }
-
- featureVectCreator->Update();
-
- std::cout << "Number of Inputs: " << featureVectCreator->GetNumberOfInputs() << std::endl;
-
- cv::Mat output = featureVectCreator->GetOuputCv();
-
- float f1 = output.at<float>(0,0);
- float f2 = output.at<float>(0,1);
-
- MITK_INFO << "OutputVector :" << std::endl << output << std::endl;
-
- cv::waitKey();
-
- //// Test with 2D Image for "visual" verification
- //if(VDimension == 2)
- //{
- // ImageTypePtr image = inputImages.at(0);
-
- // unsigned int width;
- // unsigned int height;
- // unsigned int x,y;
-
- // width = image->GetLargestPossibleRegion().GetSize(0);
- // height = 2* image->GetLargestPossibleRegion().GetSize(1);
-
- // cv::Mat testImage(height,width, CV_8UC1);
- // cv::Mat testImage2(height,width, CV_8UC1);
- // cv::Mat testImage3(height,width, CV_8UC1);
-
- // unsigned int index = 0;
-
- // for( index = 0; index < width*height ; index++)
- // {
- // x = (int) index % (width);
- // float d = index / (width);
- // y = (int) floor( d);
-
- // unsigned char value;
- // float val = output.at<float>(index,0);
- // value = (unsigned char) val;
- // testImage.at<unsigned char>(y,x)= value;
-
- // if(featureVectCreator->GetIsGenerateResponseEnabled() == false)
-
- // {
- // value = (unsigned char) output.at<float>(index,1);
- // testImage2.at<unsigned char>(y,x)= value;
-
- // value = (unsigned char) output.at<float>(index,2);
- // testImage3.at<unsigned char>(y,x)= value;
- // }
- // }
-
- // cv::imshow("testImage1", testImage);
- // cv::imshow("testImage2", testImage2);
- // cv::imshow("testImage3", testImage3);
- // cv::waitKey();
-
- //}
-
- //if(VDimension == 3)
- //{
- // }
-
- return 0;
-}
diff --git a/Modules/Classification/DataCollection/Testing/mitkSherwoodTest.cpp b/Modules/Classification/DataCollection/Testing/mitkSherwoodTest.cpp
deleted file mode 100644
index f587133fd1..0000000000
--- a/Modules/Classification/DataCollection/Testing/mitkSherwoodTest.cpp
+++ /dev/null
@@ -1,265 +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 <mitkTestingMacros.h>
-#include <mitkImageDataCollections.h>
-#include <mitkImageGenerator.h>
-#include <mitkImageDataCollections.h>
-#include <mitkSWFeatureResponse.h>
-#include <mitkSWTrainingContext.h>
-
-#include <mitkSWForestExample.h>
-
-#include <itkFeatureImageFilter.h>
-
-#include <Forest.h>
-#include <ForestTrainer.h>
-#include <StatisticsAggregators.h>
-#include <TrainingParameters.h>
-#include <mitkIOUtil.h>
-#include <iostream>
-#include <sstream>
-
-#include <mitkSWForest.h>
-#include <mitkParallelForestTrainer.h>
-
-#include <itkSWHistogramToImageFilter.h>
-
-
-class mitkSherwoodTestClass
-{
-public:
- std::unique_ptr< mitk::SWForest > m_Forest;
- mitk::ImageDataCollections m_TrainingData;
- mitk::ImageDataCollections m_TestData;
-
- unsigned int m_NumberOfSets;
- unsigned int m_NumberOfModalities;
- unsigned int m_Trees;
- std::vector<std::string> m_TrainingDataPaths;
- std::vector<std::string> m_TestDataPaths;
-
- void LoadForest(std::string path)
- {
- m_Forest = mitk::SWForest::ReadFromFile(path);
- }
-
- void SaveForest(std::string path)
- {
- m_Forest->PrintToFile(path);
- }
-
- void GenerateTrainingData()
- {
- m_TrainingData.SetNumberOfSets(m_NumberOfSets);
- m_TrainingData.SetNumberOfModalities(m_NumberOfModalities);
- for (int set = 0; set < m_NumberOfSets; ++set)
- {
- for (int modality = 0; modality < m_NumberOfModalities; ++modality)
- {
- mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage<float>(5,5,5);
- m_TrainingData.AddImage(set,modality, image);
- }
- }
- }
-
- void TrainForest()
- {
- mitk::SWRandom random;
-
- // Definde Training parameters0
- mitk::SWTrainingParameters parameters;
- parameters.NumberOfTrees = m_Trees;
- parameters.NumberOfCandidateFeatures = 10;
- parameters.NumberOfCandidateThresholdsPerFeature = 200;
- parameters.MaxDecisionLevels = 19;
- parameters.Verbose = false;
-
- //
- mitk::SWTrainingContext trainingContext;
- trainingContext.SetClasses(4);
- trainingContext.SetModalities(m_TrainingData.GetNumberOfModalities());
-
- mitk::SWHistogramAggregator hist = trainingContext.GetStatisticsAggregator();
- for (int i = 0; i < m_TrainingData.Count(); ++i)
- {
- if (m_TrainingData.IsLabeled(i))
- {
- hist.Aggregate(m_TrainingData, i);
- }
- }
- trainingContext.SetStatistic(hist);
- mitk::SWForestTrainer forestTrainer;
- mitk::ParallelForestTrainer<mitk::ImageDataCollections, mitk::SWFeatureContainer,mitk::SWHistogramAggregator> trainer;
-
- trainer.SetTreeNumber(parameters.NumberOfTrees);
-
- m_Forest = trainer.TrainForest (random, parameters, trainingContext, m_TrainingData);
- }
-
- void ApplyForest(std::string labelPath, std::string probPath)
- {
- typedef itk::Image<unsigned char, 3> LabelImageType;
- typedef itk::Image<float, 3> PropImageType;
-
- typedef itk::SWHistogramToImageFilter<LabelImageType, PropImageType> FilterType;
- FilterType::Pointer filter = FilterType::New();
- filter->SetForest(m_Forest);
- filter->SetCollection(m_TestData);
- filter->SetSet(0);
- filter->Update();
- LabelImageType::Pointer labelImage = filter->GetLabelImage();
- PropImageType::Pointer propImage = filter->GetPropabilityImage();
-
- mitk::Image::Pointer mLabelImage = mitk::Image::New();
- mitk::Image::Pointer mPropImage = mitk::Image::New();
- mitk::CastToMitkImage(labelImage, mLabelImage);
- mitk::CastToMitkImage(propImage, mPropImage);
-
- mitk::IOUtil::Save(mLabelImage, labelPath);
- mitk::IOUtil::Save(mPropImage, probPath);
- }
-
-
-
- void ParseCommandline(int argc, char* argv[])
- {
- m_TrainingDataPaths.clear();
- m_TestDataPaths.clear();
- for (int i = 0; i < argc; i++)
- {
- if ((std::string(argv[i]) == "--trees" || std::string(argv[i]) == "-t") && i < argc-1)
- {
- MITK_INFO << "trees";
- m_Trees = atoi(argv[i+1]);
- i++;
- }
- if ((std::string(argv[i]) == "--sets" || std::string(argv[i]) == "-s") && i < argc-1)
- {
- MITK_INFO << "sets";
- m_NumberOfSets = atoi(argv[i+1]);
- i++;
- }
- if ((std::string(argv[i]) == "--modalities" || std::string(argv[i]) == "-m") && i < argc-1)
- {
- MITK_INFO << "modalities";
- m_NumberOfModalities = atoi(argv[i+1]);
- i++;
- }
- if (std::string(argv[i]) == "--generate-training-data")
- {
- MITK_INFO << "generate-training-data";
- this->GenerateTrainingData();
- }
- if (std::string(argv[i]) == "--test-equal-training" || (std::string(argv[i]) == "-tet"))
- {
- MITK_INFO << "test-equal-training";
- m_TestData = m_TrainingData;
- }
- if ((std::string(argv[i]) == "--read-forest" || std::string(argv[i]) == "-r") && i < argc-1)
- {
- MITK_INFO << "read-forest";
- this->LoadForest(argv[i+1]);
- i++;
- }
- if ((std::string(argv[i]) == "--save-forest" || std::string(argv[i]) == "-s") && i < argc-1)
- {
- MITK_INFO << "save-forest";
- this->SaveForest(argv[i+1]);
- i++;
- }
- if (std::string(argv[i]) == "--train")
- {
- MITK_INFO << "train";
- m_TrainingData.GetDataPoint(0,0);
- this->TrainForest();
- }
- if (std::string(argv[i]) == "--apply" && i < argc-2)
- {
- MITK_INFO << "apply";
- this->ApplyForest(argv[i+1],argv[i+2]);
- i++;i++;
- }
- if (std::string(argv[i]) == "--testdata")
- {
- MITK_INFO << "testdata";
- m_TestData.SetNumberOfSets(m_NumberOfSets);
- m_TestData.SetNumberOfModalities(m_NumberOfModalities);
- for (int set = 0; set < 1; ++set)
- {
- for (int modality = 0; modality < m_NumberOfModalities; ++modality)
- {
- ++i;
- if ( i >= argc || argv[i][0] == '-')
- break;
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(argv[i]);
- m_TestData.AddImage(set,modality, image);
- }
- if ( i >= argc || argv[i][0] == '-')
- break;
- }
- }
- if (std::string(argv[i]) == "--traindata")
- {
- MITK_INFO << "traindata";
- m_TrainingData.SetNumberOfSets(m_NumberOfSets);
- m_TrainingData.SetNumberOfModalities(m_NumberOfModalities);
- for (int set = 0; set < m_NumberOfSets; ++set)
- {
- for (int modality = 0; modality < m_NumberOfModalities; ++modality)
- {
- ++i;
- if ( i >= argc || argv[i][0] == '-')
- break;
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(argv[i]);
- m_TrainingData.AddImage(set,modality, image);
- }
- ++i;
- if ( i >= argc || argv[i][0] == '-')
- break;
- mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(argv[i]);
- m_TrainingData.SetLabelImage(set, image);
- }
- }
- }
- }
-};
-
-
-int mitkSherwoodTest(int argc, char* argv[])
-{
- MITK_TEST_BEGIN("mitkSherwoodTest");
-
- mitkSherwoodTestClass test;
- test.ParseCommandline(argc,argv);
-
-
- // Basically to test features
- bool btest = false;
- if (btest)
- {
- typedef itk::Image<float, 3> ImageType;
- typedef itk::FeatureImageFilter<ImageType, ImageType> Zikic1FilterType;
-
- Zikic1FilterType::Pointer zikic1 = Zikic1FilterType::New();
- }
-
-
-
-
-
- MITK_TEST_CONDITION_REQUIRED(true, "Message");
- MITK_TEST_END();
- MITK_INFO << "Press Key and Enter to leave test";
- char ch;
- std::cin >> ch;
-}
diff --git a/Modules/Classification/DataCollection/Testing/textCollection.xml b/Modules/Classification/DataCollection/Testing/textCollection.xml
deleted file mode 100644
index 11857320ec..0000000000
--- a/Modules/Classification/DataCollection/Testing/textCollection.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<col name="TestCollection">
- <subcol name="Patient1" description="dummyShit" id="oma">
- <data name="TimeStep1" description="BeforeOp" id="opa">
- <item name="T2" link="/home/cweber/E011-Projekte/Glioma/high_grade_data_20_cases/Ciwis_Damian/PROCESSED-001/CiwisDamian_20100812_T2_reg.nrrd" />
- <item name="DWI" link="/home/cweber/E011-Projekte/Glioma/high_grade_data_20_cases/Ciwis_Damian/PROCESSED-001/CiwisDamian_20100812_reg.dwi" />
- <item name="GTV" link="/home/cweber/E011-Projekte/Glioma/high_grade_data_20_cases/Ciwis_Damian/PROCESSED-001/CiwisDamian_20100812_gtv_reg.nrrd" />
- </data>
- <data name="TimeStep2" description="PostOP" id="1">
- <item name="T2" link="/home/cweber/E011-Projekte/Glioma/high_grade_data_20_cases/Ciwis_Damian/PROCESSED-001/CiwisDamian_20100812_T2_reg.nrrd" />
- <item name="GTV" link="/home/cweber/E011-Projekte/Glioma/high_grade_data_20_cases/Ciwis_Damian/PROCESSED-001/CiwisDamian_20100812_gtv_reg.nrrd" />
- </data>
- </subcol>
- <subcol name="Patient2" description="dummyShit" id="patient2ID">
- <data name="TimeStep0" description="BeforeOp" id="2">
- <item name="T2" link="/home/cweber/E011-Projekte/Glioma/high_grade_data_20_cases/Ciwis_Damian/PROCESSED-001/CiwisDamian_20100909_T2_reg.nrrd" />
- </data>
- </subcol>
-</col>
diff --git a/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.cpp b/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.cpp
deleted file mode 100644
index d283baa433..0000000000
--- a/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.cpp
+++ /dev/null
@@ -1,512 +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 <mitkCollectionStatistic.h>
-#include <mitkDataCollection.h>
-
-// DataCollection Stuff
-#include <mitkDataCollectionImageIterator.h>
-//stl stuff
-#include <sstream>
-
-#include <itkShapedNeighborhoodIterator.h>
-#include <itkSignedDanielssonDistanceMapImageFilter.h>
-
-
-mitk::CollectionStatistic::CollectionStatistic()
- : m_GroundTruthValueToIndexMapper(nullptr)
- , m_TestValueToIndexMapper(nullptr)
-{
-
-}
-
-mitk::CollectionStatistic::~CollectionStatistic()
-{
- m_GroundTruthValueToIndexMapper = nullptr;
- m_TestValueToIndexMapper = nullptr;
-}
-
-
-void mitk::CollectionStatistic::SetCollection(mitk::DataCollection::Pointer collection)
-{
- m_Collection = collection;
-}
-
-mitk::DataCollection::Pointer mitk::CollectionStatistic::GetCollection()
-{
- return m_Collection;
-}
-
-void mitk::CollectionStatistic::SetClassCount (size_t count)
-{
- m_ClassCount = count;
-}
-
-size_t mitk::CollectionStatistic::GetClassCount()
-{
- return m_ClassCount;
-}
-
-void mitk::CollectionStatistic::SetGoldName(std::string name)
-{
- m_GroundTruthName = name;
-}
-
-std::string mitk::CollectionStatistic::GetGoldName()
-{
- return m_GroundTruthName;
-}
-
-void mitk::CollectionStatistic::SetTestName(std::string name)
-{
- m_TestName = name;
-}
-
-std::string mitk::CollectionStatistic::GetTestName()
-{
- return m_TestName;
-}
-
-void mitk::CollectionStatistic::SetGroundTruthValueToIndexMapper(const ValueToIndexMapper* mapper)
-{
- m_GroundTruthValueToIndexMapper = mapper;
-}
-
-const mitk::ValueToIndexMapper* mitk::CollectionStatistic::GetGroundTruthValueToIndexMapper(void) const
-{
- return m_GroundTruthValueToIndexMapper;
-}
-
-void mitk::CollectionStatistic::SetTestValueToIndexMapper(const ValueToIndexMapper* mapper)
-{
- m_TestValueToIndexMapper = mapper;
-}
-
-const mitk::ValueToIndexMapper* mitk::CollectionStatistic::GetTestValueToIndexMapper(void) const
-{
- return m_TestValueToIndexMapper;
-}
-
-int mitk::CollectionStatistic::IsInSameVirtualClass(unsigned char gold, unsigned char test)
-{
- int resultClass = -1;
- for (std::size_t i = 0; i < m_ConnectionGold.size(); ++i)
- {
- if (m_ConnectionGold[i] == gold && m_ConnectionTest[i] == test)
- {
- resultClass = m_ConnectionClass[i];
- break;
- }
- }
- return resultClass;
-}
-
-bool mitk::CollectionStatistic::Update()
-{
- if (m_GroundTruthValueToIndexMapper == nullptr)
- {
- MITK_ERROR << "m_GroundTruthValueToIndexMapper is nullptr";
- return false;
- }
-
- if (m_TestValueToIndexMapper == nullptr)
- {
- MITK_ERROR << "m_TestValueToIndexMapper is nullptr";
- return false;
- }
-
- DataCollectionImageIterator<unsigned char, 3> goldIter(m_Collection, m_GroundTruthName);
- DataCollectionImageIterator<unsigned char, 3> testIter(m_Collection, m_TestName);
- DataCollectionImageIterator<unsigned char, 3> maskIter(m_Collection, m_MaskName);
-
- int index = 0;
-
- while (!goldIter.IsAtEnd())
- {
- std::size_t imageIndex = goldIter.GetImageIndex();
- if (m_ImageClassStatistic.size() <= imageIndex)
- {
- MITK_INFO << "New Image: " << goldIter.GetFilePrefix();
- m_ImageNames.push_back(goldIter.GetFilePrefix());
- StatisticData statData;
- m_ImageStatistic.push_back(statData);
- DataVector data;
- for (std::size_t i = 0; i < m_ClassCount; ++i)
- {
- StatisticData stat;
- data.push_back(stat);
- }
- m_ImageClassStatistic.push_back(data);
- }
-
- if (maskIter.GetVoxel() <= 0)
- {
- ++goldIter;
- ++testIter;
- ++maskIter;
- continue;
- }
-
- ++index;
- unsigned char goldClass = m_GroundTruthValueToIndexMapper->operator()(goldIter.GetVoxel());
- unsigned char testClass = m_TestValueToIndexMapper->operator()(testIter.GetVoxel());
- if (goldClass == testClass) // True Positive
- {
- m_ImageStatistic[imageIndex].m_TruePositive += 1;
- for (std::size_t i = 0; i < m_ClassCount; ++i)
- {
- if (goldClass == i) // For the detected class it is a true positive
- {
- m_ImageClassStatistic[imageIndex][i].m_TruePositive += 1;
- } else // for all other classes than the detected it is a true negative
- {
- m_ImageClassStatistic[imageIndex][i].m_TrueNegative += 1;
- }
- }
- } else // No True Positive
- {
- m_ImageStatistic[imageIndex].m_FalseNegative += 1;
- m_ImageStatistic[imageIndex].m_FalsePositive += 1;
- for (std::size_t i = 0; i < m_ClassCount; ++i)
- {
- if (goldClass == i) // For the class in Goldstandard it is a false negative
- {
- m_ImageClassStatistic[imageIndex][i].m_FalseNegative += 1;
- } else if ( testClass == i) // For the test class it is a false positive
- {
- m_ImageClassStatistic[imageIndex][i].m_FalsePositive += 1;
- } else // For all other it is a true negative
- {
- m_ImageClassStatistic[imageIndex][i].m_TrueNegative += 1;
- }
- }
- }
-
- ++goldIter;
- ++testIter;
- ++maskIter;
- }
- MITK_INFO << "Evaluated " << index << " points";
- return true;
-}
-
-void mitk::CollectionStatistic::Print(std::ostream& out, std::ostream& sout, bool withHeader, std::string label)
-{
- assert(m_ImageClassStatistic.size() > 0);
- assert(m_ImageClassStatistic[0].size() == m_ClassCount);
-
- if (withHeader)
- {
- sout << "Label;ImageName;";
- for (std::size_t i = 0; i < m_ClassCount; ++i)
- {
- sout << "DICE-Class-"<< i << ";";
- sout << "Jaccard-Class-"<< i << ";";
- sout << "Sensitivity-Class-"<< i << ";";
- sout << "Specificity-Class-"<< i << ";";
- sout << "TP-Class-"<< i << ";";
- sout << "TN-Class-"<< i << ";";
- sout << "FP-Class-"<< i << ";";
- sout << "FN-Class-"<< i << ";";
- }
- sout << "DICE-MEAN"<< ";";
- sout << "Jaccard-MEAN"<< ";";
- sout << "Sensitivity-MEAN"<< ";";
- sout << "Specificity-MEAN"<< ";";
- sout << "TP-MEAN"<< ";";
- sout << "TN-MEAN"<< ";";
- sout << "FP-MEAN"<< ";";
- sout << "FN-MEAN"<< ";";
- sout << "DICE-WMEAN"<< ";";
- sout << "Jaccard-WMEAN"<< ";";
- sout << "Sensitivity-WMEAN"<< ";";
- sout << "Specificity-WMEAN"<< ";";
- sout << "TP-WMEAN"<< ";";
- sout << "TN-WMEAN"<< ";";
- sout << "FP-WMEAN"<< ";";
- sout << "FN-WMEAN"<< ";";
- sout << "COMPLETE-TRUE/FALSE"<< ";";
- sout << "COMPLETE-TRUES"<< ";";
- sout << "COMPLETE_FALSE"<< ";";
- sout << std::endl;
- }
- out << std::setprecision(5);
-
-
- MITK_INFO << "m_ImageClassStatistic.size(): " << m_ImageClassStatistic.size();
-
- for (std::size_t i = 0; i < m_ImageClassStatistic.size(); ++i)
- {
- sout << label << ";"<< m_ImageNames[i]<<";";
- StatisticData meanStat;
- StatisticData wMeanStat;
- double pointsSum = 0;
-
- out << "======================================================== Image " << std::setw(3) << i << " ========================================================" << std::endl;
- out << " Image ID : " << m_ImageNames[i] <<std::endl;
-
- out << "|--------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|--------------|" << std::endl;
- out << "| Class | DICE | Jaccard | Sensitivity | Specificity | TP | TN | FP | FN |" << std::endl;
- out << "|--------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|--------------|" << std::endl;
-
- for (std::size_t j =0; j < m_ImageClassStatistic[i].size(); ++j)
- {
- StatisticData& stat = m_ImageClassStatistic[i][j];
- stat.m_DICE = std::max(0.0,(2.0 * stat.m_TruePositive) / (2.0 * stat.m_TruePositive + stat.m_FalseNegative + stat.m_FalsePositive));
- stat.m_Jaccard = std::max(0.0,(1.0 * stat.m_TruePositive) / (1.0 * stat.m_TruePositive + stat.m_FalseNegative + stat.m_FalsePositive));
- stat.m_Sensitivity = std::max(0.0,(1.0 * stat.m_TruePositive) / (stat.m_TruePositive + stat.m_FalseNegative));
- stat.m_Specificity = std::max(0.0,(1.0 * stat.m_TrueNegative) / ( stat.m_FalsePositive + stat.m_TrueNegative));
-
- meanStat.m_DICE += std::max(stat.m_DICE,0.0);
- meanStat.m_Jaccard += std::max(stat.m_Jaccard,0.0);
- meanStat.m_Sensitivity += std::max(stat.m_Sensitivity,0.0);
- meanStat.m_Specificity += std::max(stat.m_Specificity,0.0);
- meanStat.m_TruePositive += stat.m_TruePositive;
- meanStat.m_TrueNegative += stat.m_TrueNegative;
- meanStat.m_FalsePositive += stat.m_FalsePositive;
- meanStat.m_FalseNegative += stat.m_FalseNegative;
-
- double points = stat.m_TruePositive + stat.m_FalseNegative;
- pointsSum += points;
-
- wMeanStat.m_DICE += std::max(stat.m_DICE,0.0) * points;
- wMeanStat.m_Jaccard += std::max(stat.m_Jaccard,0.0) * points;
- wMeanStat.m_Sensitivity += std::max(stat.m_Sensitivity,0.0) * points;
- wMeanStat.m_Specificity += std::max(stat.m_Specificity,0.0) * points;
- wMeanStat.m_TruePositive += stat.m_TruePositive;
- wMeanStat.m_TrueNegative += stat.m_TrueNegative;
- wMeanStat.m_FalsePositive += stat.m_FalsePositive;
- wMeanStat.m_FalseNegative += stat.m_FalseNegative;
-
- out<< "|" << std::setw(7) << j << " | ";
- out << std::setw(11) << stat.m_DICE << " | ";
- out << std::setw(11) << stat.m_Jaccard << " | ";
- out << std::setw(11) << stat.m_Sensitivity << " | ";
- out << std::setw(11) << stat.m_Specificity << " | ";
- out << std::setw(11) << stat.m_TruePositive << " | ";
- out << std::setw(11) << stat.m_TrueNegative<< " | ";
- out << std::setw(11) << stat.m_FalsePositive<< " | ";
- out << std::setw(11) << stat.m_FalseNegative << " |"<< std::endl;
- sout << stat.m_DICE << ";";
- sout << stat.m_Jaccard << ";";
- sout << stat.m_Sensitivity << ";";
- sout << stat.m_Specificity << ";";
- sout << stat.m_TruePositive << ";";
- sout << stat.m_TrueNegative<< ";";
- sout << stat.m_FalsePositive<< ";";
- sout << stat.m_FalseNegative << ";";
- sout << stat.m_RMSD << ";";
- }
-
- meanStat.m_DICE /= m_ImageClassStatistic[i].size();
- meanStat.m_Jaccard /= m_ImageClassStatistic[i].size();
- meanStat.m_Sensitivity /= m_ImageClassStatistic[i].size();
- meanStat.m_Specificity /= m_ImageClassStatistic[i].size();
- meanStat.m_TruePositive /= m_ImageClassStatistic[i].size();
- meanStat.m_TrueNegative /= m_ImageClassStatistic[i].size();
- meanStat.m_FalsePositive /= m_ImageClassStatistic[i].size();
- meanStat.m_FalseNegative /= m_ImageClassStatistic[i].size();
-
- out << "|--------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|--------------|" << std::endl;
- out << std::setw(7) << "| Mean "<< " | ";
- out << std::setw(11) << meanStat.m_DICE << " | ";
- out << std::setw(11) << meanStat.m_Jaccard << " | ";
- out << std::setw(11) << meanStat.m_Sensitivity << " | ";
- out << std::setw(11) << meanStat.m_Specificity << " | ";
- out << std::setw(11) << meanStat.m_TruePositive << " | ";
- out << std::setw(11) << meanStat.m_TrueNegative<< " | ";
- out << std::setw(11) << meanStat.m_FalsePositive<< " | ";
- out << std::setw(11) << meanStat.m_FalseNegative << " |"<< std::endl;
- sout << meanStat.m_DICE << ";";
- sout << meanStat.m_Jaccard << ";";
- sout << meanStat.m_Sensitivity << ";";
- sout << meanStat.m_Specificity << ";";
- sout << meanStat.m_TruePositive << ";";
- sout << meanStat.m_TrueNegative<< ";";
- sout << meanStat.m_FalsePositive<< ";";
- sout << meanStat.m_FalseNegative << ";";
-
- wMeanStat.m_DICE /= pointsSum;
- wMeanStat.m_Jaccard /= pointsSum;
- wMeanStat.m_Sensitivity /= pointsSum;
- wMeanStat.m_Specificity /= pointsSum;
- wMeanStat.m_TruePositive /= pointsSum;
- wMeanStat.m_TrueNegative /= pointsSum;
- wMeanStat.m_FalsePositive /= pointsSum;
- wMeanStat.m_FalseNegative /= pointsSum;
-
- out << std::setw(7) << "| W-Mean"<< " | ";
- out << std::setw(11) << wMeanStat.m_DICE << " | ";
- out << std::setw(11) << wMeanStat.m_Jaccard << " | ";
- out << std::setw(11) << wMeanStat.m_Sensitivity << " | ";
- out << std::setw(11) << wMeanStat.m_Specificity << " | ";
- out << std::setw(11) << wMeanStat.m_TruePositive << " | ";
- out << std::setw(11) << wMeanStat.m_TrueNegative<< " | ";
- out << std::setw(11) << wMeanStat.m_FalsePositive<< " | ";
- out << std::setw(11) << wMeanStat.m_FalseNegative << " |"<< std::endl;
- sout << wMeanStat.m_DICE << ";";
- sout << wMeanStat.m_Jaccard << ";";
- sout << wMeanStat.m_Sensitivity << ";";
- sout << wMeanStat.m_Specificity << ";";
- sout << wMeanStat.m_TruePositive << ";";
- sout << wMeanStat.m_TrueNegative<< ";";
- sout << wMeanStat.m_FalsePositive<< ";";
- sout << wMeanStat.m_FalseNegative << ";";
-
- m_ImageStatistic[i].m_Sensitivity = std::max(0.0,(1.0 * m_ImageStatistic[i].m_TruePositive) / (m_ImageStatistic[i].m_TruePositive + m_ImageStatistic[i].m_FalseNegative));
- m_ImageStatistic[i].m_Specificity = std::max(0.0,(1.0 * m_ImageStatistic[i].m_TrueNegative) / ( m_ImageStatistic[i].m_FalsePositive + m_ImageStatistic[i].m_TrueNegative));
-
- out << std::setw(7) << "| Compl."<< " | ";
- out << std::setw(11) << " x " << " | ";
- out << std::setw(11) << " x " << " | ";
- out << std::setw(11) << m_ImageStatistic[i].m_Sensitivity << " | ";
- out << std::setw(11) << " x " << " | ";
- out << std::setw(11) << m_ImageStatistic[i].m_TruePositive << " | ";
- out << std::setw(11) << m_ImageStatistic[i].m_TrueNegative<< " | ";
- out << std::setw(11) << m_ImageStatistic[i].m_FalsePositive<< " | ";
- out << std::setw(11) << m_ImageStatistic[i].m_FalseNegative << " |"<< std::endl;
- out << "|--------|-------------|-------------|-------------|-------------|-------------|-------------|-------------|--------------|" << std::endl;
-
- sout << m_ImageStatistic[i].m_Sensitivity << ";";
- sout << m_ImageStatistic[i].m_TruePositive << ";";
- sout << m_ImageStatistic[i].m_FalsePositive<< std::endl;
- out << std::endl;
- }
-}
-
-std::vector<mitk::StatisticData> mitk::CollectionStatistic::GetStatisticData(unsigned char c) const
-{
- std::vector<StatisticData> statistics;
-
- for (size_t i = 0; i < m_ImageClassStatistic.size(); i++)
- {
- statistics.push_back(m_ImageClassStatistic[i][c]);
- }
-
- return statistics;
-}
-
-void mitk::CollectionStatistic::ComputeRMSD()
-{
- assert(m_ClassCount == 2);
- assert(m_GroundTruthValueToIndexMapper != nullptr);
- assert(m_TestValueToIndexMapper != nullptr);
-
- DataCollectionImageIterator<unsigned char, 3> groundTruthIter(m_Collection, m_GroundTruthName);
- DataCollectionImageIterator<unsigned char, 3> testIter(m_Collection, m_TestName);
- DataCollectionImageIterator<unsigned char, 3> maskIter(m_Collection, m_MaskName);
-
- typedef itk::Image<unsigned char, 3> LabelImage;
- typedef itk::Image<double, 3> ImageType;
- typedef itk::SignedDanielssonDistanceMapImageFilter<LabelImage, ImageType, ImageType> DistanceMapFilterType;
- typedef itk::ConstantBoundaryCondition<LabelImage> BoundaryConditionType;
- typedef itk::ConstShapedNeighborhoodIterator<LabelImage, BoundaryConditionType> ConstNeighborhoodIteratorType;
-
- // Build up 6-neighborhood. Diagonal voxel are maybe not considered for distance map computation.
- // So 6-neighborhood avoids inconsistencies.
- ConstNeighborhoodIteratorType::OffsetType offset0 = {{ 0, 0, -1}};
- ConstNeighborhoodIteratorType::OffsetType offset1 = {{ 0, 0, 1}};
- ConstNeighborhoodIteratorType::OffsetType offset2 = {{ 0, -1, 0}};
- ConstNeighborhoodIteratorType::OffsetType offset3 = {{ 0, 1, 0}};
- ConstNeighborhoodIteratorType::OffsetType offset4 = {{-1, 0, 0}};
- ConstNeighborhoodIteratorType::OffsetType offset5 = {{ 1, 0, 0}};
-
- const int outsideVal = 17;
- itk::NeighborhoodIterator<LabelImage>::RadiusType radius;
- radius.Fill(1);
-
- BoundaryConditionType bc;
- // if a neighborhood voxel is outside of the image region a default value is returned
- bc.SetConstant(outsideVal);
-
- ConstNeighborhoodIteratorType neighborhoodIter;
-
- ImageType::Pointer distanceImage;
- std::vector<mitk::StatisticData>* currentImageStatistics = nullptr;
-
- unsigned int distanceBorderSamples = 0;
- double totalBorderRMSDistance = 0;
-
- int previousImageIndex = -1;
-
- while (!testIter.IsAtEnd())
- {
- int currentImageIndex = testIter.GetImageIndex();
-
- // prepare data for next image
- if (previousImageIndex != currentImageIndex)
- {
- previousImageIndex = currentImageIndex;
-
- currentImageStatistics = &(m_ImageClassStatistic.at(currentImageIndex));
-
- distanceBorderSamples = 0;
- totalBorderRMSDistance = 0;
-
- // generate distance map from gold standard image
- DistanceMapFilterType::Pointer distanceMapFilter = DistanceMapFilterType::New();
- distanceMapFilter->SetInput(groundTruthIter.GetImageIterator().GetImage());
- distanceMapFilter->SetUseImageSpacing(true);
- distanceMapFilter->Update();
- distanceImage = distanceMapFilter->GetOutput();
-
- neighborhoodIter = ConstNeighborhoodIteratorType(radius, testIter.GetImageIterator().GetImage(), testIter.GetImageIterator().GetImage()->GetRequestedRegion());
- neighborhoodIter.OverrideBoundaryCondition(&bc);
-
- // configure 6-neighborhood
- neighborhoodIter.ActivateOffset(offset0);
- neighborhoodIter.ActivateOffset(offset1);
- neighborhoodIter.ActivateOffset(offset2);
- neighborhoodIter.ActivateOffset(offset3);
- neighborhoodIter.ActivateOffset(offset4);
- neighborhoodIter.ActivateOffset(offset5);
- }
-
- unsigned char testClass = m_TestValueToIndexMapper->operator()(testIter.GetVoxel());
-
- if ( maskIter.GetVoxel() > 0 && testClass != 0)
- {
- // check if it is a border voxel
- neighborhoodIter.SetLocation(testIter.GetImageIterator().GetIndex());
- bool border = false;
-
- ConstNeighborhoodIteratorType::ConstIterator iter;
- for (iter = neighborhoodIter.Begin(); !iter.IsAtEnd(); iter++)
- {
- if (iter.Get() == outsideVal)
- {
- continue;
- }
-
- if (m_TestValueToIndexMapper->operator()(iter.Get()) != 1 )
- {
- border = true;
- break;
- }
- }
-
- if (border)
- {
- double currentDistance = distanceImage->GetPixel(testIter.GetImageIterator().GetIndex());
- totalBorderRMSDistance += currentDistance * currentDistance;
- ++distanceBorderSamples;
-
- // update immediately, so the final value is set after the iterator of the last image has reached the end
- double rmsd = std::sqrt(totalBorderRMSDistance / (double) distanceBorderSamples);
- currentImageStatistics->at(1).m_RMSD = rmsd;
- }
- }
- ++groundTruthIter;
- ++testIter;
- ++maskIter;
- }
-}
diff --git a/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.h b/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.h
deleted file mode 100644
index 2693eef735..0000000000
--- a/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.h
+++ /dev/null
@@ -1,158 +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.
-
-============================================================================*/
-
-#ifndef mitkCollectionStatistic_h
-#define mitkCollectionStatistic_h
-
-#include <MitkDataCollectionExports.h>
-
-#include <mitkDataCollection.h>
-
-#include <iostream>
-
-namespace mitk {
-struct MITKDATACOLLECTION_EXPORT StatisticData
-{
- unsigned int m_TruePositive;
- unsigned int m_FalsePositive;
- unsigned int m_TrueNegative;
- unsigned int m_FalseNegative;
-
- double m_DICE;
- double m_Jaccard;
- double m_Sensitivity;
- double m_Specificity;
- double m_RMSD;
-
- StatisticData() :
- m_TruePositive(0), m_FalsePositive(0), m_TrueNegative(0), m_FalseNegative(0),
- m_DICE(0), m_Jaccard(0), m_Sensitivity(0), m_Specificity(0), m_RMSD(-1.0)
- {}
-};
-
-class ValueToIndexMapper
-{
-public:
- virtual unsigned char operator() (unsigned char value) const = 0;
-};
-
-class BinaryValueminusOneToIndexMapper : public virtual ValueToIndexMapper
-{
-public:
- unsigned char operator() (unsigned char value) const override
- {
- return value-1;
- }
-};
-
-class BinaryValueToIndexMapper : public virtual ValueToIndexMapper
-{
-public:
- unsigned char operator() (unsigned char value) const override
- {
- return value;
- }
-};
-
-class MultiClassValueToIndexMapper : public virtual ValueToIndexMapper
-{
-public:
- unsigned char operator() (unsigned char value) const override
- {
- if (value == 1 || value == 5)
- return 0;
- else
- return 1;
- }
-};
-
-class ProgressionValueToIndexMapper : public virtual ValueToIndexMapper
-{
-public:
- unsigned char operator() (unsigned char value) const override
- {
- if (value == 1 || value == 0)
- return 0;
- else
- return 1;
- }
-};
-
-class MITKDATACOLLECTION_EXPORT CollectionStatistic
-{
-public:
-
- CollectionStatistic();
- ~CollectionStatistic();
-
- typedef std::vector<StatisticData> DataVector;
- typedef std::vector<DataVector> MultiDataVector;
-
- void SetCollection(DataCollection::Pointer collection);
- DataCollection::Pointer GetCollection();
-
- void SetClassCount (size_t count);
- size_t GetClassCount();
-
- void SetGoldName(std::string name);
- std::string GetGoldName();
-
- void SetTestName(std::string name);
- std::string GetTestName();
-
- void SetMaskName(std::string name) {m_MaskName = name; }
-
- void SetGroundTruthValueToIndexMapper(const ValueToIndexMapper* mapper);
- const ValueToIndexMapper* GetGroundTruthValueToIndexMapper(void) const;
-
- void SetTestValueToIndexMapper(const ValueToIndexMapper* mapper);
- const ValueToIndexMapper* GetTestValueToIndexMapper(void) const;
-
- void Print(std::ostream& out, std::ostream& sout = std::cout, bool withHeader = false, std::string label = "None");
- bool Update();
- int IsInSameVirtualClass(unsigned char gold, unsigned char test);
-
- /**
- * @brief mitk::CollectionStatistic::GetStatisticData
- * @param c The class for which to retrieve the statistic data.
- * @return
- */
- std::vector<StatisticData> GetStatisticData(unsigned char c) const;
-
- /**
- * @brief Computes root-mean-square distance of two binary images.
- */
- void ComputeRMSD();
-
-private:
- size_t m_ClassCount;
- std::string m_GroundTruthName;
- std::string m_TestName;
- std::string m_MaskName;
- DataCollection::Pointer m_Collection;
-
- std::vector<unsigned char> m_ConnectionGold;
- std::vector<unsigned char> m_ConnectionTest;
- std::vector<unsigned char> m_ConnectionClass;
-
- MultiDataVector m_ImageClassStatistic;
- std::vector<std::string> m_ImageNames;
- DataVector m_ImageStatistic;
- StatisticData m_MeanCompleteStatistic;
- StatisticData m_CompleteStatistic;
-
- const ValueToIndexMapper* m_GroundTruthValueToIndexMapper;
- const ValueToIndexMapper* m_TestValueToIndexMapper;
-};
-}
-
-#endif
diff --git a/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.cpp b/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.cpp
deleted file mode 100644
index 754db798c3..0000000000
--- a/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.cpp
+++ /dev/null
@@ -1,208 +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 <mitkCostingStatistic.h>
-#include <mitkDataCollection.h>
-
-#include <mitkCollectionStatistic.h>
-#include <sstream>
-
-// DataCollection Stuff
-#include <mitkDataCollectionImageIterator.h>
-//stl stuff
-#include <sstream>
-
-static void EnsureDataImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target)
-{
- typedef itk::Image<double, 3> FeatureImage;
- typedef itk::Image<unsigned char, 3> LabelImage;
-
- if (collection->HasElement(origin))
- {
- LabelImage::Pointer originImage = dynamic_cast<LabelImage*>(collection->GetData(origin).GetPointer());
- MITK_INFO << "Creating new Element";
- if (!collection->HasElement(target) && originImage.IsNotNull())
- {
- MITK_INFO << "New image necessary";
- FeatureImage::Pointer image = FeatureImage::New();
- image->SetRegions(originImage->GetLargestPossibleRegion());
- image->SetSpacing(originImage->GetSpacing());
- image->SetOrigin(originImage->GetOrigin());
- image->SetDirection(originImage->GetDirection());
- image->Allocate();
-
- collection->AddData(dynamic_cast<itk::DataObject*>(image.GetPointer()),target,"");
- }
- }
- for (std::size_t i = 0; i < collection->Size();++i)
- {
- mitk::DataCollection* newCol = dynamic_cast<mitk::DataCollection*>(collection->GetData(i).GetPointer());
- if (newCol != nullptr)
- {
- EnsureDataImageInCollection(newCol, origin, target);
- }
- }
-}
-
-static void EnsureLabelImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target)
-{
- typedef itk::Image<unsigned char, 3> FeatureImage;
- typedef itk::Image<unsigned char, 3> LabelImage;
-
- if (collection->HasElement(origin))
- {
- LabelImage::Pointer originImage = dynamic_cast<LabelImage*>(collection->GetData(origin).GetPointer());
- MITK_INFO << "Creating new Element";
- if (!collection->HasElement(target) && originImage.IsNotNull())
- {
- MITK_INFO << "New image necessary";
- FeatureImage::Pointer image = FeatureImage::New();
- image->SetRegions(originImage->GetLargestPossibleRegion());
- image->SetSpacing(originImage->GetSpacing());
- image->SetOrigin(originImage->GetOrigin());
- image->SetDirection(originImage->GetDirection());
- image->Allocate();
-
- collection->AddData(dynamic_cast<itk::DataObject*>(image.GetPointer()),target,"");
- }
- }
- for (std::size_t i = 0; i < collection->Size();++i)
- {
- mitk::DataCollection* newCol = dynamic_cast<mitk::DataCollection*>(collection->GetData(i).GetPointer());
- if (newCol != nullptr)
- {
- EnsureLabelImageInCollection(newCol, origin, target);
- }
- }
-}
-
-void mitk::CostingStatistic::SetCollection(mitk::DataCollection::Pointer collection)
-{
- m_Collection = collection;
-}
-
-mitk::DataCollection::Pointer mitk::CostingStatistic::GetCollection()
-{
- return m_Collection;
-}
-
-bool mitk::CostingStatistic::UpdateCollection()
-{
- EnsureDataImageInCollection(m_Collection, m_MaskName, m_CombinedProbabilityA);
- EnsureDataImageInCollection(m_Collection, m_MaskName, m_CombinedProbabilityB);
- EnsureLabelImageInCollection(m_Collection, m_MaskName, m_CombinedLabelName);
-
- std::vector<DataCollectionImageIterator<double, 3> > iterProbA;
- std::vector<DataCollectionImageIterator<double, 3> > iterProbB;
- for (std::size_t i = 0; i < m_ProbabilityClassA.size(); ++i)
- {
- DataCollectionImageIterator<double, 3> iter(m_Collection, m_ProbabilityClassA[i]);
- iterProbA.push_back(iter);
- }
- for (std::size_t i = 0; i < m_ProbabilityClassB.size(); ++i)
- {
- DataCollectionImageIterator<double, 3> iter(m_Collection, m_ProbabilityClassB[i]);
- iterProbB.push_back(iter);
- }
- DataCollectionImageIterator<double, 3> iterCombineA(m_Collection, m_CombinedProbabilityA);
- DataCollectionImageIterator<double, 3> iterCombineB(m_Collection, m_CombinedProbabilityB);
- DataCollectionImageIterator<unsigned char, 3> iterMask(m_Collection, m_MaskName);
-
- while (!iterMask.IsAtEnd())
- {
- if (iterMask.GetVoxel() > 0)
- {
- double probA = 0;
- double probB = 0;
- for (std::size_t i = 0; i < iterProbA.size(); ++i)
- {
- probA += iterProbA[i].GetVoxel();
- }
- for (std::size_t i = 0; i < iterProbB.size(); ++i)
- {
- probB += iterProbB[i].GetVoxel();
- }
- iterCombineA.SetVoxel(probA * 100);
- iterCombineB.SetVoxel(probB * 100);
- }
- else
- {
- iterCombineA.SetVoxel(0.0);
- iterCombineB.SetVoxel(0.0);
- }
-
- ++iterCombineA;
- ++iterCombineB;
- ++iterMask;
- for (std::size_t i = 0; i < iterProbA.size(); ++i)
- {
- ++(iterProbA[i]);
- }
- for (std::size_t i = 0; i < iterProbB.size(); ++i)
- {
- ++(iterProbB[i]);
- }
- }
- return false;
-}
-
-bool mitk::CostingStatistic::CalculateClass(double threshold)
-{
- DataCollectionImageIterator<unsigned char, 3> iterMask(m_Collection, m_MaskName);
- DataCollectionImageIterator<unsigned char, 3> iterLabel(m_Collection, m_CombinedLabelName);
- DataCollectionImageIterator<double, 3> iterCombineA(m_Collection, m_CombinedProbabilityA);
- DataCollectionImageIterator<double, 3> iterCombineB(m_Collection, m_CombinedProbabilityB);
-
- while (!iterMask.IsAtEnd())
- {
- if (iterMask.GetVoxel() > 0)
- {
- double probA = iterCombineA.GetVoxel() / (iterCombineA.GetVoxel() + iterCombineB.GetVoxel());
- probA *= 100;
- iterLabel.SetVoxel(probA >= threshold ? 1 : 2);
- }
- else
- {
- iterLabel.SetVoxel(0);
- }
-
- ++iterMask;
- ++iterLabel;
- ++iterCombineA;
- ++iterCombineB;
- }
-
- return true;
-}
-
-bool mitk::CostingStatistic::WriteStatistic(std::ostream &out,std::ostream &sout, double stepSize, std::string shortLabel)
-{
- UpdateCollection();
- for (double threshold = 0 ; threshold <= 100; threshold += stepSize)
- {
- CalculateClass(threshold);
-
- std::stringstream ss;
- ss << shortLabel << ";" << threshold;
-
- mitk::CollectionStatistic stat;
- stat.SetCollection(m_Collection);
- stat.SetClassCount(2);
- stat.SetGoldName("GTV");
- stat.SetTestName(m_CombinedLabelName);
- stat.SetMaskName(m_MaskName);
- stat.Update();
-
- stat.Print(out, sout,false, ss.str());
- }
- return true;
-}
diff --git a/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.h b/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.h
deleted file mode 100644
index 68f9cf44a2..0000000000
--- a/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.h
+++ /dev/null
@@ -1,53 +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.
-
-============================================================================*/
-
-#ifndef mitkCostingStatistic_h
-#define mitkCostingStatistic_h
-
-#include <MitkDataCollectionExports.h>
-
-#include <mitkDataCollection.h>
-
-#include <iostream>
-
-namespace mitk {
- class MITKDATACOLLECTION_EXPORT CostingStatistic
- {
- public:
- void SetCollection(DataCollection::Pointer collection);
- DataCollection::Pointer GetCollection();
-
- void SetMaskName(std::string name) {m_MaskName = name;}
- void SetCombinedA(std::string name) {m_CombinedProbabilityA = name; }
- void SetCombinedB(std::string name) {m_CombinedProbabilityB = name; }
- void SetCombinedLabel(std::string name) {m_CombinedLabelName = name; }
- void SetProbabilitiesA (std::vector<std::string> probA) {m_ProbabilityClassA = probA;}
- void SetProbabilitiesB (std::vector<std::string> probB) {m_ProbabilityClassB = probB;}
-
- bool UpdateCollection();
- bool CalculateClass(double threshold);
-
- bool WriteStatistic(std::ostream &out,std::ostream &sout, double stepSize, std::string shortLabel);
- private:
-
- DataCollection::Pointer m_Collection;
- std::string m_MaskName;
- std::string m_CombinedProbabilityA;
- std::string m_CombinedProbabilityB;
- std::string m_CombinedLabelName;
-
- std::vector<std::string> m_ProbabilityClassA;
- std::vector<std::string> m_ProbabilityClassB;
- };
-}
-
-#endif
diff --git a/Modules/Classification/DataCollection/Utilities/mitkDataCollectionUtilities.cpp b/Modules/Classification/DataCollection/Utilities/mitkDataCollectionUtilities.cpp
deleted file mode 100644
index d6e9d94585..0000000000
--- a/Modules/Classification/DataCollection/Utilities/mitkDataCollectionUtilities.cpp
+++ /dev/null
@@ -1,279 +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 <mitkDataCollectionUtilities.h>
-
-#include <mitkDataCollectionImageIterator.h>
-
-#include <mitkImageCast.h>
-
-int mitk::DCUtilities::VoxelInMask(mitk::DataCollection::Pointer dc, std::string mask)
-{
- mitk::DataCollectionImageIterator<unsigned char, 3> maskIter(dc, mask);
- int count = 0;
- while ( ! maskIter.IsAtEnd() )
- {
- if (maskIter.GetVoxel() > 0)
- ++count;
- ++maskIter;
- }
- return count;
-}
-
-Eigen::MatrixXd mitk::DCUtilities::DC3dDToMatrixXd(mitk::DataCollection::Pointer dc, std::string name, std::string mask)
-{
- std::vector<std::string> names;
- names.push_back(name);
- return DC3dDToMatrixXd(dc, names, mask);
-}
-
-Eigen::MatrixXd mitk::DCUtilities::DC3dDToMatrixXd(mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask)
-{
- typedef mitk::DataCollectionImageIterator<double, 3> DataIterType;
-
- int numberOfVoxels = DCUtilities::VoxelInMask(dc,mask);
- int numberOfNames = names.size();
-
- mitk::DataCollectionImageIterator<unsigned char, 3> maskIter(dc, mask);
- std::vector<DataIterType> dataIter;
-
- for (int i = 0; i < numberOfNames; ++i)
- {
- DataIterType iter(dc, names[i]);
- dataIter.push_back(iter);
- }
-
- Eigen::MatrixXd result(numberOfVoxels, names.size());
- int row = 0;
- while ( ! maskIter.IsAtEnd() )
- {
- if (maskIter.GetVoxel() > 0)
- {
- for (int col = 0; col < numberOfNames; ++col)
- {
- result(row,col) = dataIter[col].GetVoxel();
- }
- ++row;
- }
- for (int col = 0; col < numberOfNames; ++col)
- {
- ++(dataIter[col]);
- }
- ++maskIter;
- }
- return result;
-}
-
-Eigen::MatrixXi mitk::DCUtilities::DC3dDToMatrixXi(mitk::DataCollection::Pointer dc, std::string name, std::string mask)
-{
- std::vector<std::string> names;
- names.push_back(name);
- return DC3dDToMatrixXi(dc, names, mask);
-}
-
-Eigen::MatrixXi mitk::DCUtilities::DC3dDToMatrixXi(mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask)
-{
- typedef mitk::DataCollectionImageIterator<unsigned char, 3> DataIterType;
-
- int numberOfVoxels = DCUtilities::VoxelInMask(dc,mask);
- int numberOfNames = names.size();
-
- mitk::DataCollectionImageIterator<unsigned char, 3> maskIter(dc, mask);
- std::vector<DataIterType> dataIter;
-
- for (int i = 0; i < numberOfNames; ++i)
- {
- DataIterType iter(dc, names[i]);
- dataIter.push_back(iter);
- }
-
- Eigen::MatrixXi result(numberOfVoxels, names.size());
- result.setZero();
- int row = 0;
- while ( ! maskIter.IsAtEnd() )
- {
- if (maskIter.GetVoxel() > 0)
- {
- for (int col = 0; col < numberOfNames; ++col)
- {
- result(row,col) = dataIter[col].GetVoxel();
- }
- ++row;
- }
- for (int col = 0; col < numberOfNames; ++col)
- {
- ++(dataIter[col]);
- }
- ++maskIter;
- }
- return result;
-}
-
-void mitk::DCUtilities::MatrixToDC3d(const Eigen::MatrixXd &matrix, mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask)
-{
- typedef mitk::DataCollectionImageIterator<double, 3> DataIterType;
-
- int numberOfNames = names.size();
-
- mitk::DataCollectionImageIterator<unsigned char, 3> maskIter(dc, mask);
- std::vector<DataIterType> dataIter;
-
- for (int i = 0; i < numberOfNames; ++i)
- {
- EnsureDoubleImageInDC(dc,names[i],mask);
- DataIterType iter(dc, names[i]);
- dataIter.push_back(iter);
- }
-
- int row = 0;
- while ( ! maskIter.IsAtEnd() )
- {
- if (maskIter.GetVoxel() > 0)
- {
- for (int col = 0; col < numberOfNames; ++col)
- {
- dataIter[col].SetVoxel(matrix(row,col));
- }
- ++row;
- }
- for (int col = 0; col < numberOfNames; ++col)
- {
- ++(dataIter[col]);
- }
- ++maskIter;
- }
-}
-
-void mitk::DCUtilities::MatrixToDC3d(const Eigen::MatrixXi &matrix, mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask)
-{
- typedef mitk::DataCollectionImageIterator<unsigned char, 3> DataIterType;
-
- int numberOfNames = names.size();
-
- mitk::DataCollectionImageIterator<unsigned char, 3> maskIter(dc, mask);
- std::vector<DataIterType> dataIter;
-
- for (int i = 0; i < numberOfNames; ++i)
- {
- EnsureUCharImageInDC(dc,names[i],mask);
- DataIterType iter(dc, names[i]);
- dataIter.push_back(iter);
- }
-
- int row = 0;
- while ( ! maskIter.IsAtEnd() )
- {
- if (maskIter.GetVoxel() > 0)
- {
- for (int col = 0; col < numberOfNames; ++col)
- {
- (dataIter[col]).SetVoxel(matrix(row,col));
- }
- ++row;
- }
- for (int col = 0; col < numberOfNames; ++col)
- {
- ++(dataIter[col]);
- }
- ++maskIter;
- }
-}
-
-void mitk::DCUtilities::MatrixToDC3d(const Eigen::MatrixXd &matrix, mitk::DataCollection::Pointer dc, const std::string &name, std::string mask)
-{
- std::vector<std::string> names;
- names.push_back(name);
- return MatrixToDC3d(matrix, dc, names, mask);
-}
-
-void mitk::DCUtilities::MatrixToDC3d(const Eigen::MatrixXi &matrix, mitk::DataCollection::Pointer dc, const std::string &name, std::string mask)
-{
- std::vector<std::string> names;
- names.push_back(name);
- return MatrixToDC3d(matrix, dc, names, mask);
-}
-
-void mitk::DCUtilities::EnsureUCharImageInDC(mitk::DataCollection::Pointer dc, std::string name, std::string origin)
-{
- typedef itk::Image<unsigned char, 3> FeatureImage;
- typedef itk::Image<unsigned char, 3> LabelImage;
-
- mitk::DataCollectionImageIterator<unsigned char , 3> iter( dc, origin);
- while (!iter.IsAtEnd())
- {
- ++iter;
- }
-
- if (dc->HasElement(origin))
- {
- LabelImage::Pointer originImage = dynamic_cast<LabelImage*>(dc->GetData(origin).GetPointer());
- // = dynamic_cast<LabelImage*>(dc->GetItkImage<LabelImage>(origin).GetPointer());
- if (!dc->HasElement(name) && originImage.IsNotNull())
- {
- MITK_INFO << "New unsigned char image necessary";
- FeatureImage::Pointer image = FeatureImage::New();
- image->SetRegions(originImage->GetLargestPossibleRegion());
- image->SetSpacing(originImage->GetSpacing());
- image->SetOrigin(originImage->GetOrigin());
- image->SetDirection(originImage->GetDirection());
- image->Allocate();
- image->FillBuffer(0);
-
- dc->AddData(dynamic_cast<itk::DataObject*>(image.GetPointer()),name,"");
- }
- }
- for (std::size_t i = 0; i < dc->Size();++i)
- {
- mitk::DataCollection* newCol = dynamic_cast<mitk::DataCollection*>(dc->GetData(i).GetPointer());
- if (newCol != nullptr)
- {
- EnsureUCharImageInDC(newCol, name, origin);
- }
- }
-}
-
-void mitk::DCUtilities::EnsureDoubleImageInDC(mitk::DataCollection::Pointer dc, std::string name, std::string origin)
-{
- typedef itk::Image<double, 3> FeatureImage;
- typedef itk::Image<unsigned char, 3> LabelImage;
-
- mitk::DataCollectionImageIterator<unsigned char , 3> iter( dc, origin);
- while (!iter.IsAtEnd())
- {
- ++iter;
- }
-
- if (dc->HasElement(origin))
- {
- LabelImage::Pointer originImage = dynamic_cast<LabelImage*>(dc->GetData(origin).GetPointer());
- if (!dc->HasElement(name) && originImage.IsNotNull())
- {
- MITK_INFO << "New double image necessary";
- FeatureImage::Pointer image = FeatureImage::New();
- image->SetRegions(originImage->GetLargestPossibleRegion());
- image->SetSpacing(originImage->GetSpacing());
- image->SetOrigin(originImage->GetOrigin());
- image->SetDirection(originImage->GetDirection());
- image->Allocate();
-
- dc->AddData(dynamic_cast<itk::DataObject*>(image.GetPointer()),name,"");
- }
- }
- for (std::size_t i = 0; i < dc->Size();++i)
- {
- mitk::DataCollection* newCol = dynamic_cast<mitk::DataCollection*>(dc->GetData(i).GetPointer());
- if (newCol != nullptr)
- {
- EnsureDoubleImageInDC(newCol, name, origin);
- }
- }
-}
diff --git a/Modules/Classification/DataCollection/Utilities/mitkDataCollectionUtilities.h b/Modules/Classification/DataCollection/Utilities/mitkDataCollectionUtilities.h
deleted file mode 100644
index 5ed55fb8e0..0000000000
--- a/Modules/Classification/DataCollection/Utilities/mitkDataCollectionUtilities.h
+++ /dev/null
@@ -1,43 +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.
-
-============================================================================*/
-
-#ifndef mitkDataCollectionUtilities_h
-#define mitkDataCollectionUtilities_h
-
-#include <MitkDataCollectionExports.h>
-
-#include <mitkDataCollection.h>
-#include <Eigen/Dense>
-
-namespace mitk
-{
- class MITKDATACOLLECTION_EXPORT DCUtilities
- {
- public:
- static int VoxelInMask(mitk::DataCollection::Pointer dc, std::string mask);
-
- static Eigen::MatrixXd DC3dDToMatrixXd(mitk::DataCollection::Pointer dc, std::string names, std::string mask);
- static Eigen::MatrixXd DC3dDToMatrixXd(mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask);
- static Eigen::MatrixXi DC3dDToMatrixXi(mitk::DataCollection::Pointer dc, std::string name, std::string mask);
- static Eigen::MatrixXi DC3dDToMatrixXi(mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask);
-
- static void MatrixToDC3d(const Eigen::MatrixXd &matrix, mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask);
- static void MatrixToDC3d(const Eigen::MatrixXi &matrix, mitk::DataCollection::Pointer dc, const std::vector<std::string> &names, std::string mask);
- static void MatrixToDC3d(const Eigen::MatrixXd &matrix, mitk::DataCollection::Pointer dc, const std::string &names, std::string mask);
- static void MatrixToDC3d(const Eigen::MatrixXi &matrix, mitk::DataCollection::Pointer dc, const std::string &names, std::string mask);
-
- static void EnsureUCharImageInDC(mitk::DataCollection::Pointer dc, std::string name, std::string origin);
- static void EnsureDoubleImageInDC(mitk::DataCollection::Pointer dc, std::string name, std::string origin);
- };
-}
-
-#endif
diff --git a/Modules/Classification/DataCollection/files.cmake b/Modules/Classification/DataCollection/files.cmake
deleted file mode 100644
index 6ae049e2a7..0000000000
--- a/Modules/Classification/DataCollection/files.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-SET(CPP_FILES
- DataHolder/mitkDataCollection.cpp
- DataHolder/mitkDataCollectionUtility.cpp
- ReaderWriter/mitkCollectionReader.cpp
- ReaderWriter/mitkCollectionWriter.cpp
- Utilities/mitkCostingStatistic.cpp
- Utilities/mitkCollectionStatistic.cpp
- Utilities/mitkDataCollectionUtilities.cpp
- testcase.cpp
-)
-
-SET(H_FILES
- DataHolder/mitkDataCollection.h
- DataHolder/mitkDataCollectionUtility.h
- ReaderWriter/mitkCollectionReader.h
- ReaderWriter/mitkCollectionWriter.h
- Iterators/mitkDataCollectionImageIterator.h
- Iterators/mitkDataCollectionSingleImageIterator.h
- Iterators/mitkDataCollectionVectorImageIterator.h
- Utilities/mitkCostingStatistic.h
- Utilities/mitkCollectionStatistic.h
- Utilities/mitkDataCollectionUtilities.h
- testcase.h
-)
diff --git a/Modules/Classification/DataCollection/testcase.cpp b/Modules/Classification/DataCollection/testcase.cpp
deleted file mode 100644
index 4e7753f58c..0000000000
--- a/Modules/Classification/DataCollection/testcase.cpp
+++ /dev/null
@@ -1,27 +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 <testcase.h>
-
-#include <mitkDataCollectionImageIterator.h>
-
-void test::bla::test()
- {
- mitk::DataCollection::Pointer c = mitk::DataCollection::New();
- mitk::DataCollectionImageIterator<double, 3> ci(c,"test");
- ci.ToBegin();
- ci.IsAtEnd();
- ci++;
- ++ci;
- ci.GetVoxel();
- ci.SetVoxel(3);
- ci.GetFilePrefix();
-};
diff --git a/Modules/Classification/DataCollection/testcase.h b/Modules/Classification/DataCollection/testcase.h
deleted file mode 100644
index f88d903984..0000000000
--- a/Modules/Classification/DataCollection/testcase.h
+++ /dev/null
@@ -1,36 +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.
-
-============================================================================*/
-
-
-#ifndef testcase_h
-#define testcase_h
-
-
-#include <mitkDataCollection.h>
-#include <itkImageIterator.h>
-
-
-/**
- \brief Follow Up Storage - Class to facilitate loading/accessing structured follow-up data
-
- Data is into a collection that may contain further (sub) collections or images.
-*/
-
-namespace test
-{
- class bla
- {
- void test();
- };
-} // end namespace
-
-#endif //testcase_h
diff --git a/Modules/Classification/Scripts/xvfb-run-save.sh b/Modules/Classification/Scripts/xvfb-run-save.sh
deleted file mode 100644
index d5a26df183..0000000000
--- a/Modules/Classification/Scripts/xvfb-run-save.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-# allow settings to be updated via environment
-: "${xvfb_lockdir:=$HOME/.xvfb-locks}"
-: "${xvfb_display_min:=99}"
-: "${xvfb_display_max:=599}"
-
-# assuming only one user will use this, let's put the locks in our own home directory
-# avoids vulnerability to symlink attacks.
-mkdir -p -- "$xvfb_lockdir" || exit
-
-i=$xvfb_display_min # minimum display number
-while (( i < xvfb_display_max )); do
- if [ -f "/tmp/.X$i-lock" ]; then # still avoid an obvious open display
- (( ++i )); continue
- fi
- exec 5>"$xvfb_lockdir/$i" || continue # open a lockfile
- if flock -x -n 5; then # try to lock it
-# echo xvfb-run --server-num="$i" --server-args="'-screen 0 1024x768x24'" "$@"
- exec xvfb-run -e ~/xvfblog.log --server-num="$i" --server-args='-screen 0 1024x768x24' "$@" || exit # if locked, run xvfb-run
- fi
- (( i++ ))
-done
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Modules/Classification/documentation/UserManual/mitkClassificationMiniAppsPortalPage.dox b/Modules/Classification/documentation/UserManual/mitkClassificationMiniAppsPortalPage.dox
deleted file mode 100644
index 32778b37b1..0000000000
--- a/Modules/Classification/documentation/UserManual/mitkClassificationMiniAppsPortalPage.dox
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
-\page mitkClassificationMiniAppsPortalPage MITK Classification Mini Apps
-
-\tableofcontents
-
-The Classification Mini Apps bundle the functionality that is commonly neeeded for the processing and learning with medical images. As all other MiniApps, they follow the <a href="https://www.slicer.org/slicerWiki/index.php/Slicer3:Execution_Model_Documentation">Slicer Execution Model</a> in describing themselves via xml. You can simply obtain a description by calling the MiniApp without any parameter. If the MiniApp is calles with the option "--xml" a XML description of all possible parameter is added.
-
-\section mcmasec1 Description of Mini Apps
-
-\subsection mcmasub1 mitkCLGLobalImageFeatures
-Allows to calculate features that describe the masked area. Can be used to obtain radiomics features.
-
-\subsection mcmasub2 mitkCLN4
-Allows to calculate a bias normalization.
-
-\subsection mcmasub3 mitkCLStaple
-Allows to combine multiple segmentations into a single segmentation using the STAPLE algorithm
-
-*/
diff --git a/Modules/Core/CMakeLists.txt b/Modules/Core/CMakeLists.txt
index 34a24839c4..0ad7a726f5 100644
--- a/Modules/Core/CMakeLists.txt
+++ b/Modules/Core/CMakeLists.txt
@@ -1,74 +1,74 @@
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
DEPENDS
PUBLIC
- mbilog
+ MitkLog
CppMicroServices
PACKAGE_DEPENDS
PUBLIC
Boost
ITK|IOImageBase+SpatialObjects+Statistics
#ITK|Statistics+Transform
VTK|FiltersTexture+FiltersParallel+ImagingStencil+ImagingMath+InteractionStyle+RenderingOpenGL2+RenderingVolumeOpenGL2+RenderingFreeType+RenderingLabel+InteractionWidgets+IOGeometry+IOImage+IOXML
PRIVATE
ITK|IOBioRad+IOBMP+IOBruker+IOCSV+IOGDCM+IOGE+IOGIPL+IOHDF5+IOIPL+IOJPEG+IOJPEG2000+IOLSM+IOMesh+IOMeta+IOMINC+IOMRC+IONIFTI+IONRRD+IOPNG+IOSiemens+IOSpatialObjects+IOStimulate+IOTIFF+IOTransformBase+IOTransformHDF5+IOTransformInsightLegacy+IOTransformMatlab+IOVTK+IOXML
nlohmann_json
tinyxml2
${optional_private_package_depends}
# Do not automatically create CppMicroServices initialization code.
# Because the VTK "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(BUILD_TESTING)
add_subdirectory(TestingHelper)
add_subdirectory(test)
endif()
diff --git a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp
index bfb05627d7..b03a5bdfc1 100644
--- a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp
+++ b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp
@@ -1,435 +1,422 @@
/*============================================================================
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.
============================================================================*/
// MITK
#include <mitkIOUtil.h>
#include <mitkInteractionEventConst.h>
#include <mitkInteractionTestHelper.h>
#include <mitkPlaneGeometryDataMapper2D.h>
+#include <mitkRenderingManager.h>
#include <mitkStandaloneDataStorage.h>
+#include <mitkTimeNavigationController.h>
// VTK
#include <vtkCamera.h>
#include <vtkRenderWindowInteractor.h>
// us
#include <usGetModuleContext.h>
#include <tinyxml2.h>
mitk::InteractionTestHelper::InteractionTestHelper(const std::string &interactionXmlFilePath)
: m_InteractionFilePath(interactionXmlFilePath)
{
this->Initialize(interactionXmlFilePath);
}
void mitk::InteractionTestHelper::Initialize(const std::string &interactionXmlFilePath)
{
tinyxml2::XMLDocument document;
if (tinyxml2::XML_SUCCESS == document.LoadFile(interactionXmlFilePath.c_str()))
{
- // get RenderingManager instance
- auto rm = mitk::RenderingManager::GetInstance();
-
// create data storage
m_DataStorage = mitk::StandaloneDataStorage::New();
// for each renderer found create a render window and configure
for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str())
->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str())
->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str());
element != nullptr;
element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()))
{
// get name of renderer
const char *rendererName =
element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str());
// get view direction
mitk::AnatomicalPlane viewDirection = mitk::AnatomicalPlane::Axial;
if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str()) != nullptr)
{
int viewDirectionNum =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str()));
viewDirection = static_cast<mitk::AnatomicalPlane>(viewDirectionNum);
}
// get mapper slot id
MapperSlotId mapperID = mitk::BaseRenderer::Standard2D;
if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr)
{
int mapperIDNum =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()));
mapperID = static_cast<MapperSlotId>(mapperIDNum);
}
// Get Size of Render Windows
int size[3];
size[0] = size[1] = size[2] = 0;
if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str()) != nullptr)
{
size[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str()));
}
if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str()) != nullptr)
{
size[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str()));
}
if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str()) != nullptr)
{
size[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str()));
}
// create renderWindow, renderer and dispatcher
auto rw = RenderWindow::New(nullptr, rendererName); // VtkRenderWindow is created within constructor if nullptr
if (size[0] != 0 && size[1] != 0)
{
rw->SetSize(size[0], size[1]);
rw->GetRenderer()->Resize(size[0], size[1]);
}
// set storage of renderer
rw->GetRenderer()->SetDataStorage(m_DataStorage);
// set view direction to axial
rw->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection);
// set renderer to render 2D
rw->GetRenderer()->SetMapperID(mapperID);
rw->GetRenderer()->PrepareRender();
// Some more magic for the 3D render window case:
// Camera view direction, position and focal point
if (mapperID == mitk::BaseRenderer::Standard3D)
{
if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr)
{
double cameraFocalPoint[3];
cameraFocalPoint[0] =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()));
cameraFocalPoint[1] =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str()));
cameraFocalPoint[2] =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str()));
rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint);
}
if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr)
{
double cameraPosition[3];
cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()));
cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str()));
cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str()));
rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition);
}
if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr)
{
double viewUp[3];
viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()));
viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str()));
viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str()));
rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp);
}
}
rw->GetVtkRenderWindow()->Render();
rw->GetVtkRenderWindow()->WaitForCompletion();
- // connect SliceNavigationControllers to timestep changed event of TimeNavigationController
- rw->GetSliceNavigationController()->ConnectGeometryTimeEvent(rm->GetTimeNavigationController());
- rm->GetTimeNavigationController()->ConnectGeometryTimeEvent(rw->GetSliceNavigationController());
-
// add to list of known render windows
m_RenderWindowList.push_back(rw);
}
- // TODO: check the following lines taken from QmitkStdMultiWidget and adapt them to be executed in our code here.
- // mitkWidget1->GetSliceNavigationController()
- // ->ConnectGeometrySendEvent(mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()));
-
// register interaction event obserer to handle scroll events
InitializeDisplayActionEventHandling();
}
else
{
mitkThrow() << "Can not load interaction xml file <" << m_InteractionFilePath << ">";
}
// WARNING assumes a 3D window exists !!!!
this->AddDisplayPlaneSubTree();
}
void mitk::InteractionTestHelper::InitializeDisplayActionEventHandling()
{
m_DisplayActionEventBroadcast = mitk::DisplayActionEventBroadcast::New();
m_DisplayActionEventBroadcast->LoadStateMachine("DisplayInteraction.xml");
m_DisplayActionEventBroadcast->SetEventConfig("DisplayConfigMITKBase.xml");
m_DisplayActionEventBroadcast->AddEventConfig("DisplayConfigCrosshair.xml");
}
mitk::InteractionTestHelper::~InteractionTestHelper()
{
- mitk::RenderingManager *rm = mitk::RenderingManager::GetInstance();
-
// unregister renderers
auto it = m_RenderWindowList.begin();
auto end = m_RenderWindowList.end();
for (; it != end; ++it)
{
- rm->GetTimeNavigationController()->Disconnect((*it)->GetSliceNavigationController());
- (*it)->GetSliceNavigationController()->Disconnect(rm->GetTimeNavigationController());
mitk::BaseRenderer::RemoveInstance((*it)->GetVtkRenderWindow());
}
- rm->RemoveAllObservers();
+
+ mitk::RenderingManager::GetInstance()->RemoveAllObservers();
}
mitk::DataStorage::Pointer mitk::InteractionTestHelper::GetDataStorage()
{
return m_DataStorage;
}
void mitk::InteractionTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node)
{
this->m_DataStorage->Add(node);
this->Set3dCameraSettings();
}
void mitk::InteractionTestHelper::PlaybackInteraction()
{
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage);
// load events if not loaded yet
if (m_Events.empty())
this->LoadInteraction();
auto it = m_RenderWindowList.begin();
auto end = m_RenderWindowList.end();
for (; it != end; ++it)
{
(*it)->GetRenderer()->PrepareRender();
(*it)->GetVtkRenderWindow()->Render();
(*it)->GetVtkRenderWindow()->WaitForCompletion();
}
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage);
it = m_RenderWindowList.begin();
for (; it != end; ++it)
{
(*it)->GetVtkRenderWindow()->Render();
(*it)->GetVtkRenderWindow()->WaitForCompletion();
}
// mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
// playback all events in queue
for (unsigned long i = 0; i < m_Events.size(); ++i)
{
// let dispatcher of sending renderer process the event
m_Events.at(i)->GetSender()->GetDispatcher()->ProcessEvent(m_Events.at(i));
}
if (false)
{
it--;
(*it)->GetVtkRenderWindow()->GetInteractor()->Start();
}
}
void mitk::InteractionTestHelper::LoadInteraction()
{
// load interaction pattern from xml file
std::ifstream xmlStream(m_InteractionFilePath.c_str());
mitk::XML2EventParser parser(xmlStream);
m_Events = parser.GetInteractions();
xmlStream.close();
// Avoid VTK warning: Trying to delete object with non-zero reference count.
parser.SetReferenceCount(0);
}
void mitk::InteractionTestHelper::SetTimeStep(int newTimeStep)
{
- mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage);
+ auto rm = mitk::RenderingManager::GetInstance();
+ rm->InitializeViewsByBoundingObjects(m_DataStorage);
- bool timeStepIsvalid =
- mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetCreatedWorldGeometry()->IsValidTimeStep(
- newTimeStep);
+ bool timeStepIsvalid = rm->GetTimeNavigationController()->GetInputWorldTimeGeometry()->IsValidTimeStep(newTimeStep);
if (timeStepIsvalid)
{
- mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime()->SetPos(newTimeStep);
+ rm->GetTimeNavigationController()->GetStepper()->SetPos(newTimeStep);
}
}
mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByName(const std::string &name)
{
auto it = m_RenderWindowList.begin();
auto end = m_RenderWindowList.end();
for (; it != end; ++it)
{
if (name.compare((*it)->GetRenderer()->GetName()) == 0)
return (*it).GetPointer();
}
return nullptr;
}
mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByDefaultViewDirection(AnatomicalPlane viewDirection)
{
auto it = m_RenderWindowList.begin();
auto end = m_RenderWindowList.end();
for (; it != end; ++it)
{
if (viewDirection == (*it)->GetSliceNavigationController()->GetDefaultViewDirection())
return (*it).GetPointer();
}
return nullptr;
}
mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindow(unsigned int index)
{
if (index < m_RenderWindowList.size())
{
return m_RenderWindowList.at(index).GetPointer();
}
else
{
return nullptr;
}
}
void mitk::InteractionTestHelper::AddDisplayPlaneSubTree()
{
// add the displayed planes of the multiwidget to a node to which the subtree
// @a planesSubTree points ...
mitk::PlaneGeometryDataMapper2D::Pointer mapper;
mitk::IntProperty::Pointer layer = mitk::IntProperty::New(1000);
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetProperty("name", mitk::StringProperty::New("Widgets"));
node->SetProperty("helper object", mitk::BoolProperty::New(true));
m_DataStorage->Add(node);
for (auto it : m_RenderWindowList)
{
if (it->GetRenderer()->GetMapperID() == BaseRenderer::Standard3D)
continue;
// ... of widget 1
mitk::DataNode::Pointer planeNode1 =
(mitk::BaseRenderer::GetInstance(it->GetVtkRenderWindow()))->GetCurrentWorldPlaneGeometryNode();
planeNode1->SetProperty("visible", mitk::BoolProperty::New(true));
planeNode1->SetProperty("name", mitk::StringProperty::New("widget1Plane"));
planeNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
planeNode1->SetProperty("helper object", mitk::BoolProperty::New(true));
planeNode1->SetProperty("layer", layer);
planeNode1->SetColor(1.0, 0.0, 0.0);
mapper = mitk::PlaneGeometryDataMapper2D::New();
planeNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
m_DataStorage->Add(planeNode1, node);
}
}
void mitk::InteractionTestHelper::Set3dCameraSettings()
{
tinyxml2::XMLDocument document;
if (tinyxml2::XML_SUCCESS == document.LoadFile(m_InteractionFilePath.c_str()))
{
// for each renderer found create a render window and configure
for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str())
->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str())
->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str());
element != nullptr;
element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()))
{
// get name of renderer
const char *rendererName =
element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str());
// get mapper slot id
MapperSlotId mapperID = mitk::BaseRenderer::Standard2D;
if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr)
{
int mapperIDNum =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()));
mapperID = static_cast<MapperSlotId>(mapperIDNum);
}
if (mapperID == mitk::BaseRenderer::Standard3D)
{
RenderWindow *namedRenderer = nullptr;
for (const auto &it : m_RenderWindowList)
{
if (strcmp(it->GetRenderer()->GetName(), rendererName) == 0)
{
namedRenderer = it.GetPointer();
break;
}
}
if (namedRenderer == nullptr)
{
MITK_ERROR << "No match for render window was found.";
return;
}
namedRenderer->GetRenderer()->PrepareRender();
if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr)
{
double cameraFocalPoint[3];
cameraFocalPoint[0] =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()));
cameraFocalPoint[1] =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str()));
cameraFocalPoint[2] =
std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str()));
namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint);
}
if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr)
{
double cameraPosition[3];
cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()));
cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str()));
cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str()));
namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition);
}
if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr)
{
double viewUp[3];
viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()));
viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str()));
viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str()));
namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp);
}
namedRenderer->GetVtkRenderWindow()->Render();
}
}
}
}
diff --git a/Modules/Core/files.cmake b/Modules/Core/files.cmake
index cff9510c3c..d8412455d1 100644
--- a/Modules/Core/files.cmake
+++ b/Modules/Core/files.cmake
@@ -1,328 +1,329 @@
file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
set(CPP_FILES
mitkCoreActivator.cpp
mitkCoreObjectFactoryBase.cpp
mitkCoreObjectFactory.cpp
mitkCoreServices.cpp
mitkException.cpp
Algorithms/mitkBaseDataSource.cpp
Algorithms/mitkClippedSurfaceBoundsCalculator.cpp
Algorithms/mitkCompareImageDataFilter.cpp
Algorithms/mitkCompositePixelValueToString.cpp
Algorithms/mitkConvert2Dto3DImageFilter.cpp
Algorithms/mitkDataNodeSource.cpp
Algorithms/mitkExtractSliceFilter.cpp
Algorithms/mitkExtractSliceFilter2.cpp
Algorithms/mitkHistogramGenerator.cpp
Algorithms/mitkImageChannelSelector.cpp
Algorithms/mitkImageSliceSelector.cpp
Algorithms/mitkImageSource.cpp
Algorithms/mitkImageTimeSelector.cpp
Algorithms/mitkImageToImageFilter.cpp
Algorithms/mitkImageToSurfaceFilter.cpp
Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp
Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp
Algorithms/mitkPointSetSource.cpp
Algorithms/mitkPointSetToPointSetFilter.cpp
Algorithms/mitkRGBToRGBACastImageFilter.cpp
Algorithms/mitkSubImageSelector.cpp
Algorithms/mitkSurfaceSource.cpp
Algorithms/mitkSurfaceToImageFilter.cpp
Algorithms/mitkSurfaceToSurfaceFilter.cpp
Algorithms/mitkUIDGenerator.cpp
Algorithms/mitkVolumeCalculator.cpp
Algorithms/mitkTemporalJoinImagesFilter.cpp
Controllers/mitkBaseController.cpp
Controllers/mitkCallbackFromGUIThread.cpp
Controllers/mitkCameraController.cpp
Controllers/mitkCameraRotationController.cpp
Controllers/mitkCrosshairManager.cpp
Controllers/mitkLimitedLinearUndo.cpp
Controllers/mitkOperationEvent.cpp
Controllers/mitkPlanePositionManager.cpp
Controllers/mitkProgressBar.cpp
Controllers/mitkRenderingManager.cpp
Controllers/mitkSliceNavigationController.cpp
Controllers/mitkSliceNavigationHelper.cpp
Controllers/mitkStatusBar.cpp
Controllers/mitkStepper.cpp
Controllers/mitkTestManager.cpp
+ Controllers/mitkTimeNavigationController.cpp
Controllers/mitkUndoController.cpp
Controllers/mitkVerboseLimitedLinearUndo.cpp
Controllers/mitkVtkLayerController.cpp
DataManagement/mitkAnatomicalStructureColorPresets.cpp
DataManagement/mitkArbitraryTimeGeometry.cpp
DataManagement/mitkAbstractTransformGeometry.cpp
DataManagement/mitkAnnotationProperty.cpp
DataManagement/mitkApplicationCursor.cpp
DataManagement/mitkApplyTransformMatrixOperation.cpp
DataManagement/mitkBaseData.cpp
DataManagement/mitkBaseGeometry.cpp
DataManagement/mitkBaseProperty.cpp
DataManagement/mitkChannelDescriptor.cpp
DataManagement/mitkClippingProperty.cpp
DataManagement/mitkColorProperty.cpp
DataManagement/mitkCrosshairData.cpp
DataManagement/mitkDataNode.cpp
DataManagement/mitkDataStorage.cpp
DataManagement/mitkEnumerationProperty.cpp
DataManagement/mitkFloatPropertyExtension.cpp
DataManagement/mitkGeometry3D.cpp
DataManagement/mitkGeometryData.cpp
DataManagement/mitkGeometryTransformHolder.cpp
DataManagement/mitkGroupTagProperty.cpp
DataManagement/mitkGenericIDRelationRule.cpp
DataManagement/mitkIdentifiable.cpp
DataManagement/mitkImageAccessorBase.cpp
DataManagement/mitkImageCaster.cpp
DataManagement/mitkImageCastPart1.cpp
DataManagement/mitkImageCastPart2.cpp
DataManagement/mitkImageCastPart3.cpp
DataManagement/mitkImageCastPart4.cpp
DataManagement/mitkImage.cpp
DataManagement/mitkImageDataItem.cpp
DataManagement/mitkImageDescriptor.cpp
DataManagement/mitkImageReadAccessor.cpp
DataManagement/mitkImageStatisticsHolder.cpp
DataManagement/mitkImageVtkAccessor.cpp
DataManagement/mitkImageVtkReadAccessor.cpp
DataManagement/mitkImageVtkWriteAccessor.cpp
DataManagement/mitkImageWriteAccessor.cpp
DataManagement/mitkIntPropertyExtension.cpp
DataManagement/mitkIPersistenceService.cpp
DataManagement/mitkIPropertyAliases.cpp
DataManagement/mitkIPropertyDescriptions.cpp
DataManagement/mitkIPropertyExtensions.cpp
DataManagement/mitkIPropertyFilters.cpp
DataManagement/mitkIPropertyOwner.cpp
DataManagement/mitkIPropertyPersistence.cpp
DataManagement/mitkIPropertyProvider.cpp
DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp
DataManagement/mitkLandmarkProjector.cpp
DataManagement/mitkLevelWindow.cpp
DataManagement/mitkLevelWindowManager.cpp
DataManagement/mitkLevelWindowPreset.cpp
DataManagement/mitkLevelWindowProperty.cpp
DataManagement/mitkLine.cpp
DataManagement/mitkLookupTable.cpp
DataManagement/mitkLookupTableProperty.cpp
DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable
DataManagement/mitkMaterial.cpp
DataManagement/mitkMemoryUtilities.cpp
DataManagement/mitkModalityProperty.cpp
DataManagement/mitkModifiedLock.cpp
DataManagement/mitkNodePredicateAnd.cpp
DataManagement/mitkNodePredicateBase.cpp
DataManagement/mitkNodePredicateCompositeBase.cpp
DataManagement/mitkNodePredicateData.cpp
DataManagement/mitkNodePredicateDataType.cpp
DataManagement/mitkNodePredicateDataUID.cpp
DataManagement/mitkNodePredicateDimension.cpp
DataManagement/mitkNodePredicateFunction.cpp
DataManagement/mitkNodePredicateGeometry.cpp
DataManagement/mitkNodePredicateNot.cpp
DataManagement/mitkNodePredicateOr.cpp
DataManagement/mitkNodePredicateProperty.cpp
DataManagement/mitkNodePredicateDataProperty.cpp
DataManagement/mitkNodePredicateSubGeometry.cpp
DataManagement/mitkNumericConstants.cpp
DataManagement/mitkPlaneGeometry.cpp
DataManagement/mitkPlaneGeometryData.cpp
DataManagement/mitkPlaneOperation.cpp
DataManagement/mitkPlaneOrientationProperty.cpp
DataManagement/mitkPointOperation.cpp
DataManagement/mitkPointSet.cpp
DataManagement/mitkPointSetShapeProperty.cpp
DataManagement/mitkProperties.cpp
DataManagement/mitkPropertyAliases.cpp
DataManagement/mitkPropertyDescriptions.cpp
DataManagement/mitkPropertyExtension.cpp
DataManagement/mitkPropertyExtensions.cpp
DataManagement/mitkPropertyFilter.cpp
DataManagement/mitkPropertyFilters.cpp
DataManagement/mitkPropertyKeyPath.cpp
DataManagement/mitkPropertyList.cpp
DataManagement/mitkPropertyListReplacedObserver.cpp
DataManagement/mitkPropertyNameHelper.cpp
DataManagement/mitkPropertyObserver.cpp
DataManagement/mitkPropertyPersistence.cpp
DataManagement/mitkPropertyPersistenceInfo.cpp
DataManagement/mitkPropertyRelationRuleBase.cpp
DataManagement/mitkProportionalTimeGeometry.cpp
DataManagement/mitkRenderingModeProperty.cpp
DataManagement/mitkResliceMethodProperty.cpp
DataManagement/mitkRestorePlanePositionOperation.cpp
DataManagement/mitkRotationOperation.cpp
DataManagement/mitkScaleOperation.cpp
DataManagement/mitkSlicedData.cpp
DataManagement/mitkSlicedGeometry3D.cpp
DataManagement/mitkSmartPointerProperty.cpp
DataManagement/mitkStandaloneDataStorage.cpp
DataManagement/mitkStringProperty.cpp
DataManagement/mitkSurface.cpp
DataManagement/mitkSurfaceOperation.cpp
DataManagement/mitkSourceImageRelationRule.cpp
DataManagement/mitkThinPlateSplineCurvedGeometry.cpp
DataManagement/mitkTimeGeometry.cpp
DataManagement/mitkTransferFunction.cpp
DataManagement/mitkTransferFunctionInitializer.cpp
DataManagement/mitkTransferFunctionProperty.cpp
DataManagement/mitkTemporoSpatialStringProperty.cpp
DataManagement/mitkUIDManipulator.cpp
DataManagement/mitkVector.cpp
DataManagement/mitkVectorProperty.cpp
DataManagement/mitkVtkInterpolationProperty.cpp
DataManagement/mitkVtkRepresentationProperty.cpp
DataManagement/mitkVtkResliceInterpolationProperty.cpp
DataManagement/mitkVtkScalarModeProperty.cpp
DataManagement/mitkWeakPointerProperty.cpp
DataManagement/mitkIPropertyRelations.cpp
DataManagement/mitkPropertyRelations.cpp
Interactions/mitkAction.cpp
Interactions/mitkBindDispatcherInteractor.cpp
Interactions/mitkDataInteractor.cpp
Interactions/mitkDispatcher.cpp
Interactions/mitkDisplayActionEventBroadcast.cpp
Interactions/mitkDisplayActionEventFunctions.cpp
Interactions/mitkDisplayActionEventHandler.cpp
Interactions/mitkDisplayActionEventHandlerDesynchronized.cpp
Interactions/mitkDisplayActionEventHandlerStd.cpp
Interactions/mitkDisplayActionEventHandlerSynchronized.cpp
Interactions/mitkDisplayCoordinateOperation.cpp
Interactions/mitkEventConfig.cpp
Interactions/mitkEventFactory.cpp
Interactions/mitkEventRecorder.cpp
Interactions/mitkEventStateMachine.cpp
Interactions/mitkInteractionEventConst.cpp
Interactions/mitkInteractionEvent.cpp
Interactions/mitkInteractionEventHandler.cpp
Interactions/mitkInteractionEventObserver.cpp
Interactions/mitkInteractionKeyEvent.cpp
Interactions/mitkInteractionPositionEvent.cpp
Interactions/mitkInteractionSchemeSwitcher.cpp
Interactions/mitkInternalEvent.cpp
Interactions/mitkMouseDoubleClickEvent.cpp
Interactions/mitkMouseMoveEvent.cpp
Interactions/mitkMousePressEvent.cpp
Interactions/mitkMouseReleaseEvent.cpp
Interactions/mitkMouseWheelEvent.cpp
Interactions/mitkPointSetDataInteractor.cpp
Interactions/mitkSinglePointDataInteractor.cpp
Interactions/mitkStateMachineAction.cpp
Interactions/mitkStateMachineCondition.cpp
Interactions/mitkStateMachineContainer.cpp
Interactions/mitkStateMachineState.cpp
Interactions/mitkStateMachineTransition.cpp
Interactions/mitkVtkEventAdapter.cpp
Interactions/mitkVtkInteractorStyle.cxx
Interactions/mitkXML2EventParser.cpp
IO/mitkAbstractFileIO.cpp
IO/mitkAbstractFileReader.cpp
IO/mitkAbstractFileWriter.cpp
IO/mitkCustomMimeType.cpp
IO/mitkFileReader.cpp
IO/mitkFileReaderRegistry.cpp
IO/mitkFileReaderSelector.cpp
IO/mitkFileReaderWriterBase.cpp
IO/mitkFileWriter.cpp
IO/mitkFileWriterRegistry.cpp
IO/mitkFileWriterSelector.cpp
IO/mitkGeometry3DToXML.cpp
IO/mitkIFileIO.cpp
IO/mitkIFileReader.cpp
IO/mitkIFileWriter.cpp
IO/mitkGeometryDataReaderService.cpp
IO/mitkGeometryDataWriterService.cpp
IO/mitkImageGenerator.cpp
IO/mitkImageVtkLegacyIO.cpp
IO/mitkImageVtkXmlIO.cpp
IO/mitkIMimeTypeProvider.cpp
IO/mitkIOConstants.cpp
IO/mitkIOMimeTypes.cpp
IO/mitkIOUtil.cpp
IO/mitkItkImageIO.cpp
IO/mitkItkLoggingAdapter.cpp
IO/mitkLegacyFileReaderService.cpp
IO/mitkLegacyFileWriterService.cpp
IO/mitkLocaleSwitch.cpp
- IO/mitkLog.cpp
+ IO/mitkLogBackend.cpp
IO/mitkMimeType.cpp
IO/mitkMimeTypeProvider.cpp
IO/mitkOperation.cpp
IO/mitkPixelType.cpp
IO/mitkPointSetReaderService.cpp
IO/mitkPointSetWriterService.cpp
IO/mitkProportionalTimeGeometryToXML.cpp
IO/mitkRawImageFileReader.cpp
IO/mitkStandardFileLocations.cpp
IO/mitkSurfaceStlIO.cpp
IO/mitkSurfaceVtkIO.cpp
IO/mitkSurfaceVtkLegacyIO.cpp
IO/mitkSurfaceVtkXmlIO.cpp
IO/mitkUtf8Util.cpp
IO/mitkVtkLoggingAdapter.cpp
IO/mitkPreferenceListReaderOptionsFunctor.cpp
IO/mitkIOMetaInformationPropertyConstants.cpp
IO/mitkIPreferences.cpp
IO/mitkPreferences.cpp
IO/mitkIPreferencesService.cpp
IO/mitkPreferencesService.cpp
IO/mitkIPreferencesStorage.cpp
IO/mitkXMLPreferencesStorage.cpp
Rendering/mitkAbstractAnnotationRenderer.cpp
Rendering/mitkAnnotationUtils.cpp
Rendering/mitkBaseRenderer.cpp
Rendering/mitkBaseRendererHelper.cpp
Rendering/mitkCrosshairVtkMapper2D.cpp
Rendering/mitkGradientBackground.cpp
Rendering/mitkImageVtkMapper2D.cpp
Rendering/mitkMapper.cpp
Rendering/mitkAnnotation.cpp
Rendering/mitkPlaneGeometryDataMapper2D.cpp
Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp
Rendering/mitkPointSetVtkMapper2D.cpp
Rendering/mitkPointSetVtkMapper3D.cpp
Rendering/mitkRenderWindowBase.cpp
Rendering/mitkRenderWindow.cpp
Rendering/mitkRenderWindowFrame.cpp
Rendering/mitkSurfaceVtkMapper2D.cpp
Rendering/mitkSurfaceVtkMapper3D.cpp
Rendering/mitkVideoRecorder.cpp
Rendering/mitkVtkEventProvider.cpp
Rendering/mitkVtkMapper.cpp
Rendering/mitkVtkPropRenderer.cpp
Rendering/mitkVtkWidgetRendering.cpp
Rendering/vtkMitkLevelWindowFilter.cpp
Rendering/vtkMitkRectangleProp.cpp
Rendering/vtkMitkRenderProp.cpp
Rendering/vtkMitkThickSlicesFilter.cpp
Rendering/vtkNeverTranslucentTexture.cpp
)
set(RESOURCE_FILES
Interactions/globalConfig.xml
Interactions/DisplayInteraction.xml
Interactions/DisplayConfigMITKBase.xml
Interactions/DisplayConfigPACSBase.xml
Interactions/DisplayConfigCrosshair.xml
Interactions/DisplayConfigRotation.xml
Interactions/DisplayConfigActivateCoupling.xml
Interactions/DisplayConfigSwivel.xml
Interactions/DisplayConfigPACSPan.xml
Interactions/DisplayConfigPACSScroll.xml
Interactions/DisplayConfigPACSZoom.xml
Interactions/DisplayConfigPACSLevelWindow.xml
Interactions/DisplayConfigBlockLMB.xml
Interactions/PointSet.xml
Interactions/PointSetConfig.xml
mitkLevelWindowPresets.xml
mitkAnatomicalStructureColorPresets.xml
)
diff --git a/Modules/Core/include/mitkBaseController.h b/Modules/Core/include/mitkBaseController.h
index 41d8307e65..f0b33dc004 100644
--- a/Modules/Core/include/mitkBaseController.h
+++ b/Modules/Core/include/mitkBaseController.h
@@ -1,77 +1,69 @@
/*============================================================================
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 mitkBaseController_h
#define mitkBaseController_h
#include "mitkEventStateMachine.h"
#include "mitkOperationActor.h"
#include "mitkStepper.h"
#include <MitkCoreExports.h>
#include <itkObjectFactory.h>
namespace mitk
{
class BaseRenderer;
- //##Documentation
- //## @brief Baseclass for renderer slice-/camera-control
- //##
- //## Tells the render (subclass of BaseRenderer) which slice (subclass
- //## SliceNavigationController) or from which direction (subclass
- //## CameraController) it has to render. Contains two Stepper for stepping
- //## through the slices or through different camera views (e.g., for the
- //## creation of a movie around the data), respectively, and through time, if
- //## there is 3D+t data.
- //## @note not yet implemented
- //## @ingroup NavigationControl
+ /**
+ * \brief Baseclass for renderer slice-/camera-/time-control
+ *
+ * Tells the renderer (subclass of BaseRenderer) which slice (SliceNavigationController),
+ * which direction (CameraController) or which time (TimeNavigationController) it has to render.
+ * Contains a Stepper for stepping through the slices, through different
+ * camera views (e.g., for the creation of a movie around the data)
+ * and through time, if there is 3D+t data.
+ */
class MITKCORE_EXPORT BaseController : public OperationActor, public itk::Object
{
public:
- /** Standard class typedefs. */
+
mitkClassMacroItkParent(BaseController, OperationActor);
itkFactorylessNewMacro(Self);
- //##Documentation
- //## @brief Get the Stepper through the slices
- Stepper *GetSlice();
- const Stepper* GetSlice() const;
-
- //##Documentation
- //## @brief Get the Stepper through the time
- Stepper *GetTime();
- const Stepper* GetTime() const;
+ /**
+ * \brief Get the stepper through the corresponding dimension.
+ */
+ Stepper* GetStepper();
+ const Stepper* GetStepper() const;
protected:
/**
* @brief Default Constructor
**/
BaseController();
/**
* @brief Default Destructor
**/
~BaseController() override;
void ExecuteOperation(Operation *) override;
- //## @brief Stepper through the time
- Stepper::Pointer m_Time;
- //## @brief Stepper through the slices
- Stepper::Pointer m_Slice;
+ //## @brief Stepper through the different dimensions
+ Stepper::Pointer m_Stepper;
unsigned long m_LastUpdateTime;
};
} // namespace mitk
#endif
diff --git a/Modules/Core/include/mitkBaseRenderer.h b/Modules/Core/include/mitkBaseRenderer.h
index f89e5bac0c..a6ad38fd83 100644
--- a/Modules/Core/include/mitkBaseRenderer.h
+++ b/Modules/Core/include/mitkBaseRenderer.h
@@ -1,505 +1,506 @@
/*============================================================================
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 mitkBaseRenderer_h
#define mitkBaseRenderer_h
#include <mitkDataStorage.h>
#include <mitkPlaneGeometry.h>
#include <mitkPlaneGeometryData.h>
#include <mitkTimeGeometry.h>
#include <mitkCameraController.h>
#include <mitkCameraRotationController.h>
#include <mitkSliceNavigationController.h>
+#include <mitkTimeNavigationController.h>
#include <mitkBindDispatcherInteractor.h>
#include <mitkDispatcher.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <map>
#include <set>
namespace mitk
{
class Mapper;
class BaseLocalStorageHandler;
#pragma GCC visibility push(default)
itkEventMacroDeclaration(RendererResetEvent, itk::AnyEvent);
#pragma GCC visibility pop
/*
* \brief Organizes the rendering process
*
* A BaseRenderer contains a reference to a given vtkRenderWindow
* and a corresponding vtkRenderer.
* The BaseRenderer defines which mapper should be used (2D / 3D)
* and which view direction should be rendered.
*
* All existing BaseRenderer are stored in a static variable
* that can be accessed / modified via the static functions.
* VtkPropRenderer is a concrete implementation of a BaseRenderer.
*/
class MITKCORE_EXPORT BaseRenderer : public itk::Object
{
public:
typedef std::map<vtkRenderWindow*, BaseRenderer*> BaseRendererMapType;
static BaseRendererMapType baseRendererMap;
/**
* \brief Defines which kind of mapper (e.g. 2D or 3D) should be used.
*/
enum StandardMapperSlot
{
Standard2D = 1,
Standard3D = 2
};
static BaseRenderer* GetInstance(vtkRenderWindow* renderWindow);
static void AddInstance(vtkRenderWindow* renderWindow, BaseRenderer* baseRenderer);
static void RemoveInstance(vtkRenderWindow* renderWindow);
static BaseRenderer* GetByName(const std::string& name);
static vtkRenderWindow* GetRenderWindowByName(const std::string& name);
/**
* \brief Get a map of specific RenderWindows
*/
static BaseRendererMapType GetSpecificRenderWindows(MapperSlotId mapper);
/**
* \brief Convenience function: Get a map of all 2D RenderWindows
*/
static BaseRendererMapType GetAll2DRenderWindows();
/**
* \brief Convenience function: Get a map of all 3D RenderWindows
*/
static BaseRendererMapType GetAll3DRenderWindows();
mitkClassMacroItkParent(BaseRenderer, itk::Object);
BaseRenderer(const char* name = nullptr, vtkRenderWindow* renderWindow = nullptr);
void RemoveAllLocalStorages();
void RegisterLocalStorageHandler(BaseLocalStorageHandler* lsh);
void UnregisterLocalStorageHandler(BaseLocalStorageHandler* lsh);
virtual void SetDataStorage(DataStorage* storage);
virtual DataStorage::Pointer GetDataStorage() const
{
return m_DataStorage.GetPointer();
}
vtkRenderWindow* GetRenderWindow() const
{
return m_RenderWindow;
}
vtkRenderer* GetVtkRenderer() const
{
return m_VtkRenderer;
}
/**
* \brief Get the dispatcher, which handles events for this base renderer.
*/
Dispatcher::Pointer GetDispatcher() const;
/**
* \brief Set a new size for the render window.
*/
virtual void Resize(int w, int h);
/**
* \brief Initialize the base renderer with a vtk render window.
* Set the new renderer for the camera controller.
*/
virtual void InitRenderer(vtkRenderWindow* renderwindow);
/**
* \brief Set the initial size for the render window.
*/
virtual void InitSize(int w, int h);
virtual void DrawOverlayMouse(Point2D&)
{
MITK_INFO << "BaseRenderer::DrawOverlayMouse() should be in concret implementation OpenGLRenderer." << std::endl;
}
/**
* \brief Set the world time geometry using the given TimeGeometry.
*
* Setting a new world time geometry updates the current world geometry and the
* curent world plane geometry, using the currently selected slice and timestep.
*/
virtual void SetWorldTimeGeometry(const TimeGeometry* geometry);
itkGetConstObjectMacro(WorldTimeGeometry, TimeGeometry);
/**
* \brief Set the interaction reference world time geometry using the given TimeGeometry.
*
* Setting a new interaction reference world time geometry also updates the
* alignment status of the reference geometry, which can be retrieved using
* 'GetReferenceGeometryAligned'.
* Using a nullptr as the interaction reference geomertry implies that
* no requirements on the geometry exist, thus in this case any check
* will result in 'ReferenceGeometryAligned' being true.
*
* \param geometry The reference geometry used for render window interaction.
*/
virtual void SetInteractionReferenceGeometry(const TimeGeometry* geometry);
/**
* \brief Get the current interaction reference geometry.
*/
itkGetConstObjectMacro(InteractionReferenceGeometry, TimeGeometry);
/**
* \brief Return if the reference geometry aligns with the base renderer's world geometry.
* If true, the interaction reference geometry aligns with the base renderer's
* current world geometry. False otherwise.
*/
itkGetMacro(ReferenceGeometryAligned, bool);
/**
* \brief Get the current time-extracted 3D-geometry.
*/
itkGetConstObjectMacro(CurrentWorldGeometry, BaseGeometry);
/**
* \brief Get the current slice-extracted 2D-geometry.
*/
itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry);
virtual bool SetWorldGeometryToDataStorageBounds()
{
return false;
}
/**
* \brief Set the slice that should be used for geometry extraction.
*
* The slice defines the current slice-extracted 2D-geometry (CurrentWorldPlaneGeometry).
* Setting a new slice will update the current world geometry and the
* curent world plane geometry.
*/
virtual void SetSlice(unsigned int slice);
itkGetConstMacro(Slice, unsigned int);
/**
* \brief Set the timestep that should be used for geometry extraction.
*
* The timestep defines the current time-extracted 3D-geometry (CurrentWorldGeometry).
* Setting a new timestep will update the current world geometry and the
* curent world plane geometry.
*/
virtual void SetTimeStep(unsigned int timeStep);
itkGetConstMacro(TimeStep, unsigned int);
/**
* \brief Get the timestep of a BaseData object which
* exists at the time of the currently displayed content.
*
* Returns -1 if there is no data at the current time.
*/
TimeStepType GetTimeStep(const BaseData* data) const;
/**
* \brief Get the time in ms of the currently display content (geometry).
*/
ScalarType GetTime() const;
/**
* \brief Set the world time geometry using the geometry of the given event.
*
* The function is triggered by a SliceNavigationController::GeometrySendEvent.
*/
virtual void SetGeometry(const itk::EventObject& geometrySliceEvent);
/**
* \brief Set the current world plane geometry using the existing current world geometry.
*
* The function is triggered by a SliceNavigationController::GeometryUpdateEvent.
*/
virtual void UpdateGeometry(const itk::EventObject& geometrySliceEvent);
/**
* \brief Set the current slice using "SetSlice" and update the current world geometry
* and the current world plane geometry.
*
* The function is triggered by a SliceNavigationController::GeometrySliceEvent.
*/
virtual void SetGeometrySlice(const itk::EventObject& geometrySliceEvent);
/**
* \brief Set the current time using "SetTimeStep" and update the current world geometry
* and the current world plane geometry.
*
* The function is triggered by a TimeNavigationController::TimeEvent.
*/
virtual void SetGeometryTime(const itk::EventObject& geometryTimeEvent);
itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode);
/**
* \brief Modify the update time of the current world plane geometry and force reslicing.
*/
void SendUpdateSlice();
/**
* \brief Get timestamp of the update time of the current world plane geometry.
*/
itkGetMacro(CurrentWorldPlaneGeometryUpdateTime, unsigned long);
/**
* \brief Get timestamp of the update time of the current timestep.
*/
itkGetMacro(TimeStepUpdateTime, unsigned long);
/**
* \brief Pick a world coordinate (x,y,z) given a display coordinate (x,y).
*
* \warning Not implemented; has to be overwritten in subclasses.
*/
virtual void PickWorldPoint(const Point2D& diplayPosition, Point3D& worldPosition) const = 0;
/**
* \brief Determines the object (mitk::DataNode) closest to the current
* position by means of picking.
*
* \warning Implementation currently empty for 2D rendering; intended to be
* implemented for 3D renderers.
*/
virtual DataNode* PickObject(const Point2D& /*displayPosition*/, Point3D& /*worldPosition*/) const
{
return nullptr;
}
/**
* \brief Get the currently used mapperID.
*/
itkGetMacro(MapperID, MapperSlotId);
itkGetConstMacro(MapperID, MapperSlotId);
/**
* \brief Set the used mapperID.
*/
virtual void SetMapperID(MapperSlotId id);
virtual int* GetSize() const;
virtual int* GetViewportSize() const;
void SetSliceNavigationController(SliceNavigationController* SlicenavigationController);
itkGetObjectMacro(CameraController, CameraController);
itkGetObjectMacro(SliceNavigationController, SliceNavigationController);
itkGetObjectMacro(CameraRotationController, CameraRotationController);
itkGetMacro(EmptyWorldGeometry, bool);
/**
* \brief Getter/Setter for defining if the displayed region should be shifted
* or rescaled if the render window is resized.
*/
itkGetMacro(KeepDisplayedRegion, bool);
itkSetMacro(KeepDisplayedRegion, bool);
/**
* \brief Return the name of the base renderer
*/
const char* GetName() const
{
return m_Name.c_str();
}
/**
* \brief Return the size in x-direction of the base renderer.
*/
int GetSizeX() const
{
return this->GetSize()[0];
}
/**
* \brief Return the size in y-direction of the base renderer.
*/
int GetSizeY() const
{
return this->GetSize()[1];
}
/**
* \brief Return the bounds of the bounding box of the
* current world geometry (time-extracted 3D-geometry).
*
* If the geometry is empty, the bounds are set to zero.
*/
const double* GetBounds() const;
void RequestUpdate();
void ForceImmediateUpdate();
/**
* \brief Return the number of mappers which are visible and have
* level-of-detail rendering enabled.
*/
unsigned int GetNumberOfVisibleLODEnabledMappers() const;
/**
* \brief Convert a display point to the 3D world index
* using the geometry of the renderWindow.
*/
void DisplayToWorld(const Point2D& displayPoint, Point3D& worldIndex) const;
/**
* \brief Convert a display point to the 2D world index, mapped onto the display plane
* using the geometry of the renderWindow.
*/
void DisplayToPlane(const Point2D& displayPoint, Point2D& planePointInMM) const;
/**
* \brief Convert a 3D world index to the display point
* using the geometry of the renderWindow.
*/
void WorldToDisplay(const Point3D& worldIndex, Point2D& displayPoint) const;
/**
* \brief Convert a 3D world index to the point on the viewport
* using the geometry of the renderWindow.
*/
void WorldToView(const Point3D& worldIndex, Point2D& viewPoint) const;
/**
* \brief Convert a 2D plane coordinate to the display point
* using the geometry of the renderWindow.
*/
void PlaneToDisplay(const Point2D& planePointInMM, Point2D& displayPoint) const;
/**
* \brief Convert a 2D plane coordinate to the point on the viewport
* using the geometry of the renderWindow.
*/
void PlaneToView(const Point2D& planePointInMM, Point2D& viewPoint) const;
double GetScaleFactorMMPerDisplayUnit() const;
Point2D GetDisplaySizeInMM() const;
Point2D GetViewportSizeInMM() const;
Point2D GetOriginInMM() const;
itkGetConstMacro(ConstrainZoomingAndPanning, bool)
virtual void SetConstrainZoomingAndPanning(bool constrain);
protected:
~BaseRenderer() override;
virtual void Update() = 0;
vtkRenderWindow* m_RenderWindow;
vtkRenderer* m_VtkRenderer;
MapperSlotId m_MapperID;
DataStorage::Pointer m_DataStorage;
unsigned long m_LastUpdateTime;
CameraController::Pointer m_CameraController;
CameraRotationController::Pointer m_CameraRotationController;
SliceNavigationController::Pointer m_SliceNavigationController;
void UpdateCurrentGeometries();
virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry* geometry2d);
virtual void SetCurrentWorldGeometry(const BaseGeometry *geometry);
private:
/**
* \brief Pointer to the current TimeGeometry.
*
* This WorldTimeGeometry is used to extract a SlicedGeometry3D,
* using the current timestep (set via SetTimeStep).
* The time-extracted 3D-geometry is used as the "CurrentWorldGeometry".
* A PlaneGeometry can further be extracted using the current slice (set via SetSlice).
* The slice-extracted 2D-geometry is used as the "CurrentWorldPlaneGeometry".
*/
TimeGeometry::ConstPointer m_WorldTimeGeometry;
/**
* \brief Pointer to the interaction reference geometry used for interaction.
*
* This InteractionReferenceGeometry is used to decide if a base renderer /
* render window is able to correctly handle display interaction, e.g. drawing.
* It will be set using the "SetInteractionReferenceGeometry"-function.
*/
TimeGeometry::ConstPointer m_InteractionReferenceGeometry;
/**
* \brief Pointer to the current time-extracted 3D-geometry.
*
* This CurrentWorldGeometry is used to define the bounds for this
* BaseRenderer.
* It will be set using the "SetCurrentWorldGeometry"-function.
*/
BaseGeometry::ConstPointer m_CurrentWorldGeometry;
/**
* \brief Pointer to the current slice-extracted 2D-geometry.
*
* This CurrentWorldPlaneGeometry is used to define the maximal
* area (2D manifold) to be rendered in case we are doing 2D-rendering.
* It will be set using the "SetCurrentWorldPlaneGeometry"-function.
*/
PlaneGeometry::Pointer m_CurrentWorldPlaneGeometry;
unsigned int m_Slice;
unsigned int m_TimeStep;
itk::TimeStamp m_CurrentWorldPlaneGeometryUpdateTime;
itk::TimeStamp m_TimeStepUpdateTime;
BindDispatcherInteractor* m_BindDispatcherInteractor;
bool m_KeepDisplayedRegion;
bool m_ReferenceGeometryAligned;
protected:
void PrintSelf(std::ostream& os, itk::Indent indent) const override;
PlaneGeometryData::Pointer m_CurrentWorldPlaneGeometryData;
DataNode::Pointer m_CurrentWorldPlaneGeometryNode;
unsigned long m_CurrentWorldPlaneGeometryTransformTime;
std::string m_Name;
double m_Bounds[6];
bool m_EmptyWorldGeometry;
typedef std::set<Mapper*> LODEnabledMappersType;
unsigned int m_NumberOfVisibleLODEnabledMappers;
std::list<BaseLocalStorageHandler*> m_RegisteredLocalStorageHandlers;
bool m_ConstrainZoomingAndPanning;
};
} // namespace mitk
#endif
diff --git a/Modules/Core/include/mitkCommon.h b/Modules/Core/include/mitkCommon.h
index 1d1cfa5d76..8651516b80 100644
--- a/Modules/Core/include/mitkCommon.h
+++ b/Modules/Core/include/mitkCommon.h
@@ -1,196 +1,196 @@
/*============================================================================
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 mitkCommon_h
#define mitkCommon_h
#ifdef _MSC_VER
// This warns about truncation to 255 characters in debug/browse info
#pragma warning(disable : 4786)
#pragma warning(disable : 4068) /* disable unknown pragma warnings */
#endif
// add only those headers here that are really necessary for all classes!
#include "itkObject.h"
#include "mitkConfig.h"
#include "mitkExceptionMacro.h"
#include "mitkGetClassHierarchy.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
typedef unsigned int MapperSlotId;
/** From ITK 4.7 version, the TypeMacro overrides (by using the explicit attribute) the GetNameOfClass
* hence the SuperClass must provide one.
*
* If not, use the mitkClassMacroNoParent version
*/
#define mitkClassMacro(className, SuperClassName) \
typedef className Self; \
typedef SuperClassName Superclass; \
typedef itk::SmartPointer<Self> Pointer; \
typedef itk::SmartPointer<const Self> ConstPointer; \
static const char *GetStaticNameOfClass() { return #className; } \
virtual std::vector<std::string> GetClassHierarchy() const override { return mitk::GetClassHierarchy<Self>(); } \
itkTypeMacro(className, SuperClassName);
#define mitkClassMacroItkParent(className, SuperClassName) \
typedef className Self; \
typedef SuperClassName Superclass; \
typedef itk::SmartPointer<Self> Pointer; \
typedef itk::SmartPointer<const Self> ConstPointer; \
static const char *GetStaticNameOfClass() { return #className; } \
virtual std::vector<std::string> GetClassHierarchy() const { return mitk::GetClassHierarchy<Self>(); } \
itkTypeMacro(className, SuperClassName);
/** At version 4.7 provides two type macros, the normal one expects the Superclass to provide the
* GetNameOfClass explicitly, the NoParent deos not expect anything.
*/
#define mitkClassMacroNoParent(className) \
typedef className Self; \
typedef itk::SmartPointer<Self> Pointer; \
typedef itk::SmartPointer<const Self> ConstPointer; \
static const char *GetStaticNameOfClass() { return #className; } \
virtual std::vector<std::string> GetClassHierarchy() const { return mitk::GetClassHierarchy<Self>(); } \
itkTypeMacroNoParent(className)
/**
* Macro for Constructors with one parameter for classes derived from itk::Lightobject
**/
#define mitkNewMacro1Param(classname, type) \
\
static Pointer New(type _arg) \
\
{ \
Pointer smartPtr = new classname(_arg); \
smartPtr->UnRegister(); \
return smartPtr; \
}
/**
* Macro for Constructors with two parameters for classes derived from itk::Lightobject
**/
#define mitkNewMacro2Param(classname, typea, typeb) \
\
static Pointer New(typea _arga, typeb _argb) \
\
{ \
Pointer smartPtr = new classname(_arga, _argb); \
smartPtr->UnRegister(); \
return smartPtr; \
}
/**
* Macro for Constructors with three parameters for classes derived from itk::Lightobject
**/
#define mitkNewMacro3Param(classname, typea, typeb, typec) \
\
static Pointer New(typea _arga, typeb _argb, typec _argc) \
\
{ \
Pointer smartPtr = new classname(_arga, _argb, _argc); \
smartPtr->UnRegister(); \
return smartPtr; \
}
/**
* Macro for Constructors with four parameters for classes derived from itk::Lightobject
**/
#define mitkNewMacro4Param(classname, typea, typeb, typec, typed) \
\
static Pointer New(typea _arga, typeb _argb, typec _argc, typed _argd) \
\
{ \
Pointer smartPtr = new classname(_arga, _argb, _argc, _argd); \
smartPtr->UnRegister(); \
return smartPtr; \
}
/**
* Macro for Constructors with five parameters for classes derived from itk::Lightobject
**/
#define mitkNewMacro5Param(classname, typea, typeb, typec, typed, typee) \
\
static Pointer New(typea _arga, typeb _argb, typec _argc, typed _argd, typee _arge) \
\
{ \
Pointer smartPtr = new classname(_arga, _argb, _argc, _argd, _arge); \
smartPtr->UnRegister(); \
return smartPtr; \
}
/**
* Macro for Constructors with six parameters for classes derived from itk::Lightobject
**/
#define mitkNewMacro6Param(classname, typea, typeb, typec, typed, typee, typef) \
\
static Pointer New(typea _arga, typeb _argb, typec _argc, typed _argd, typee _arge, typef _argf) \
\
{ \
Pointer smartPtr = new classname(_arga, _argb, _argc, _argd, _arge, _argf); \
smartPtr->UnRegister(); \
return smartPtr; \
}
/** Get a smart const pointer to an object. Creates the member
* Get"name"() (e.g., GetPoints()). */
#define mitkGetObjectMacroConst(name, type) \
virtual type *Get##name() const \
{ \
itkDebugMacro("returning " #name " address " << this->m_##name); \
return this->m_##name.GetPointer(); \
}
/** Creates a Clone() method for "Classname". Returns a smartPtr of a clone of the
calling object*/
#define mitkCloneMacro(classname) \
virtual itk::LightObject::Pointer InternalClone() const override \
\
{ \
Pointer smartPtr = new classname(*this); \
smartPtr->UnRegister(); \
return smartPtr.GetPointer(); \
}
/** cross-platform deprecation macro
\todo maybe there is something in external toolkits (ITK, VTK,...) that we could reulse -- would be much preferable
*/
#ifdef MITK_NO_DEPRECATED_WARNINGS
#define DEPRECATED(func) func
#elif defined(__GNUC__)
#define DEPRECATED(...) __VA_ARGS__ __attribute__((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(...) __declspec(deprecated)##__VA_ARGS__
#else
#pragma message("WARNING: You need to implement DEPRECATED for your compiler!")
#define DEPRECATED(func) func
#endif
/**
* Mark templates as exported to generate public RTTI symbols which are
* needed for GCC and Clang to support e.g. dynamic_cast between DSOs.
*/
#if defined(__clang__) || defined(__GNUC__)
#define MITK_EXPORT __attribute__((visibility("default")))
#define MITK_IMPORT __attribute__((visibility("default")))
#define MITK_LOCAL __attribute__((visibility("hidden")))
#elif defined(WIN32)
#define MITK_EXPORT __declspec(dllexport)
#define MITK_IMPORT __declspec(dllimport)
#define MITK_LOCAL
#else
#define MITK_EXPORT
#define MITK_IMPORT
#define MITK_LOCAL
#endif
#endif
diff --git a/Modules/Core/include/mitkCoreObjectFactoryBase.h b/Modules/Core/include/mitkCoreObjectFactoryBase.h
index 06dd3db6ed..27c65ee386 100644
--- a/Modules/Core/include/mitkCoreObjectFactoryBase.h
+++ b/Modules/Core/include/mitkCoreObjectFactoryBase.h
@@ -1,91 +1,91 @@
/*============================================================================
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 mitkCoreObjectFactoryBase_h
#define mitkCoreObjectFactoryBase_h
-// the mbilog header is necessary for CMake test drivers.
+// the mitkLog.h header is necessary for CMake test drivers.
// Since the EXTRA_INCLUDE parameter of CREATE_TEST_SOURCELIST only
// allows one extra include file, we specify mitkLog.h here so it will
// be available to all classes implementing this interface.
-#include "mitkLog.h"
+#include <mitkLog.h>
#include "mitkFileWriterWithInformation.h"
#include "mitkMapper.h"
#include <MitkCoreExports.h>
#include <itkObjectFactoryBase.h>
#include <itkVersion.h>
namespace mitk
{
class DataNode;
//## @brief base-class for factories of certain mitk objects.
//## @ingroup Algorithms
//## This interface can be implemented by factories which add new mapper classes or extend the
//## data tree deserialization mechanism.
class MITKCORE_EXPORT CoreObjectFactoryBase : public itk::Object
{
public:
typedef std::list<mitk::FileWriterWithInformation::Pointer> FileWriterList;
typedef std::multimap<std::string, std::string> MultimapType;
mitkClassMacroItkParent(CoreObjectFactoryBase, itk::Object);
virtual Mapper::Pointer CreateMapper(mitk::DataNode *node, MapperSlotId slotId) = 0;
virtual void SetDefaultProperties(mitk::DataNode *node) = 0;
/**
* @deprecatedSince{2014_10} See mitk::FileReaderRegistry and QmitkIOUtil
*/
virtual std::string GetFileExtensions() = 0;
/**
* @deprecatedSince{2014_10} See mitk::FileReaderRegistry and QmitkIOUtil
*/
virtual MultimapType GetFileExtensionsMap() = 0;
/**
* @deprecatedSince{2014_10} See mitk::FileWriterRegistry and QmitkIOUtil
*/
virtual std::string GetSaveFileExtensions() = 0;
/**
* @deprecatedSince{2014_10} See mitk::FileWriterRegistry and QmitkIOUtil
*/
virtual MultimapType GetSaveFileExtensionsMap() = 0;
virtual const char *GetITKSourceVersion() const { return ITK_SOURCE_VERSION; }
virtual const char *GetDescription() const { return "Core Object Factory"; }
/**
* @deprecatedSince{2014_10} See mitk::FileWriterRegistry
*/
FileWriterList GetFileWriters() { return m_FileWriters; }
protected:
/**
* @brief create a string from a map that contains the file extensions
* @param fileExtensionsMap input map with the file extensions, e.g. ("*.dcm", "DICOM files")("*.dc3", "DICOM
* files")
* @param fileExtensions the converted output string, suitable for the QT QFileDialog widget
* e.g. "all (*.dcm *.DCM *.dc3 ... *.vti *.hdr *.nrrd *.nhdr );;ODF Images (*.odf *qbi)"
*
* @deprecatedSince{2014_10}
*/
static void CreateFileExtensions(MultimapType fileExtensionsMap, std::string &fileExtensions);
FileWriterList m_FileWriters;
friend class CoreObjectFactory;
};
}
#endif
diff --git a/Modules/Core/include/mitkCoreServices.h b/Modules/Core/include/mitkCoreServices.h
index 2fc123f3e3..ce30201441 100644
--- a/Modules/Core/include/mitkCoreServices.h
+++ b/Modules/Core/include/mitkCoreServices.h
@@ -1,187 +1,187 @@
/*============================================================================
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 mitkCoreServices_h
#define mitkCoreServices_h
#include "MitkCoreExports.h"
#include <mitkCommon.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkServiceInterface.h>
#include <usGetModuleContext.h>
#include <usModuleContext.h>
#include <usServiceReference.h>
#include <cassert>
namespace mitk
{
struct IMimeTypeProvider;
class IPropertyAliases;
class IPropertyDescriptions;
class IPropertyExtensions;
class IPropertyFilters;
class IPropertyPersistence;
class IPropertyRelations;
class IPreferencesService;
/**
* @brief Access MITK core services.
*
* This class can be used to conveniently access common
* MITK Core service objects. Some getter methods where implementations
* exist in the core library are guaranteed to return a non-nullptr service object.
*
* To ensure that CoreServices::Unget() is called after the caller
* has finished using a service object, you should use the CoreServicePointer
* helper class which calls Unget() when it goes out of scope:
*
* \code
* CoreServicePointer<IShaderRepository> shaderRepo(CoreServices::GetShaderRepository());
* // Do something with shaderRepo
* \endcode
*
* @see CoreServicePointer
*/
class MITKCORE_EXPORT CoreServices
{
public:
/**
* @brief Get an IPropertyAliases instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IPropertyAliases instance.
*/
static IPropertyAliases *GetPropertyAliases(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Get an IPropertyDescriptions instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IPropertyDescriptions instance.
*/
static IPropertyDescriptions *GetPropertyDescriptions(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Get an IPropertyExtensions instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IPropertyExtensions instance.
*/
static IPropertyExtensions *GetPropertyExtensions(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Get an IPropertyFilters instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IPropertyFilters instance.
*/
static IPropertyFilters *GetPropertyFilters(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Get an IPropertyPersistence instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IPropertyPersistence instance.
*/
static IPropertyPersistence *GetPropertyPersistence(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Get an IPropertyRelations instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IPropertyRelations instance.
*/
static IPropertyRelations *GetPropertyRelations(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Get an IMimeTypeProvider instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IMimeTypeProvider instance.
*/
static IMimeTypeProvider *GetMimeTypeProvider(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Get an IPreferencesService instance.
* @param context The module context of the module getting the service.
* @return A non-nullptr IPreferencesService instance.
* @sa IPreferences
*/
static IPreferencesService *GetPreferencesService(us::ModuleContext *context = us::GetModuleContext());
/**
* @brief Unget a previously acquired service instance.
* @param service The service instance to be released.
* @param context
* @return \c true if ungetting the service was successful, \c false otherwise.
*/
template <class S>
static bool Unget(S *service, us::ModuleContext *context = us::GetModuleContext())
{
return Unget(context, us_service_interface_iid<S>(), service);
}
private:
static bool Unget(us::ModuleContext *context, const std::string &interfaceId, void *service);
// purposely not implemented
CoreServices();
CoreServices(const CoreServices &);
CoreServices &operator=(const CoreServices &);
};
/**
* @brief A RAII helper class for core service objects.
*
* This is class is intended for usage in local scopes; it calls
* CoreServices::Unget(S*) in its destructor. You should not construct
* multiple CoreServicePointer instances using the same service pointer,
* unless it is retrieved by a new call to a CoreServices getter method.
*
* @see CoreServices
*/
template <class S>
class MITK_LOCAL CoreServicePointer
{
public:
explicit CoreServicePointer(S *service, us::ModuleContext* context = us::GetModuleContext())
: m_Service(service),
m_Context(context)
{
assert(service);
}
~CoreServicePointer()
{
try
{
CoreServices::Unget(m_Service, m_Context);
}
catch (const std::exception &e)
{
MITK_ERROR << e.what();
}
catch (...)
{
MITK_ERROR << "Ungetting core service failed.";
}
}
S *operator->() const
{
return m_Service;
}
private:
S *const m_Service;
us::ModuleContext* m_Context;
};
}
#endif
diff --git a/Modules/Core/include/mitkEqual.h b/Modules/Core/include/mitkEqual.h
index 03145da33d..aa7b9c39d3 100644
--- a/Modules/Core/include/mitkEqual.h
+++ b/Modules/Core/include/mitkEqual.h
@@ -1,78 +1,78 @@
/*============================================================================
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 mitkEqual_h
#define mitkEqual_h
#include <cmath>
#include <iomanip>
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include "mitkNumericConstants.h"
namespace mitk
{
/**
* Helper method to check if the difference is bigger or equal to a given epsilon
*
* @param diff the difference to be checked against the epsilon
* @param epsilon The absolute difference needs to be smaller than this.
* @return true if abs(diff) >= eps
*/
template <typename DifferenceType>
inline bool DifferenceBiggerOrEqualEps(DifferenceType diff, mitk::ScalarType epsilon = mitk::eps)
{
return std::fabs(diff) >= epsilon;
}
/**
* outputs elem1, elem2 and eps in case verbose and !isEqual.
* Elem can e.g. be a mitk::Vector or an mitk::Point.
*
* @param elem1 first element to be output
* @param elem2 second
* @param eps the epsilon which their difference was bigger than
* @param verbose tells the function if something shall be output
* @param isEqual function will only output something if the two elements are not equal
*/
template <typename ElementToOutput1, typename ElementToOutput2>
inline void ConditionalOutputOfDifference(
ElementToOutput1 elem1, ElementToOutput2 elem2, mitk::ScalarType eps, bool verbose, bool isEqual)
{
if (verbose && !isEqual)
{
MITK_INFO << typeid(ElementToOutput1).name() << " and " << typeid(ElementToOutput2).name()
<< " not equal. Lefthandside " << std::setprecision(12) << elem1 << " - Righthandside " << elem2
<< " - epsilon " << eps;
}
}
/**
* @ingroup MITKTestingAPI
*
* @param scalar1 Scalar value to compare.
* @param scalar2 Scalar value to compare.
* @param eps Tolerance for floating point comparison.
* @param verbose Flag indicating detailed console output.
* @return True if scalars are equal.
*/
inline bool Equal(ScalarType scalar1, ScalarType scalar2, ScalarType eps = mitk::eps, bool verbose = false)
{
bool isEqual(!DifferenceBiggerOrEqualEps(scalar1 - scalar2, eps));
ConditionalOutputOfDifference(scalar1, scalar2, eps, verbose, isEqual);
return isEqual;
}
}
#endif
diff --git a/Modules/Core/include/mitkException.h b/Modules/Core/include/mitkException.h
index 2ae365b6a3..e4ac635604 100644
--- a/Modules/Core/include/mitkException.h
+++ b/Modules/Core/include/mitkException.h
@@ -1,115 +1,115 @@
/*============================================================================
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 mitkException_h
#define mitkException_h
#include <MitkCoreExports.h>
#include <itkMacro.h>
#include <vector>
namespace mitk
{
/**Documentation
* \brief An object of this class represents an exception of MITK.
* Please don't instantiate exceptions manually, but use the
* exception macros (file mitkExceptionMacro.h) instead.
* Simple use in your code is:
*
* mitkThrow() << "optional exception message";
*
* You can also define specialized exceptions which must inherit
* from this class. Please always use the mitkExceptionClassMacro
* when implementing specialized exceptions. A simple implementation
* can look like:
*
* class MyException : public mitk::Exception
* {
* public:
* mitkExceptionClassMacro(MyException,mitk::Exception);
* };
*
* You can then throw your specialized exceptions by using the macro
*
* mitkThrowException(MyException) << "optional exception message";
*/
class MITKCORE_EXPORT Exception : public itk::ExceptionObject
{
public:
Exception(const char *file, unsigned int lineNumber = 0, const char *desc = "None", const char *loc = "Unknown")
: itk::ExceptionObject(file, lineNumber, desc, loc)
{
}
~Exception() throw() override {}
itkTypeMacro(ClassName, SuperClassName);
/** \brief Adds rethrow data to this exception. */
void AddRethrowData(const char *file, unsigned int lineNumber, const char *message);
/** \return Returns how often the exception was rethrown. */
int GetNumberOfRethrows();
- /** @return Returns the rethrow data of the specified rethrow number. Returns empty data, if the rethrowNumber
+ /** Returns the rethrow data of the specified rethrow number. Returns empty data, if the rethrowNumber
* doesn't
* exist.
* @param rethrowNumber The internal number of the rethrow.
* @param file (returnvalue) This variable will be filled with the file of the specified rethrow.
* @param line (returnvalue) This variable will be filled with the line of the specified rethrow.
* @param message (returnvalue) This variable will be filled with the message of the specified rethrow.
*/
void GetRethrowData(int rethrowNumber, std::string &file, int &line, std::string &message);
/** \brief Definition of the bit shift operator for this class.*/
template <class T>
inline Exception &operator<<(const T &data)
{
std::stringstream ss;
ss << this->GetDescription() << data;
this->SetDescription(ss.str());
return *this;
}
/** \brief Definition of the bit shift operator for this class (for non const data).*/
template <class T>
inline Exception &operator<<(T &data)
{
std::stringstream ss;
ss << this->GetDescription() << data;
this->SetDescription(ss.str());
return *this;
}
/** \brief Definition of the bit shift operator for this class (for functions).*/
inline Exception &operator<<(std::ostream &(*func)(std::ostream &))
{
std::stringstream ss;
ss << this->GetDescription() << func;
this->SetDescription(ss.str());
return *this;
}
protected:
struct ReThrowData
{
std::string RethrowClassname;
unsigned int RethrowLine;
std::string RethrowMessage;
};
std::vector<ReThrowData> m_RethrowData;
};
MITKCORE_EXPORT std::ostream &operator<<(std::ostream &os, const mitk::Exception &e);
} // namespace mitk
#endif
diff --git a/Modules/Core/include/mitkExceptionMacro.h b/Modules/Core/include/mitkExceptionMacro.h
index 80809b012c..cb7aebe2d6 100644
--- a/Modules/Core/include/mitkExceptionMacro.h
+++ b/Modules/Core/include/mitkExceptionMacro.h
@@ -1,95 +1,95 @@
/*============================================================================
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 mitkExceptionMacro_h
#define mitkExceptionMacro_h
#include "mitkException.h"
#include <itkMacro.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <sstream>
/** The exception macro is used to throw an exception
* (i.e., usually a condition that results in program failure).
*
* Example usage looks like:
* mitkThrow() << "this is error info";
*/
#define mitkThrow() throw mitk::Exception(__FILE__, __LINE__, "", ITK_LOCATION)
/** The rethrow macro is used to rethrow an existing exception. The
* rethrow information (file,line of code) is then additionally stored
* in the exception. To check if an exception was rethrown you can use
* the methods GetNumberOfRethrows() and GetRethrowData().
*
* Example usage:
* try
* {
* //some code that throws an exception
* }
* catch(mitk::Exception e)
* {
* //here we want to rethrow the exception
* mitkReThrow(e) << "Message that will be appended to the exception (optional)";
* }
*/
#define mitkReThrow(mitkexception) \
mitkexception.AddRethrowData(__FILE__, __LINE__, "Rethrow by mitkReThrow macro."); \
throw mitkexception
/** The specialized exception macro is used to throw exceptions
* in cases of specialized errors. This means the second parameter must be a class which
* inherits from mitk::Exception. An object of this exception is thrown when using the macro.
* Thus, more differentiated excaptions can be thrown, when needed.
*
* Example usage:
* mitkSpecializedExceptionMacro(mitk::MySpecializedException) << "this is error info";
*/
#define mitkThrowException(classname) throw classname(__FILE__, __LINE__, "", ITK_LOCATION)
/** Class macro for MITK exception classes.
* All MITK exception classes should derive from MITK::Exception.
*/
#define mitkExceptionClassMacro(ClassName, SuperClassName) \
ClassName(const char *file, unsigned int lineNumber, const char *desc, const char *loc) \
: SuperClassName(file, lineNumber, desc, loc) \
{ \
} \
itkTypeMacro(ClassName, SuperClassName); \
/** \brief Definition of the bit shift operator for this class. It can be used to add messages.*/ \
template <class T> \
inline ClassName &operator<<(const T &data) \
{ \
std::stringstream ss; \
ss << this->GetDescription() << data; \
this->SetDescription(ss.str()); \
return *this; \
} \
/** \brief Definition of the bit shift operator for this class (for non const data).*/ \
template <class T> \
inline ClassName &operator<<(T &data) \
{ \
std::stringstream ss; \
ss << this->GetDescription() << data; \
this->SetDescription(ss.str()); \
return *this; \
} \
/** \brief Definition of the bit shift operator for this class (for functions).*/ \
inline ClassName &operator<<(std::ostream &(*func)(std::ostream &)) \
{ \
std::stringstream ss; \
ss << this->GetDescription() << func; \
this->SetDescription(ss.str()); \
return *this; \
}
#endif
diff --git a/Modules/Core/include/mitkInteractionConst.h b/Modules/Core/include/mitkInteractionConst.h
index e83f33b429..0df91c3715 100644
--- a/Modules/Core/include/mitkInteractionConst.h
+++ b/Modules/Core/include/mitkInteractionConst.h
@@ -1,776 +1,762 @@
/*============================================================================
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 mitkInteractionConst_h
#define mitkInteractionConst_h
//##Documentation
//## @file mitkInteractionConst.h
//## @brief Constants for most interaction classes, due to the generic StateMachines.
//##
//## Changes in Type, ButtonState or Key has to be don in mitkEventMapper.cpp, too.
//## @ingroup Interaction
/*Prefixes for Constants:
E = Enumeration
EID = EventId's
Op = Operations
Ac = Action
Type_ = Type of Event
BS_ = ButtonStates and Buttons
Key_ = Keys like in QT
*/
namespace mitk
{
// Constants for EventIds; use the according constant to through an event in the code
enum EEventIds
{
EIDNULLEVENT = 0,
EIDLEFTMOUSEBTN = 1,
EIDRIGHTMOUSEBTN = 2,
EIDLEFTMOUSEBTNANDSHIFT = 3,
EIDMIDDLEMOUSEBTN = 4,
EIDLEFTMOUSEBTNANDCTRL = 5,
EIDMIDDLEMOUSEBTNANDCTRL = 6,
EIDRIGHTMOUSEBTNANDCTRL = 7,
EIDLEFTMOUSEBTNDOUBLECLICK = 8,
EIDMOUSEWHEEL = 9,
EIDLEFTMOUSERELEASE = 505,
EIDMIDDLEMOUSERELEASE = 506,
EIDRIGHTMOUSERELEASE = 507,
EIDLEFTMOUSERELEASEANDSHIFT = 508,
EIDMOUSEMOVE = 520,
EIDLEFTMOUSEBTNANDMOUSEWHEEL = 521,
EIDRIGHTMOUSEBTNANDMOUSEWHEEL = 522,
EIDMIDDLEMOUSEBTNANDMOUSEWHEEL = 523,
EIDLEFTMOUSEBTNANDMOUSEMOVE = 530,
EIDRIGHTMOUSEBTNANDMOUSEMOVE = 531,
EIDMIDDLEMOUSEBTNANDMOUSEMOVE = 533,
EIDCTRLANDLEFTMOUSEBTNANDMOUSEMOVE = 534,
EIDCTRLANDRIGHTMOUSEBTNANDMOUSEMOVE = 535,
EIDCTRLANDMIDDLEMOUSEBTNANDMOUSEMOVE = 536,
EIDCTRLANDLEFTMOUSEBTNRELEASE = 537,
EIDCTRLANDRIGHTMOUSEBTNRELEASE = 538,
EIDCTRLANDMIDDLEMOUSEBTNRELEASE = 539,
EIDSHIFTANDCTRLANDMIDDLEMOUSEBTN = 540,
EIDSHIFTANDLEFTMOUSEBTNANDMOUSEMOVE = 541,
EIDSHIFTANDCTRLANDMOUSEMOVE = 542,
EIDSHIFTANDCTRLANDMOUSERELEASE = 543,
EIDALTANDLEFTMOUSEBTN = 600,
EIDALTANDLEFTMOUSEBTNANDMOUSEMOVE = 610,
EIDALTANDLEFTMOUSERELEASE = 620,
EIDCTRLANDLEFTMOUSEWHEEL = 630,
EIDALTANDMOUSEWHEEL = 640,
EIDALTANDMIDDLEMOUSEBTN = 641,
EIDALTANDMIDDLEMOUSEBTNANDMOVE = 642,
EIDALTANDMIDDLEMOUSEBTNRELEASE = 643,
EIDALTANDSHIFTANDRIGHTMOUSEBTN = 644,
EIDALTANDSHIFTANDRIGHTMOUSEBTNANDMOUSEMOVE = 645,
EIDALTANDSHIFTANDRIGHTMOUSEBTNRELEASE = 646,
EIDSHIFTANDRIGHTMOUSEPRESS = 2000,
EIDSHIFTANDRIGHTMOUSEMOVE = 2001,
EIDSHIFTANDRIGHTMOUSERELEASE = 2002,
EIDSHIFTANDMIDDLEMOUSEPRESS = 2003,
EIDSHIFTANDMIDDLEMOUSEMOVE = 2004,
EIDSHIFTANDMIDDLEMOUSERELEASE = 2005,
- EIDSPACENAVIGATORINPUT = 4001, // 3d Mouse, SpaceNavigator input
- EIDSPACENAVIGATORKEYDOWN = 4002, // 3d Mouse, KeyDown
- EIDWIIMOTEINPUT = 4003, // WiiMote input
- EIDWIIMOTEBUTTON = 4004, // WiiMote home button
- EIDWIIMOTEBUTTONB = 4005, // WiiMote b button
EIDSTRGANDN = 10,
EIDSTRGANDE = 11,
EIDDELETE = 12,
EIDN = 13,
EIDESCAPE = 14,
EIDP = 15,
EIDR = 16,
EIDT = 17,
EIDS = 18,
EIDE = 19,
EIDSTRGANDALTANDA = 20,
EIDSTRGANDALTANDB = 21,
EIDH = 22,
EIDRETURN = 23,
EIDENTER = 24,
EIDSPACE = 25,
EIDPLUS = 26,
EIDMINUS = 27,
EIDSTRGANDALTANDH = 30,
EIDSTRGANDALTANDI = 31,
EIDSTRGANDALTANDS = 40,
EIDALT = 90,
EIDSTRGANDB = 91,
EIDNEW = 1000,
EIDOLD = 1001,
EIDFINISHED = 1002,
EIDNO = 1003,
EIDYES = 1004,
EIDSAME = 1005,
EIDNOANDLASTOBJECT = 1006,
EIDNOANDNOTLASTOBJECT = 1007,
EIDLAST = 1008,
EIDNOTLAST = 1009,
EIDSTSMALERNMINUS1 = 1010,
EIDSTLARGERNMINUS1 = 1011,
EIDPOSITIONEVENT = 1012,
EIDEDIT = 1013,
EIDSMALLERN = 1014,
EIDEQUALSN = 1015,
EIDLARGERN = 1016,
EIDEMPTY = 1017,
EIDSUBDESELECT = 1020,
EIDSMTOSELECTED = 1030,
EIDSMTODESELECTED = 1031,
EIDTIP = 1050,
EIDHEAD = 1051,
EIDBODY = 1052,
EIDCLEAR = 1100,
EIDACTIVATETOOL = 1300,
EIDPRINT = 3001,
EV_INIT = 5551001,
EV_PREVIOUS = 5551002,
EV_PATH_COLLECTION_SELECTED = 5551003,
EV_NAVIGATION_SELECTED = 5551004,
EV_LESS_THEN_MIN_COUNT = 5551005,
EV_READY = 5551006,
EV_NEXT = 5551007,
EV_DONE = 5551008,
EV_NEW_LANDMARK = 5551009,
EV_REMOVE_LANDMARK = 5551010,
EIDINSIDE = 2500,
EIDA = 4001,
EIDB = 4002,
EIDC = 4003,
EIDD = 4004,
EIDF = 4005,
EIDG = 4006,
EIDI = 4007,
EIDJ = 4008,
EIDK = 4009,
EIDL = 4010,
EIDM = 4011,
EIDO = 4012,
EIDQ = 4013,
EIDU = 4014,
EIDV = 4015,
EIDW = 4016,
EIDX = 4017,
EIDY = 4018,
EIDZ = 4019,
EID1 = 4020,
EID2 = 4021,
EID3 = 4022,
EID4 = 4023,
EID5 = 4024,
EID6 = 4025,
EID7 = 4026,
EID8 = 4027,
EID9 = 4028,
EID0 = 4029,
EIDFIGUREHOVER = 12340,
EIDNOFIGUREHOVER = 12341
};
//##Constants for Operations
- //## xomments are always examples of the usage
+ //## comments are always examples of the usage
enum EOperations
{
OpNOTHING = 0,
OpTEST = 1,
OpNEWCELL = 10, // add a new cell
OpADD = 100, // add a point or a vessel
OpUNDOADD = 101,
OpADDLINE = 1001, // add a line
OpINSERT = 200, // insert a point at position
OpINSERTLINE = 201, // insert a line at position
OpINSERTPOINT = 202,
OpCLOSECELL = 250, // close a cell (to a polygon)
OpOPENCELL = 251, // close a cell (to a polygon)
OpMOVE = 300, // move a point
OpMOVELINE = 301, // move a line
OpMOVECELL = 302, // move a line
OpUNDOMOVE = 303,
OpMOVEPOINTUP = 304,
OpMOVEPOINTDOWN = 305,
OpREMOVE = 400, // remove a point at position
OpREMOVELINE = 401, // remove a line at position
OpREMOVECELL = 402, // remove a cell
OpREMOVEPOINT = 403,
OpDELETE = 500, // delete
OpDELETELINE = 501, // delete the last line in a cell
OpUNDELETE = 502,
OpDELETECELL = 505,
OpSTATECHANGE = 600, // change a state
OpTIMECHANGE = 601, // change a state
OpTERMINATE = 666, // change a state
OpSELECTPOINT = 700,
OpSELECTLINE = 701,
OpSELECTCELL = 702,
OpSELECTSUBOBJECT = 703, // for VesselGraphInteractor
// OpSELECTNEWSUBOBJECT = 704, //for VesselGraphInteractor
OpSELECT = 705,
OpDESELECTPOINT = 800,
OpDESELECTLINE = 801,
OpDESELECTCELL = 802,
OpDESELECTSUBOBJECT = 803, // for VesselGraphInteractor
OpDESELECTALL = 804, // for VesselGraphInteractor
OpDESELECT = 805,
OpNAVIGATE = 900,
OpZOOM = 1000,
OpSCALE = 1100,
OpROTATE = 1200,
OpORIENT = 1201,
OpRESTOREPLANEPOSITION = 1202,
OpAPPLYTRANSFORMMATRIX = 1203,
OpSETPOINTTYPE = 1210,
OpMODECHANGE = 1500,
OpSENDCOORDINATES = 1600,
OpPERIPHERYSEARCH = 2000, // used in VesselGraphInteractor
OpROOTSEARCH = 2001, // used in VesselGraphInteractor
OpTHICKSTVESSELSEARCH = 2002, // used in VesselGraphInteractor
OpSHORTESTPATHSEARCH = 2003, // used in VesselGraphInteractor
OpATTRIBUTATION = 2004, // used in VesselGraphInteractor
OpDEFAULT = 2006, // used in VesselGraphInteractor
OpSURFACECHANGED = 3000, // used for changing polydata in surfaces
};
//##Constants for EventMapping...
//##connects the statemachine.xml-File with the implemented conditions.
//##within one statemachine the choice of the actionconstants is freely
//##
//## ActionId
enum EActions
{
AcDONOTHING = 0,
AcINITNEWOBJECT = 5,
AcINITEDITOBJECT = 6,
AcINITEDITGROUP = 7,
AcINITMOVEMENT = 8,
AcINITMOVE = 9,
AcINITFOREGROUND = 45, // used in SeedsInteractor for setting the foreground seeds
AcINITBACKGROUND = 46, // used in SeedsInteractor for setting the background seeds
AcINITNEUTRAL = 47, // used in SeedsInteractor for setting the neutral seeds (rubber)
AcINITUPDATE = 1235, // For shape model deformation
AcADDPOINT = 10,
AcADDPOINTRMB = 6000, // in mitralPointSetInteractor used to set a different type of point
AcADD = 11,
AcADDLINE = 12,
AcADDANDFINISH = 13,
AcADDSELECTEDTOGROUP = 64,
AcCHECKPOINT = 21,
AcCHECKLINE = 22,
AcCHECKCELL = 23,
AcCHECKELEMENT = 30, // check if there is a element close enough (picking)
AcCHECKOBJECT = 31, // check if an object is hit
AcCHECKNMINUS1 = 32, // check if the number of elements is equal to N-1
AcCHECKEQUALS1 = 33, // check if the number of elements in the data is equal to 1
AcCHECKNUMBEROFPOINTS = 330, // check the number of elements in the data
AcCHECKSELECTED = 34, // check if the given element is selected or not
AcCHECKONESELECTED = 340, // check if there is an element that is selected
AcCHECKHOVERING = 341, // check if there is an element that is selected
AcCHECKGREATERZERO = 35, // check if the current number of elements is greater than 0
AcCHECKGREATERTWO = 36, // check if the current number of elements is greater than two
AcCHECKOPERATION = 37, // check if the operation is of one spectial type
AcCHECKONESUBINTERACTOR = 38,
AcCHECKSUBINTERACTORS = 39,
AcFINISHOBJECT = 40,
AcFINISHGROUP = 41,
AcFINISHMOVEMENT = 42,
AcFINISHMOVE = 43,
AcFINISH = 44,
AcSEARCHOBJECT = 50,
AcSEARCHGROUP = 51,
AcSEARCHANOTHEROBJECT = 52, // one object is selected and another object is to be added to selection
AcSELECTPICKEDOBJECT = 60, // select the picked object and deselect others
AcSELECTANOTHEROBJECT = 61,
AcSELECTGROUP = 62,
AcSELECTALL = 63,
AcSELECT = 65,
AcSELECTPOINT = 66,
AcSELECTLINE = 68,
AcSELECTCELL = 67,
AcSELECTSUBOBJECT = 69, // used in VesselGraphInteractor
AcDESELECTOBJECT = 70, // deselect picked from group
AcDESELECTALL = 72,
AcDESELECT = 75,
AcDESELECTPOINT = 76,
AcDESELECTLINE = 78,
AcDESELECTCELL = 77,
AcNEWPOINT = 80,
AcNEWSUBOBJECT = 81,
AcMOVEPOINT = 90,
AcMOVESELECTED = 91,
AcMOVE = 92,
AcMOVEPOINTUP = 93,
AcMOVEPOINTDOWN = 94,
AcREMOVEPOINT = 100,
AcREMOVE = 101,
AcREMOVELINE = 102,
AcREMOVEALL = 103,
AcREMOVESELECTEDSUBOBJECT = 104, // used in VesselGraphInteractor
AcWHEEL = 105,
AcPLUS = 106,
AcMINUS = 107,
AcDELETEPOINT = 120,
AcCLEAR = 130, // clear all elements from a list
AcINSERTPOINT = 110,
AcINSERTLINE = 111,
AC_SET_NEXT_BUTTON_VISIBLE = 5550001,
AC_SET_NEXT_BUTTON_INVISIBLE = 5550002,
AC_SET_PREVIOUS_BUTTON_VISIBLE = 5550003,
AC_SET_PREVIOUS_BUTTON_INVISIBLE = 5550004,
AC_SET_ASSISTAND_WIDGET_STECK = 5550005,
AC_SETMAX_COUNT_REF_POINTS = 5550006,
AC_SET_NEXT_BUTTON_TEXT = 5550007,
AC_CHECK_LANDMARK_COUNT = 5550008,
AC_SET_DONE_FALSE = 5550009,
AC_INIT = 55500010,
AC_SET_APPLICATION_SELECTED_FALSE = 55500011,
AC_SENSOR_ATTACHED = 55500012,
AC_CLOSE_ASSISTENT = 55500013,
AC_START_APPLICATION_TEXT = 55500014,
AC_START_NAVIGATION = 55500015,
AC_START_PATHCOLLECTION = 55500016,
AC_LOAD_LANDMARKS = 55500017,
AC_CALCULATE_LANDMARK_TRANSFORM = 55500018,
AcTERMINATE_INTERACTION = 666,
AcTRANSLATESTART = 1000,
AcTRANSLATE = 1001,
AcSCALESTART = 1002,
AcSCALE = 1003,
AcROTATESTART = 1004,
AcROTATE = 1005,
AcINITAFFINEINTERACTIONS = 1006,
AcFINISHAFFINEINTERACTIONS = 1007,
AcTRANSLATEEND = 1008,
AcSCALEEND = 1009,
AcROTATEEND = 1010,
AcINITZOOM = 1011,
AcZOOM = 1012,
AcSCROLL = 1013,
AcLEVELWINDOW = 1014,
AcSCROLLMOUSEWHEEL = 1015,
AcSETSTARTPOINT = 1050,
AcMODEDESELECT = 1100, // set interactor in not selected mode
AcMODESELECT = 1101, // set interactor in selected mode
AcMODESUBSELECT = 1102, // set interacor in sub selected mode
AcINFORMLISTENERS = 1200,
AcASKINTERACTORS = 1201,
AcCHECKGREATERONE = 1500,
AcCHECKBOUNDINGBOX = 1510,
AcFORCESUBINTERACTORS = 1550,
AcSENDCOORDINATES = 1600,
AcTRANSMITEVENT = 2000, // to transmit an event to a lower Interactor/Statemachine
AcPERIPHERYSEARCH = 3000, // used in VesselGraphInteractor
AcROOTSEARCH = 3001, // used in VesselGraphInteractor
AcTHICKSTVESSELSEARCH = 3002, // used in VesselGraphInteractor
AcSHORTESTPATHSEARCH = 3003, // used in VesselGraphInteractor
AcSINGLE = 3004, // used in VesselGraphInteractor
AcATTRIBUTATION = 3005, // used in VesselGraphInteractor
AcDEFAULT = 3007, // used in VesselGraphInteractor
AcSETVESSELELEMENT = 3008, // used in VesselGraphInteractor
AcCHECKBARRIERSTATUS = 3010, // used in VesselGraphInteractor
AcUPDATEMESH = 1234, // For Shape Model Interaction
AcINCREASE = 49012,
AcDECREASE = 49013,
AcMODIFY = 49014,
AcUNDOUPDATE = 1236, // For restoring a mesh after an update
AcENTEROBJECT = 48000,
AcLEAVEOBJECT = 48001,
AcSWITCHOBJECT = 48002,
AcUPDATELINE = 48003,
AcINITLINE = 48004,
AcTERMINATELINE = 48005,
AcCREATEBOX = 48006,
AcCREATEOBJECTFROMLINE = 48007,
AcCANCEL = 48008,
AcACTIVATETOOL = 48009,
AcROTATEAROUNDPOINT1 = 49002,
AcROTATEAROUNDPOINT2 = 49003,
AcMOVEPOINT1 = 49004,
AcMOVEPOINT2 = 49005,
AcUPDATEPOINT = 49006,
AcUPDATERADIUSMOUSEWHEEL = 49007,
AcDISPLAYOPTIONS = 49009,
AcCYCLE = 49010,
AcACCEPT = 49011,
- AcONSPACENAVIGATORMOUSEINPUT = 4001, // On input of 3D Mouse
- AcONPACENAVIGATORKEYDOWN = 4002, // On input of 3D Mouse
- AcONWIIMOTEINPUT = 4003, // used for wiimote to signal IR input
- AcRESETVIEW = 4004, // used for wiimote to reset view
- AcONWIIMOTEBUTTONRELEASED = 4005, // stops the surface interaction
AcCHECKPOSITION = 5000,
AcINITIALIZECONTOUR = 5001,
AcCALCULATENEWSEGMENTATION_SP = 5002,
AcINTERACTOR = 5003,
AcCALCULATENEWSEGMENTATION_BB = 5004
};
/*
//!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!
//EventMechanism:
//If you change anything from here on, then change in mitkEventMapper.cpp (Array of constants) as well.
//!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!
*/
// Type of an Event;
enum EEventType
{
Type_None = 0, // invalid event
Type_Timer = 1, // timer event
Type_MouseButtonPress = 2, // mouse button pressed
Type_MouseButtonRelease = 3, // mouse button released
Type_MouseButtonDblClick = 4, // mouse button double click
Type_MouseMove = 5, // mouse move
Type_KeyPress = 6, // key pressed
Type_KeyRelease = 7, // key released
Type_FocusIn = 8, // keyboard focus received
Type_FocusOut = 9, // keyboard focus lost
Type_Enter = 10, // mouse enters widget
Type_Leave = 11, // mouse leaves widget
Type_Paint = 12, // paint widget
Type_Move = 13, // move widget
Type_Resize = 14, // resize widget
Type_Create = 15, // after object creation
Type_Destroy = 16, // during object destruction
Type_Show = 17, // widget is shown
Type_Hide = 18, // widget is hidden
Type_Close = 19, // request to close widget
Type_Quit = 20, // request to quit application
Type_Reparent = 21, // widget has been reparented
Type_ShowMinimized = 22, // widget is shown minimized
Type_ShowNormal = 23, // widget is shown normal
Type_WindowActivate = 24, // window was activated
Type_WindowDeactivate = 25, // window was deactivated
Type_ShowToParent = 26, // widget is shown to parent
Type_HideToParent = 27, // widget is hidden to parent
Type_ShowMaximized = 28, // widget is shown maximized
Type_ShowFullScreen = 29, // widget is shown full-screen
Type_Accel = 30, // accelerator event
Type_Wheel = 31, // wheel event
Type_AccelAvailable = 32, // accelerator available event
Type_CaptionChange = 33, // caption changed
Type_IconChange = 34, // icon changed
Type_ParentFontChange = 35, // parent font changed
Type_ApplicationFontChange = 36, // application font changed
Type_ParentPaletteChange = 37, // parent palette changed
Type_ApplicationPaletteChange = 38, // application palette changed
Type_PaletteChange = 39, // widget palette changed
Type_Clipboard = 40, // internal clipboard event
Type_Speech = 42, // reserved for speech input
Type_SockAct = 50, // socket activation
Type_AccelOverride = 51, // accelerator override event
Type_DeferredDelete = 52, // deferred delete event
Type_DragEnter = 60, // drag moves into widget
Type_DragMove = 61, // drag moves in widget
Type_DragLeave = 62, // drag leaves or is cancelled
Type_Drop = 63, // actual drop
Type_DragResponse = 64, // drag accepted/rejected
Type_ChildInserted = 70, // new child widget
Type_ChildRemoved = 71, // deleted child widget
Type_LayoutHint = 72, // child min/max size changed
Type_ShowWindowRequest = 73, // widget's window should be mapped
Type_ActivateControl = 80, // ActiveX activation
Type_DeactivateControl = 81, // ActiveX deactivation
Type_ContextMenu = 82, // context popup menu
Type_IMStart = 83, // input method composition start
Type_IMCompose = 84, // input method composition
Type_IMEnd = 85, // input method composition end
Type_Accessibility = 86, // accessibility information is requested
Type_TabletMove = 87, // Wacom tablet event
Type_LocaleChange = 88, // the system locale changed
Type_LanguageChange = 89, // the application language changed
Type_LayoutDirectionChange = 90, // the layout direction changed
Type_Style = 91, // internal style event
Type_TabletPress = 92, // tablet press
Type_TabletRelease = 93, // tablet release
Type_User = 1000, // first user event id
- Type_SpaceNavigatorInput = 1094, // 3D mouse input occurred
- Type_SpaceNavigatorKeyDown = 1095, // 3D mouse input occurred
- Type_WiiMoteInput = 1096, // WiiMote input occurred
- Type_WiiMoteButton = 1097, // WiiMote button pressed
Type_MaxUser = 65535
};
//##ButtonState
// mouse/keyboard state values
// QT combinations if MOUSEBUTTONRelease: left MouseButton + ControlButton: 0x201
enum EButtonStates
{
BS_NoButton = 0x0000,
BS_LeftButton = 0x0001,
BS_RightButton = 0x0002,
BS_MidButton = 0x0004,
BS_MouseButtonMask = 0x0007,
BS_ShiftButton = 0x0100,
BS_ControlButton = 0x0200,
BS_AltButton = 0x0400,
BS_MetaButton = 0x0800,
BS_KeyButtonMask = 0x0f00,
BS_Keypad = 0x4000
};
//##Key
enum EKeys
{
Key_Escape = 0x1000, // misc keys
Key_Tab = 0x1001,
Key_Backtab = 0x1002,
Key_BackTab = 0x1002, //= Key_Backtab
Key_Backspace = 0x1003,
Key_BackSpace = 0x1003, //= Key_Backspace
Key_Return = 0x1004,
Key_Enter = 0x1005,
Key_Insert = 0x1006,
Key_Delete = 0x1007,
Key_Pause = 0x1008,
Key_Print = 0x1009,
Key_SysReq = 0x100a,
Key_Home = 0x1010, // cursor movement
Key_End = 0x1011,
Key_Left = 0x1012,
Key_Up = 0x1013,
Key_Right = 0x1014,
Key_Down = 0x1015,
Key_Prior = 0x1016,
Key_PageUp = 0x1016, //=Key_Prior
Key_Next = 0x1017,
Key_PageDown = 0x1017, //=Key_Next
Key_Shift = 0x1020, // modifiers
Key_Control = 0x1021,
Key_Meta = 0x1022,
Key_Alt = 0x1023,
Key_CapsLock = 0x1024,
Key_NumLock = 0x1025,
Key_ScrollLock = 0x1026,
Key_F1 = 0x1030, // function keys
Key_F2 = 0x1031,
Key_F3 = 0x1032,
Key_F4 = 0x1033,
Key_F5 = 0x1034,
Key_F6 = 0x1035,
Key_F7 = 0x1036,
Key_F8 = 0x1037,
Key_F9 = 0x1038,
Key_F10 = 0x1039,
Key_F11 = 0x103a,
Key_F12 = 0x103b,
Key_F13 = 0x103c,
Key_F14 = 0x103d,
Key_F15 = 0x103e,
Key_F16 = 0x103f,
Key_F17 = 0x1040,
Key_F18 = 0x1041,
Key_F19 = 0x1042,
Key_F20 = 0x1043,
Key_F21 = 0x1044,
Key_F22 = 0x1045,
Key_F23 = 0x1046,
Key_F24 = 0x1047,
Key_F25 = 0x1048, // F25 .. F35 only on X11
Key_F26 = 0x1049,
Key_F27 = 0x104a,
Key_F28 = 0x104b,
Key_F29 = 0x104c,
Key_F30 = 0x104d,
Key_F31 = 0x104e,
Key_F32 = 0x104f,
Key_F33 = 0x1050,
Key_F34 = 0x1051,
Key_F35 = 0x1052,
Key_Super_L = 0x1053, // extra keys
Key_Super_R = 0x1054,
Key_Menu = 0x1055,
Key_Hyper_L = 0x1056,
Key_Hyper_R = 0x1057,
Key_Help = 0x1058,
// International input method support (X keycode - = 0xEE00)
// Only interesting if you are writing your own input method
Key_Muhenkan = 0x1122, // Cancel Conversion
Key_Henkan = 0x1123, // Start/Stop Conversion
Key_Hiragana_Katakana = 0x1127, // Hiragana/Katakana toggle
Key_Zenkaku_Hankaku = 0x112A, // Zenkaku/Hankaku toggle
Key_Space = 0x20, // 7 bit printable ASCII
Key_Any = 0x20, //= Key_Space
Key_Exclam = 0x21,
Key_QuoteDbl = 0x22,
Key_NumberSign = 0x23,
Key_Dollar = 0x24,
Key_Percent = 0x25,
Key_Ampersand = 0x26,
Key_Apostrophe = 0x27,
Key_ParenLeft = 0x28,
Key_ParenRight = 0x29,
Key_Asterisk = 0x2a,
Key_Plus = 0x2b,
Key_Comma = 0x2c,
Key_Minus = 0x2d,
Key_Period = 0x2e,
Key_Slash = 0x2f,
Key_0 = 0x30,
Key_1 = 0x31,
Key_2 = 0x32,
Key_3 = 0x33,
Key_4 = 0x34,
Key_5 = 0x35,
Key_6 = 0x36,
Key_7 = 0x37,
Key_8 = 0x38,
Key_9 = 0x39,
Key_Colon = 0x3a,
Key_Semicolon = 0x3b,
Key_Less = 0x3c,
Key_Equal = 0x3d,
Key_Greater = 0x3e,
Key_Question = 0x3f,
Key_At = 0x40,
Key_A = 0x41,
Key_B = 0x42,
Key_C = 0x43,
Key_D = 0x44,
Key_E = 0x45,
Key_F = 0x46,
Key_G = 0x47,
Key_H = 0x48,
Key_I = 0x49,
Key_J = 0x4a,
Key_K = 0x4b,
Key_L = 0x4c,
Key_M = 0x4d,
Key_N = 0x4e,
Key_O = 0x4f,
Key_P = 0x50,
Key_Q = 0x51,
Key_R = 0x52,
Key_S = 0x53,
Key_T = 0x54,
Key_U = 0x55,
Key_V = 0x56,
Key_W = 0x57,
Key_X = 0x58,
Key_Y = 0x59,
Key_Z = 0x5a,
Key_BracketLeft = 0x5b,
Key_Backslash = 0x5c,
Key_BracketRight = 0x5d,
Key_AsciiCircum = 0x5e,
Key_Underscore = 0x5f,
Key_QuoteLeft = 0x60,
Key_BraceLeft = 0x7b,
Key_Bar = 0x7c,
Key_BraceRight = 0x7d,
Key_AsciiTilde = 0x7e,
Key_nobreakspace = 0x0a0,
Key_exclamdown = 0x0a1,
Key_cent = 0x0a2,
Key_sterling = 0x0a3,
Key_currency = 0x0a4,
Key_yen = 0x0a5,
Key_brokenbar = 0x0a6,
Key_section = 0x0a7,
Key_diaeresis = 0x0a8,
Key_copyright = 0x0a9,
Key_ordfeminine = 0x0aa,
Key_guillemotleft = 0x0ab, // left angle quotation mark
Key_notsign = 0x0ac,
Key_hyphen = 0x0ad,
Key_registered = 0x0ae,
Key_macron = 0x0af,
Key_degree = 0x0b0,
Key_plusminus = 0x0b1,
Key_twosuperior = 0x0b2,
Key_threesuperior = 0x0b3,
Key_acute = 0x0b4,
Key_mu = 0x0b5,
Key_paragraph = 0x0b6,
Key_periodcentered = 0x0b7,
Key_cedilla = 0x0b8,
Key_onesuperior = 0x0b9,
Key_masculine = 0x0ba,
Key_guillemotright = 0x0bb, // right angle quotation mark
Key_onequarter = 0x0bc,
Key_onehalf = 0x0bd,
Key_threequarters = 0x0be,
Key_questiondown = 0x0bf,
Key_Agrave = 0x0c0,
Key_Aacute = 0x0c1,
Key_Acircumflex = 0x0c2,
Key_Atilde = 0x0c3,
Key_Adiaeresis = 0x0c4,
Key_Aring = 0x0c5,
Key_AE = 0x0c6,
Key_Ccedilla = 0x0c7,
Key_Egrave = 0x0c8,
Key_Eacute = 0x0c9,
Key_Ecircumflex = 0x0ca,
Key_Ediaeresis = 0x0cb,
Key_Igrave = 0x0cc,
Key_Iacute = 0x0cd,
Key_Icircumflex = 0x0ce,
Key_Idiaeresis = 0x0cf,
Key_ETH = 0x0d0,
Key_Ntilde = 0x0d1,
Key_Ograve = 0x0d2,
Key_Oacute = 0x0d3,
Key_Ocircumflex = 0x0d4,
Key_Otilde = 0x0d5,
Key_Odiaeresis = 0x0d6,
Key_multiply = 0x0d7,
Key_Ooblique = 0x0d8,
Key_Ugrave = 0x0d9,
Key_Uacute = 0x0da,
Key_Ucircumflex = 0x0db,
Key_Udiaeresis = 0x0dc,
Key_Yacute = 0x0dd,
Key_THORN = 0x0de,
Key_ssharp = 0x0df,
Key_agrave = 0x0e0,
Key_aacute = 0x0e1,
Key_acircumflex = 0x0e2,
Key_atilde = 0x0e3,
Key_adiaeresis = 0x0e4,
Key_aring = 0x0e5,
Key_ae = 0x0e6,
Key_ccedilla = 0x0e7,
Key_egrave = 0x0e8,
Key_eacute = 0x0e9,
Key_ecircumflex = 0x0ea,
Key_ediaeresis = 0x0eb,
Key_igrave = 0x0ec,
Key_iacute = 0x0ed,
Key_icircumflex = 0x0ee,
Key_idiaeresis = 0x0ef,
Key_eth = 0x0f0,
Key_ntilde = 0x0f1,
Key_ograve = 0x0f2,
Key_oacute = 0x0f3,
Key_ocircumflex = 0x0f4,
Key_otilde = 0x0f5,
Key_odiaeresis = 0x0f6,
Key_division = 0x0f7,
Key_oslash = 0x0f8,
Key_ugrave = 0x0f9,
Key_uacute = 0x0fa,
Key_ucircumflex = 0x0fb,
Key_udiaeresis = 0x0fc,
Key_yacute = 0x0fd,
Key_thorn = 0x0fe,
Key_ydiaeresis = 0x0ff,
Key_unknown = 0xffff,
Key_none = 0xffff //= Key_unknown
};
} // namespace mitk
#endif
diff --git a/Modules/Core/include/mitkLog.h b/Modules/Core/include/mitkLog.h
deleted file mode 100644
index 7e1aacaedb..0000000000
--- a/Modules/Core/include/mitkLog.h
+++ /dev/null
@@ -1,104 +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.
-
-============================================================================*/
-
-#ifndef mitkLog_h
-#define mitkLog_h
-
-#include <MitkCoreExports.h>
-#include <mbilog.h>
-
-namespace mitk
-{
- /*!
- \brief mbilog backend implementation for mitk
- */
- class MITKCORE_EXPORT LoggingBackend : public mbilog::TextBackendBase
- {
- public:
- /** \brief overloaded method for receiving log message from mbilog
- */
- void ProcessMessage(const mbilog::LogMessage &) override;
-
- /** \brief registers MITK logging backend at mbilog
- */
- static void Register();
-
- /** \brief Unregisters MITK logging backend at mbilog
- */
- static void Unregister();
-
- /** \brief Sets extra log file path (additionally to the console log)
- */
- static void SetLogFile(const char *file);
-
- /** @brief Activates and handles a rolling log file with the given prefix and path.
- * This method handles 10 log files with a given prefix, e.g. "myLogFile".
- * The 10 log files will then look like this:
- * myLogFile-0.log (current file)
- * myLogFile-1.log (last file)
- * myLogFile-2.log
- * [...]
- * myLogFile-9.log
- *
- * Everytime this method this called, normally when MITK is started, then
- * all log files are copied one file below (0 to 1, 1 to 2, and so on).
- * The oldest logfile (number 9) is always deleted. So users have access to
- * the log files of the last 10 runs.
- * @throws mitk::Exception Throws an exception if there is a problem with renaming the logfiles, e.g., because of
- * file access problems.
- * @param prefixPath Should hold the prefix of the logfile together with its path. E.g.,
- * "C:/programs/mitk/myLogFile".
- */
- static void RotateLogFiles(const std::string &prefixPath);
-
- /** @brief Increments the names of logfiles with the given prefixPath.
- * This means, if the prefixPath is "myLogFile" myLogFile-0.log
- * is renamed to myLogFile-1.log, myLogFile-1.log to myLogFile-2.log,
- * and so on. The oldest logfile is deleted. The number of log files is
- * defined by the parameter "numLogFiles". The first logfile name is
- * "free" (e.g., [prefix]-0.log) again. This name is returned.
- * @param prefixPath Should hold the prefix of the logfile together with its path. E.g.,
- * "C:/programs/mitk/myLogFile".
- * @param numLogFiles Sets the number of logfiles. Default value is 10. This means logfiles from [prefix]-0.log
- * to [prefix]-1.log are stored.
- * @return Returns a new logfile name which is free again because the old first log file was renamed.
- * @throws mitk::Exception Throws an exception if there is a problem with renaming the logfiles, e.g., because of
- * file access problems.
- */
- static std::string IncrementLogFileNames(const std::string &prefixPath, int numLogFiles = 10);
-
- /** @return Returns the log file if there is one. Returns an empty string
- * if no log file is active.
- */
- static std::string GetLogFile();
-
- /** \brief Enables an additional logging output window by means of itk::outputwindow
- * This might be relevant for showing log output in applications with no default output console
- */
- static void EnableAdditionalConsoleWindow(bool enable);
-
- /** \brief Automatically extracts and removes the "--logfile <file>" parameters from the standard C main(argc,argv)
- * parameter list and calls SetLogFile if needed
- */
- static void CatchLogFileCommandLineParameter(int &argc, char **argv);
-
- mbilog::OutputType GetOutputType() const override;
-
- protected:
- /** Checks if a file exists.
- * @return Returns true if the file exists, false if not.
- */
- static bool CheckIfFileExists(const std::string &filename);
- };
-}
-
-#endif
diff --git a/Modules/Core/include/mitkLogBackend.h b/Modules/Core/include/mitkLogBackend.h
new file mode 100644
index 0000000000..3fe8e06fbe
--- /dev/null
+++ b/Modules/Core/include/mitkLogBackend.h
@@ -0,0 +1,111 @@
+/*============================================================================
+
+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 mitkLogBackend_h
+#define mitkLogBackend_h
+
+#include <mitkLogBackendText.h>
+#include <MitkCoreExports.h>
+
+namespace mitk
+{
+ /** \brief Log backend implementation for MITK.
+ */
+ class MITKCORE_EXPORT LogBackend : public LogBackendText
+ {
+ public:
+ void ProcessMessage(const LogMessage&) override;
+
+ /** \brief Registers MITK log backend.
+ */
+ static void Register();
+
+ /** \brief Unregister MITK log backend.
+ */
+ static void Unregister();
+
+ /** \brief Set extra log file path in addition to the console log.
+ */
+ static void SetLogFile(const std::string& file);
+
+ /** \brief Activates and handles a rolling log file with the given prefix and path.
+ *
+ * This method handles 10 log files with a given prefix, e.g. "myLogFile".
+ * The 10 log files will then look like this:
+ * <ul>
+ * <li>myLogFile-0.log (current file)</li>
+ * <li>myLogFile-1.log (last file)</li>
+ * <li>myLogFile-2.log</li>
+ * <li><em>[...]</em></li>
+ * <li>myLogFile-9.log</li>
+ * </ul>
+ *
+ * Everytime this method this called, normally when MITK is started, then
+ * all log files are copied one file below (0 to 1, 1 to 2, and so on).
+ * The oldest logfile (number 9) is always deleted. So users have access to
+ * the log files of the last 10 runs.
+ *
+ * \throws mitk::Exception Throws an exception if there is a problem with renaming the logfiles, e.g., because of
+ * file access problems.
+ *
+ * \param prefixPath Should hold the prefix of the logfile together with its path. E.g.,
+ * "C:/programs/mitk/myLogFile".
+ */
+ static void RotateLogFiles(const std::string& prefixPath);
+
+ /** \brief Increment the names of logfiles with the given prefixPath.
+ *
+ * This means, if the prefixPath is "myLogFile" myLogFile-0.log
+ * is renamed to myLogFile-1.log, myLogFile-1.log to myLogFile-2.log,
+ * and so on. The oldest logfile is deleted. The number of log files is
+ * defined by the parameter "numLogFiles". The first logfile name is
+ * "free" (e.g., [prefix]-0.log) again. This name is returned.
+ *
+ * \param prefixPath Should hold the prefix of the logfile together with its path. E.g.,
+ * "C:/programs/mitk/myLogFile".
+ * \param numLogFiles Sets the number of logfiles. Default value is 10. This means logfiles from [prefix]-0.log
+ * to [prefix]-1.log are stored.
+ *
+ * \return Returns a new logfile name which is free again because the old first log file was renamed.
+ *
+ * \throws mitk::Exception Throws an exception if there is a problem with renaming the logfiles, e.g., because of
+ * file access problems.
+ */
+ static std::string IncrementLogFileNames(const std::string& prefixPath, int numLogFiles = 10);
+
+ /** \return Return the log file if there is one. Returns an empty string if no log file is active.
+ */
+ static std::string GetLogFile();
+
+ /** \brief Enable an additional logging output window by means of itk::OutputWindow.
+ *
+ * This might be relevant for showing log output in applications with no default output console.
+ */
+ static void EnableAdditionalConsoleWindow(bool enable);
+
+ /** \brief Automatically extract and remove the "--logfile <file>" parameters from the standard C main parameter
+ * list and calls SetLogFile if needed.
+ */
+ static void CatchLogFileCommandLineParameter(int& argc, char** argv);
+
+ LogBackendBase::OutputType GetOutputType() const override;
+
+ protected:
+ /** \brief Check if a file exists.
+ *
+ * \return Returns true if the file exists, false if not.
+ */
+ static bool CheckIfFileExists(const std::string &filename);
+ };
+}
+
+#endif
diff --git a/Modules/Core/include/mitkLogMacros.h b/Modules/Core/include/mitkLogMacros.h
index 8ed99172df..2025e210b6 100644
--- a/Modules/Core/include/mitkLogMacros.h
+++ b/Modules/Core/include/mitkLogMacros.h
@@ -1,24 +1,18 @@
/*============================================================================
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 mitkLogMacros_h
#define mitkLogMacros_h
-#include <mbilog.h>
-
-#define MITK_INFO MBI_INFO
-#define MITK_WARN MBI_WARN
-#define MITK_ERROR MBI_ERROR
-#define MITK_FATAL MBI_FATAL
-#define MITK_DEBUG MBI_DEBUG
+#include <mitkLog.h>
#endif
diff --git a/Modules/Core/include/mitkMessage.h b/Modules/Core/include/mitkMessage.h
index 97f4fb693a..e8242c00eb 100644
--- a/Modules/Core/include/mitkMessage.h
+++ b/Modules/Core/include/mitkMessage.h
@@ -1,697 +1,697 @@
/*============================================================================
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 mitkMessage_h
#define mitkMessage_h
#include <functional>
#include <mutex>
#include <vector>
/**
* Adds a Message<> variable and methods to add/remove message delegates to/from
* this variable.
*/
#define mitkNewMessageMacro(msgHandleObject) \
private: \
::mitk::Message<> m_##msgHandleObject##Message; \
\
public: \
inline void Add##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate<> &delegate) \
{ \
m_##msgHandleObject##Message += delegate; \
} \
inline void Remove##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate<> &delegate) \
{ \
m_##msgHandleObject##Message -= delegate; \
}
#define mitkNewMessageWithReturnMacro(msgHandleObject, returnType) \
private: \
::mitk::Message<returnType> m_##msgHandleObject##Message; \
\
public: \
inline void Add##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate<returnType> &delegate) \
{ \
m_##msgHandleObject##Message += delegate; \
} \
inline void Remove##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate<returnType> &delegate) \
{ \
m_##msgHandleObject##Message -= delegate; \
}
#define mitkNewMessage1Macro(msgHandleObject, type1) \
private: \
::mitk::Message1<type1> m_##msgHandleObject##Message; \
\
public: \
void Add##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate1<type1> &delegate) \
{ \
m_##msgHandleObject##Message += delegate; \
} \
void Remove##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate1<type1> &delegate) \
{ \
m_##msgHandleObject##Message -= delegate; \
}
#define mitkNewMessage2Macro(msgHandleObject, type1, type2) \
private: \
::mitk::Message2<type1, type2> m_##msgHandleObject##Message; \
\
public: \
void Add##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate2<type1, type2> &delegate) \
{ \
m_##msgHandleObject##Message += delegate; \
} \
void Remove##msgHandleObject##Listener(const ::mitk::MessageAbstractDelegate2<type1, type2> &delegate) \
{ \
m_##msgHandleObject##Message -= delegate; \
}
namespace mitk
{
template <typename A = void>
class MessageAbstractDelegate
{
public:
virtual ~MessageAbstractDelegate() {}
virtual A Execute() const = 0;
virtual bool operator==(const MessageAbstractDelegate *cmd) const = 0;
virtual MessageAbstractDelegate *Clone() const = 0;
};
template <typename T, typename A = void>
class MessageAbstractDelegate1
{
public:
virtual ~MessageAbstractDelegate1() {}
virtual A Execute(T t) const = 0;
virtual bool operator==(const MessageAbstractDelegate1 *cmd) const = 0;
virtual MessageAbstractDelegate1 *Clone() const = 0;
};
template <typename T, typename U, typename A = void>
class MessageAbstractDelegate2
{
public:
virtual ~MessageAbstractDelegate2() {}
virtual A Execute(T t, U u) const = 0;
virtual bool operator==(const MessageAbstractDelegate2 *cmd) const = 0;
virtual MessageAbstractDelegate2 *Clone() const = 0;
};
template <typename T, typename U, typename V, typename A = void>
class MessageAbstractDelegate3
{
public:
virtual ~MessageAbstractDelegate3() {}
virtual A Execute(T t, U u, V v) const = 0;
virtual bool operator==(const MessageAbstractDelegate3 *cmd) const = 0;
virtual MessageAbstractDelegate3 *Clone() const = 0;
};
template <typename T, typename U, typename V, typename W, typename A = void>
class MessageAbstractDelegate4
{
public:
virtual ~MessageAbstractDelegate4() {}
virtual A Execute(T t, U u, V v, W w) const = 0;
virtual bool operator==(const MessageAbstractDelegate4 *cmd) const = 0;
virtual MessageAbstractDelegate4 *Clone() const = 0;
};
/**
* This class essentially wraps a function pointer with signature
* A(R::*function)(). A is the return type of your callback function
* and R the type of the class implementing the function.
*
* Use this class to add a callback function to
* messages without parameters.
*/
template <class R, typename A = void>
class MessageDelegate : public MessageAbstractDelegate<A>
{
public:
// constructor - takes pointer to an object and pointer to a member and stores
// them in two private variables
MessageDelegate(R *object, A (R::*memberFunctionPointer)())
: m_Object(object), m_MemberFunctionPointer(memberFunctionPointer)
{
}
~MessageDelegate() override {}
// override function "Call"
A Execute() const override
{
return (m_Object->*m_MemberFunctionPointer)(); // execute member function
}
bool operator==(const MessageAbstractDelegate<A> *c) const override
{
const MessageDelegate<R, A> *cmd = dynamic_cast<const MessageDelegate<R, A> *>(c);
if (!cmd)
return false;
if ((void *)this->m_Object != (void *)cmd->m_Object)
return false;
if (this->m_MemberFunctionPointer != cmd->m_MemberFunctionPointer)
return false;
return true;
}
MessageAbstractDelegate<A> *Clone() const override { return new MessageDelegate(m_Object, m_MemberFunctionPointer); }
private:
R *m_Object; // pointer to object
A (R::*m_MemberFunctionPointer)(); // pointer to member function
};
/**
* This class essentially wraps a function pointer with signature
* A(R::*function)(T). A is the return type of your callback function,
* R the type of the class implementing the function and T the type
* of the argument.
*
* Use this class to add a callback function to
* messages with one parameter.
*
* If you need more parameters, use MessageDelegate2 etc.
*/
template <class R, typename T, typename A = void>
class MessageDelegate1 : public MessageAbstractDelegate1<T, A>
{
public:
// constructor - takes pointer to an object and pointer to a member and stores
// them in two private variables
MessageDelegate1(R *object, A (R::*memberFunctionPointer)(T))
: m_Object(object), m_MemberFunctionPointer(memberFunctionPointer)
{
}
~MessageDelegate1() override {}
// override function "Call"
A Execute(T t) const override
{
return (m_Object->*m_MemberFunctionPointer)(t); // execute member function
}
bool operator==(const MessageAbstractDelegate1<T, A> *c) const override
{
const MessageDelegate1<R, T, A> *cmd = dynamic_cast<const MessageDelegate1<R, T, A> *>(c);
if (!cmd)
return false;
if ((void *)this->m_Object != (void *)cmd->m_Object)
return false;
if (this->m_MemberFunctionPointer != cmd->m_MemberFunctionPointer)
return false;
return true;
}
MessageAbstractDelegate1<T, A> *Clone() const override { return new MessageDelegate1(m_Object, m_MemberFunctionPointer); }
private:
R *m_Object; // pointer to object
A (R::*m_MemberFunctionPointer)(T); // pointer to member function
};
template <class R, typename T, typename U, typename A = void>
class MessageDelegate2 : public MessageAbstractDelegate2<T, U, A>
{
public:
// constructor - takes pointer to an object and pointer to a member and stores
// them in two private variables
MessageDelegate2(R *object, A (R::*memberFunctionPointer)(T, U))
: m_Object(object), m_MemberFunctionPointer(memberFunctionPointer)
{
}
~MessageDelegate2() override {}
// override function "Call"
A Execute(T t, U u) const override
{
return (m_Object->*m_MemberFunctionPointer)(t, u); // execute member function
}
bool operator==(const MessageAbstractDelegate2<T, U, A> *c) const override
{
const MessageDelegate2<R, T, U, A> *cmd = dynamic_cast<const MessageDelegate2<R, T, U, A> *>(c);
if (!cmd)
return false;
if ((void *)this->m_Object != (void *)cmd->m_Object)
return false;
if (this->m_MemberFunctionPointer != cmd->m_MemberFunctionPointer)
return false;
return true;
}
MessageAbstractDelegate2<T, U, A> *Clone() const override { return new MessageDelegate2(m_Object, m_MemberFunctionPointer); }
private:
R *m_Object; // pointer to object
A (R::*m_MemberFunctionPointer)(T, U); // pointer to member function
};
template <class R, typename T, typename U, typename V, typename A = void>
class MessageDelegate3 : public MessageAbstractDelegate3<T, U, V, A>
{
public:
// constructor - takes pointer to an object and pointer to a member and stores
// them in two private variables
MessageDelegate3(R *object, A (R::*memberFunctionPointer)(T, U, V))
: m_Object(object), m_MemberFunctionPointer(memberFunctionPointer)
{
}
~MessageDelegate3() override {}
// override function "Call"
A Execute(T t, U u, V v) const override
{
return (m_Object->*m_MemberFunctionPointer)(t, u, v); // execute member function
}
bool operator==(const MessageAbstractDelegate3<T, U, V, A> *c) const override
{
const MessageDelegate3<R, T, U, V, A> *cmd = dynamic_cast<const MessageDelegate3<R, T, U, V, A> *>(c);
if (!cmd)
return false;
if ((void *)this->m_Object != (void *)cmd->m_Object)
return false;
if (this->m_MemberFunctionPointer != cmd->m_MemberFunctionPointer)
return false;
return true;
}
MessageAbstractDelegate3<T, U, V, A> *Clone() const override
{
return new MessageDelegate3(m_Object, m_MemberFunctionPointer);
}
private:
R *m_Object; // pointer to object
A (R::*m_MemberFunctionPointer)(T, U, V); // pointer to member function
};
template <class R, typename T, typename U, typename V, typename W, typename A = void>
class MessageDelegate4 : public MessageAbstractDelegate4<T, U, V, W, A>
{
public:
// constructor - takes pointer to an object and pointer to a member and stores
// them in two private variables
MessageDelegate4(R *object, A (R::*memberFunctionPointer)(T, U, V, W))
: m_Object(object), m_MemberFunctionPointer(memberFunctionPointer)
{
}
virtual ~MessageDelegate4() {}
// override function "Call"
virtual A Execute(T t, U u, V v, W w) const
{
return (m_Object->*m_MemberFunctionPointer)(t, u, v, w); // execute member function
}
bool operator==(const MessageAbstractDelegate4<T, U, V, W, A> *c) const
{
const MessageDelegate4<R, T, U, V, W, A> *cmd = dynamic_cast<const MessageDelegate4<R, T, U, V, W, A> *>(c);
if (!cmd)
return false;
if ((void *)this->m_Object != (void *)cmd->m_Object)
return false;
if (this->m_MemberFunctionPointer != cmd->m_MemberFunctionPointer)
return false;
return true;
}
MessageAbstractDelegate4<T, U, V, W, A> *Clone() const
{
return new MessageDelegate4(m_Object, m_MemberFunctionPointer);
}
private:
R *m_Object; // pointer to object
A (R::*m_MemberFunctionPointer)(T, U, V, W); // pointer to member function
};
template <typename AbstractDelegate>
class MessageBase
{
public:
typedef std::vector<AbstractDelegate *> ListenerList;
virtual ~MessageBase()
{
for (auto iter = m_Listeners.begin(); iter != m_Listeners.end(); ++iter)
{
delete *iter;
}
}
MessageBase() {}
MessageBase(const MessageBase &o)
{
for (typename ListenerList::iterator iter = o.m_Listeners.begin(); iter != o.m_Listeners.end(); ++iter)
{
m_Listeners.push_back((*iter)->Clone());
}
}
MessageBase &operator=(const MessageBase &o)
{
MessageBase tmp(o);
std::swap(tmp.m_Listeners, this->m_Listeners);
return *this;
}
void AddListener(const AbstractDelegate &delegate) const
{
AbstractDelegate *msgCmd = delegate.Clone();
m_Mutex.lock();
for (auto iter = m_Listeners.begin(); iter != m_Listeners.end(); ++iter)
{
if ((*iter)->operator==(msgCmd))
{
delete msgCmd;
m_Mutex.unlock();
return;
}
}
m_Listeners.push_back(msgCmd);
m_Mutex.unlock();
}
void operator+=(const AbstractDelegate &delegate) const { this->AddListener(delegate); }
void RemoveListener(const AbstractDelegate &delegate) const
{
m_Mutex.lock();
for (auto iter = m_Listeners.begin(); iter != m_Listeners.end(); ++iter)
{
if ((*iter)->operator==(&delegate))
{
delete *iter;
m_Listeners.erase(iter);
m_Mutex.unlock();
return;
}
}
m_Mutex.unlock();
}
void operator-=(const AbstractDelegate &delegate) const { this->RemoveListener(delegate); }
const ListenerList &GetListeners() const { return m_Listeners; }
bool HasListeners() const { return !m_Listeners.empty(); }
bool IsEmpty() const { return m_Listeners.empty(); }
protected:
/**
* \brief List of listeners.
*
* This is declared mutable for a reason: Imagine an object that sends out notifications and
* someone gets a <tt>const Database</tt> object, because he/she should not write to the
* database. He/she should anyway be able to register for notifications about changes in the database
* -- this is why AddListener and RemoveListener are declared <tt>const</tt>. m_Listeners must be
* mutable so that AddListener and RemoveListener can modify it regardless of the object's constness.
*/
mutable ListenerList m_Listeners;
mutable std::mutex m_Mutex;
};
/**
* \brief Event/message/notification class.
*
* \sa mitk::BinaryThresholdTool
* \sa QmitkBinaryThresholdToolGUI
*
* This totally ITK, Qt, VTK, whatever toolkit independent class
* allows one class to send out messages and another class to
* receive these message. This class is templated over the
* return type (A) of the callback functions.
* There are variations of this class
* (Message1, Message2, etc.) for sending
* one, two or more parameters along with the messages.
*
* This is an implementation of the Observer pattern.
*
* \li There is no guarantee about the order of which observer is notified first. At the moment the observers which
* register first will be notified first.
* \li Notifications are <b>synchronous</b>, by direct method calls. There is no support for asynchronous messages.
*
* To conveniently add methods for registering/unregistering observers
* to Message variables of your class, you can use the mitkNewMessageMacro
* macros.
*/
template <typename A = void>
class Message : public MessageBase<MessageAbstractDelegate<A>>
{
public:
typedef MessageBase<MessageAbstractDelegate<A>> Super;
typedef typename Super::ListenerList ListenerList;
void Send() const
{
ListenerList listeners;
{
this->m_Mutex.lock();
listeners.assign(this->m_Listeners.begin(), this->m_Listeners.end());
this->m_Mutex.unlock();
}
for (auto iter = listeners.begin(); iter != listeners.end(); ++iter)
{
// notify each listener
(*iter)->Execute();
}
}
void operator()() const { this->Send(); }
};
// message with 1 parameter and return type
template <typename T, typename A = void>
class Message1 : public MessageBase<MessageAbstractDelegate1<T, A>>
{
public:
typedef MessageBase<MessageAbstractDelegate1<T, A>> Super;
typedef typename Super::ListenerList ListenerList;
void Send(T t) const
{
ListenerList listeners;
{
this->m_Mutex.lock();
listeners.assign(this->m_Listeners.begin(), this->m_Listeners.end());
this->m_Mutex.unlock();
}
for (auto iter = listeners.begin(); iter != listeners.end(); ++iter)
{
// notify each listener
(*iter)->Execute(t);
}
}
void operator() (T t) const { this->Send(t); }
};
// message with 2 parameters and return type
template <typename T, typename U, typename A = void>
class Message2 : public MessageBase<MessageAbstractDelegate2<T, U, A>>
{
public:
typedef MessageBase<MessageAbstractDelegate2<T, U, A>> Super;
typedef typename Super::ListenerList ListenerList;
void Send(T t, U u) const
{
ListenerList listeners;
{
this->m_Mutex.lock();
listeners.assign(this->m_Listeners.begin(), this->m_Listeners.end());
this->m_Mutex.unlock();
}
for (auto iter = listeners.begin(); iter != listeners.end(); ++iter)
{
// notify each listener
(*iter)->Execute(t, u);
}
}
void operator()(T t, U u) const { this->Send(t, u); }
};
// message with 3 parameters and return type
template <typename T, typename U, typename V, typename A = void>
class Message3 : public MessageBase<MessageAbstractDelegate3<T, U, V, A>>
{
public:
typedef MessageBase<MessageAbstractDelegate3<T, U, V, A>> Super;
typedef typename Super::ListenerList ListenerList;
void Send(T t, U u, V v) const
{
ListenerList listeners;
{
this->m_Mutex.lock();
listeners.assign(this->m_Listeners.begin(), this->m_Listeners.end());
this->m_Mutex.unlock();
}
for (typename ListenerList::iterator iter = listeners.begin(); iter != listeners.end(); ++iter)
{
// notify each listener
(*iter)->Execute(t, u, v);
}
}
void operator()(T t, U u, V v) const { this->Send(t, u, v); }
};
// message with 4 parameters and return type
template <typename T, typename U, typename V, typename W, typename A = void>
class Message4 : public MessageBase<MessageAbstractDelegate4<T, U, V, W>>
{
public:
typedef MessageBase<MessageAbstractDelegate4<T, U, V, W, A>> Super;
typedef typename Super::ListenerList ListenerList;
void Send(T t, U u, V v, W w) const
{
ListenerList listeners;
{
this->m_Mutex.lock();
listeners.assign(this->m_Listeners.begin(), this->m_Listeners.end());
this->m_Mutex.unlock();
}
for (typename ListenerList::iterator iter = listeners.begin(); iter != listeners.end(); ++iter)
{
// notify each listener
(*iter)->Execute(t, u, v, w);
}
}
void operator()(T t, U u, V v, W w) const { this->Send(t, u, v, w); }
};
/* Here is an example how to use the macros and templates:
*
-* // An object to be send around
+* // An object to be sent around
* class Law
* {
* private:
* std::string m_Description;
*
* public:
*
* Law(const std::string law) : m_Description(law)
* { }
*
* std::string GetDescription() const
* {
* return m_Description;
* }
* };
*
* // The NewtonMachine will issue specific events
* class NewtonMachine
* {
* mitkNewMessageMacro(AnalysisStarted);
* mitkNewMessage1Macro(AnalysisStopped, bool);
* mitkNewMessage1Macro(LawDiscovered, const Law&);
*
* public:
*
* void StartAnalysis()
* {
* // send the "started" signal
* m_AnalysisStartedMessage();
*
* // we found a new law of nature by creating one :-)
* Law massLaw("F=ma");
* m_LawDiscoveredMessage(massLaw);
* }
*
* void StopAnalysis()
* {
* // send the "stop" message with false, indicating
* // that no error occurred
* m_AnalysisStoppedMessage(false);
* }
* };
*
* class Observer
* {
* private:
*
* NewtonMachine* m_Machine;
*
* public:
*
* Observer(NewtonMachine* machine) : m_Machine(machine)
* {
* // Add "observers", i.e. function pointers to the machine
* m_Machine->AddAnalysisStartedListener(
* ::mitk::MessageDelegate<Observer>(this, &Observer::MachineStarted));
* m_Machine->AddAnalysisStoppedListener(
* ::mitk::MessageDelegate1<Observer, bool>(this, &Observer::MachineStopped));
* m_Machine->AddLawDiscoveredListener(
* ::mitk::MessageDelegate1<Observer, const Law&>(this, &Observer::LawDiscovered));
* }
*
* ~Observer()
* {
* // Always remove your observers when finished
* m_Machine->RemoveAnalysisStartedListener(
* ::mitk::MessagDelegate<Observer>(this, &Observer::MachineStarted));
* m_Machine->RemoveAnalysisStoppedListener(
* ::mitk::MessageDelegate1<Observer, bool>(this, &Observer::MachineStopped));
* m_Machine->RemoveLawDiscoveredListener(
* ::mitk::MessageDelegate1<Observer, const Law&>(this, &Observer::LawDiscovered));
* }
*
* void MachineStarted()
* {
* std::cout << "Observed machine has started" << std::endl;
* }
*
* void MachineStopped(bool error)
* {
* std::cout << "Observed machine stopped " << (error ? "with an error" : "") << std::endl;
* }
*
* void LawDiscovered(const Law& law)
* {
* std::cout << "New law of nature discovered: " << law.GetDescription() << std::endl;
* }
* };
*
* NewtonMachine newtonMachine;
* Observer observer(&newtonMachine);
*
* // This will send two events to registered observers
* newtonMachine.StartAnalysis();
* // This will send one event to registered observers
* newtonMachine.StopAnalysis();
*
* Another example of how to use these message classes can be
* found in the directory Testing, file mitkMessageTest.cpp
*
*/
} // namespace
#endif
diff --git a/Modules/Core/include/mitkRenderingManager.h b/Modules/Core/include/mitkRenderingManager.h
index 405f45116d..5dab86b41a 100644
--- a/Modules/Core/include/mitkRenderingManager.h
+++ b/Modules/Core/include/mitkRenderingManager.h
@@ -1,503 +1,503 @@
/*============================================================================
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 mitkRenderingManager_h
#define mitkRenderingManager_h
#include <MitkCoreExports.h>
#include <vtkCallbackCommand.h>
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <mitkProperties.h>
#include <mitkPropertyList.h>
#include <mitkTimeGeometry.h>
#include <mitkAntiAliasing.h>
class vtkRenderWindow;
class vtkObject;
namespace mitk
{
class RenderingManagerFactory;
class BaseGeometry;
- class SliceNavigationController;
+ class TimeNavigationController;
class BaseRenderer;
class DataStorage;
/**
* \brief Manager for coordinating the rendering process.
*
* RenderingManager is a central instance retrieving and executing
* RenderWindow update requests. Its main purpose is to coordinate
* distributed requests which cannot be aware of each other - lacking the
* knowledge of whether they are really necessary or not. For example, two
* objects might determine that a specific RenderWindow needs to be updated.
* This would result in one unnecessary update, if both executed the update
* on their own.
*
* The RenderingManager addresses this by letting each such object
* <em>request</em> an update, and waiting for other objects to possibly
* issue the same request. The actual update will then only be executed at a
* well-defined point in the main event loop (this may be each time after
* event processing is done).
*
* Convenience methods for updating all RenderWindows which have been
* registered with the RenderingManager exist. If these methods are not
* used, it is not required to register (add) RenderWindows prior to using
* the RenderingManager.
*
* The methods #ForceImmediateUpdate() and #ForceImmediateUpdateAll() can
* be used to force the RenderWindow update execution without any delay,
* bypassing the request functionality.
*
* The interface of RenderingManager is platform independent. Platform
* specific subclasses have to be implemented, though, to supply an
* appropriate event issuing for controlling the update execution process.
* See method documentation for a description of how this can be done.
*
* \sa TestingRenderingManager An "empty" RenderingManager implementation which
* can be used in tests etc.
*
*/
class MITKCORE_EXPORT RenderingManager : public itk::Object
{
public:
mitkClassMacroItkParent(RenderingManager, itk::Object);
typedef std::vector<vtkRenderWindow *> RenderWindowVector;
typedef std::vector<float> FloatVector;
typedef std::vector<bool> BoolVector;
typedef itk::SmartPointer<DataStorage> DataStoragePointer;
enum RequestType
{
REQUEST_UPDATE_ALL = 0,
REQUEST_UPDATE_2DWINDOWS,
REQUEST_UPDATE_3DWINDOWS
};
static Pointer New();
/** Set the object factory which produces the desired platform specific
* RenderingManager singleton instance. */
static void SetFactory(RenderingManagerFactory *factory);
/** Get the object factory which produces the platform specific
* RenderingManager instances. */
static const RenderingManagerFactory *GetFactory();
/** Returns true if a factory has already been set. */
static bool HasFactory();
/** Get the RenderingManager singleton instance. */
static RenderingManager *GetInstance();
/** Returns true if the singleton instance does already exist. */
static bool IsInstantiated();
/** Adds a RenderWindow. This is required if the methods #RequestUpdateAll
* or #ForceImmediateUpdate are to be used. */
void AddRenderWindow(vtkRenderWindow *renderWindow);
/** Removes a RenderWindow. */
void RemoveRenderWindow(vtkRenderWindow *renderWindow);
/** Get a list of all registered RenderWindows */
const RenderWindowVector &GetAllRegisteredRenderWindows();
/** Requests an update for the specified RenderWindow, to be executed as
* soon as the main loop is ready for rendering. */
void RequestUpdate(vtkRenderWindow *renderWindow);
/** Immediately executes an update of the specified RenderWindow. */
void ForceImmediateUpdate(vtkRenderWindow *renderWindow);
/** Requests all currently registered RenderWindows to be updated.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType. */
void RequestUpdateAll(RequestType type = REQUEST_UPDATE_ALL);
/** Immediately executes an update of all registered RenderWindows.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType. */
void ForceImmediateUpdateAll(RequestType type = REQUEST_UPDATE_ALL);
/**
* @brief Initialize the render windows by the aggregated geometry of all objects that are held in
* the data storage.
*
* @param dataStorage The data storage from which the bounding object can be retrieved
*/
virtual void InitializeViewsByBoundingObjects(const DataStorage* dataStorage);
/**
* @brief Initialize the given render window by the aggregated geometry of all objects that are held in
* the data storage.
*
* @param renderWindow The specifid render window to update
* @param dataStorage The data storage from which the bounding object can be retrieved
* @param resetCamera If this parameter is set to true, the camera controller will be
* set / fit to the center of the rendered image. If set to false, only the
* the slice navigation controller is reset to the geometry without changing
* the camera view / position.
*/
virtual void InitializeViewByBoundingObjects(vtkRenderWindow* renderWindow,
const DataStorage* dataStorage,
bool resetCamera = true);
/**
* @brief Initialize the render windows specified by "type" to the given geometry.
*
* Throws an exception if bounding box has 0 extent due to exceeding double precision range.
*
* @param geometry The geometry to be used to initialize / update a
* render window's time and slice navigation controller
* @param type The type of update request:
* - REQUEST_UPDATE_ALL will initialize / update the
* time and slice navigation controller of all retrieved render windows
* - REQUEST_UPDATE_2DWINDOWS will only initialize / update the
* time and slice navigation controller of 2D render windows
* - REQUEST_UPDATE_3DWINDOWS will only initialize / update the
* time and slice navigation controller of 3D render windows
* @param resetCamera If this parameter is set to true, the camera controller will be
* set / fit to the center of the rendered image. If set to false, only the
* the slice navigation controller is reset to the geometry without changing
* the camera view / position.
*/
virtual bool InitializeViews(const BaseGeometry *geometry,
RequestType type = REQUEST_UPDATE_ALL,
bool resetCamera = true);
/**
* @brief Initialize the render windows specified by "type" to the given geometry.
*
* Throws an exception if bounding box has 0 extent due to exceeding double precision range.
*
* @param geometry The geometry to be used to initialize / update a
* render window's time- and slice navigation controller
* @param type The type of update request:
* - REQUEST_UPDATE_ALL will initialize / update the
* time- and slice navigation controller of all retrieved render windows
* - REQUEST_UPDATE_2DWINDOWS will only initialize / update the
* time- and slice navigation controller of 2D render windows
* - REQUEST_UPDATE_3DWINDOWS will only initialize / update the
* time- and slice navigation controller of 3D render windows
* @param resetCamera If this parameter is set to true, the camera controller will be
* set / fit to the center of the rendered image. If set to false, only the
* the slice navigation controller is reset to the geometry without changing
* the camera view / position.
*/
virtual bool InitializeViews(const TimeGeometry *geometry,
RequestType type = REQUEST_UPDATE_ALL,
bool resetCamera = true);
/**
* @brief Initialize the render windows specified by "type" to the default viewing direction
* without updating the geometry information.
*
* @param type The type of update request:
* - REQUEST_UPDATE_ALL will initialize the
* slice navigation controller of all retrieved render windows
* - REQUEST_UPDATE_2DWINDOWS will only initialize the
* slice navigation controller of 2D render windows
* - REQUEST_UPDATE_3DWINDOWS will only initialize the
* slice navigation controller of 3D render windows
*/
virtual bool InitializeViews(RequestType type = REQUEST_UPDATE_ALL);
/**
* @brief Initialize the specified render window to the given geometry.
*
* Throws an exception if bounding box has 0 extent due to exceeding double precision range.
*
* @param renderWindow The specific render window to update
* @param geometry The geometry to be used to initialize / update the
* render window's time- and slice navigation controller
* @param resetCamera If this parameter is set to true, the camera controller will be
* set / fit to the center of the rendered image. If set to false, only the
* the slice navigation controller is reset to the geometry without changing
* the camera view / position.
*/
virtual bool InitializeView(vtkRenderWindow *renderWindow,
const BaseGeometry *geometry,
bool resetCamera = true);
/**
* @brief Initialize the specified render window to the given geometry.
*
* Throws an exception if bounding box has 0 extent due to exceeding double precision range.
*
* @param renderWindow The specific render window to update
* @param geometry The geometry to be used to initialize / update the
* render window's time- and slice navigation controller
* @param resetCamera If this parameter is set to true, the camera controller will be
* set / fit to the center of the rendered image. If set to false, only the
* the slice navigation controller is reset to the geometry without changing
* the camera view / position.
*/
virtual bool InitializeView(vtkRenderWindow *renderWindow,
const TimeGeometry *geometry,
bool resetCamera = true);
/**
* @brief Initialize the specified render window to the default viewing direction
* without updating the geometry information.
*
* @param renderWindow The specific render window to update
*/
virtual bool InitializeView(vtkRenderWindow *renderWindow);
- /** Gets the (global) SliceNavigationController responsible for
+ /** Gets the (global) TimeNavigationController responsible for
* time-slicing. */
- const SliceNavigationController *GetTimeNavigationController() const;
+ const TimeNavigationController* GetTimeNavigationController() const;
- /** Gets the (global) SliceNavigationController responsible for
+ /** Gets the (global) TimeNavigationController responsible for
* time-slicing. */
- SliceNavigationController *GetTimeNavigationController();
+ TimeNavigationController* GetTimeNavigationController();
~RenderingManager() override;
/** Executes all pending requests. This method has to be called by the
* system whenever a RenderingManager induced request event occurs in
* the system pipeline (see concrete RenderingManager implementations). */
virtual void ExecutePendingRequests();
bool IsRendering() const;
void AbortRendering();
/** En-/Disable LOD increase globally. */
itkSetMacro(LODIncreaseBlocked, bool);
/** En-/Disable LOD increase globally. */
itkGetMacro(LODIncreaseBlocked, bool);
/** En-/Disable LOD increase globally. */
itkBooleanMacro(LODIncreaseBlocked);
/** En-/Disable LOD abort mechanism. */
itkSetMacro(LODAbortMechanismEnabled, bool);
/** En-/Disable LOD abort mechanism. */
itkGetMacro(LODAbortMechanismEnabled, bool);
/** En-/Disable LOD abort mechanism. */
itkBooleanMacro(LODAbortMechanismEnabled);
/** Force a sub-class to start a timer for a pending hires-rendering request */
virtual void StartOrResetTimer(){};
/** To be called by a sub-class from a timer callback */
void ExecutePendingHighResRenderingRequest();
virtual void DoStartRendering(){};
virtual void DoMonitorRendering(){};
virtual void DoFinishAbortRendering(){};
int GetNextLOD(BaseRenderer *renderer);
/** Set current LOD (nullptr means all renderers)*/
void SetMaximumLOD(unsigned int max);
void SetShading(bool state, unsigned int lod);
bool GetShading(unsigned int lod);
void SetClippingPlaneStatus(bool status);
bool GetClippingPlaneStatus();
void SetShadingValues(float ambient, float diffuse, float specular, float specpower);
FloatVector &GetShadingValues();
/** Returns a property list */
PropertyList::Pointer GetPropertyList() const;
/** Returns a property from m_PropertyList */
BaseProperty *GetProperty(const char *propertyKey) const;
/** Sets or adds (if not present) a property in m_PropertyList */
void SetProperty(const char *propertyKey, BaseProperty *propertyValue);
/**
* \brief Setter for internal DataStorage
*
* Sets the DataStorage that is used internally. This instance holds all DataNodes that are
* rendered by the registered BaseRenderers.
*
* If this DataStorage is changed at runtime by calling SetDataStorage(),
* all currently registered BaseRenderers are automatically given the correct instance.
* When a new BaseRenderer is added, it is automatically initialized with the currently active DataStorage.
*/
void SetDataStorage(DataStorage *storage);
/**
* \brief Getter for internal DataStorage
*
* Returns the DataStorage that is used internally. This instance holds all DataNodes that are
* rendered by the registered BaseRenderers.
*/
itkGetMacro(DataStorage, DataStorage*);
itkGetConstMacro(DataStorage, DataStorage*);
/**
* @brief Sets a flag to the given renderwindow to indicated that it has the focus e.g. has been clicked recently.
* @param focusWindow
*/
void SetRenderWindowFocus(vtkRenderWindow *focusWindow);
itkGetMacro(FocusedRenderWindow, vtkRenderWindow *);
itkSetMacro(ConstrainedPanningZooming, bool);
itkGetConstMacro(ConstrainedPanningZooming, bool);
void SetAntiAliasing(AntiAliasing antiAliasing);
itkGetConstMacro(AntiAliasing, AntiAliasing);
protected:
enum
{
RENDERING_INACTIVE = 0,
RENDERING_REQUESTED,
RENDERING_INPROGRESS
};
RenderingManager();
/** Abstract method for generating a system specific event for rendering
* request. This method is called whenever an update is requested */
virtual void GenerateRenderingRequestEvent() = 0;
virtual void InitializePropertyList();
bool m_UpdatePending;
typedef std::map<BaseRenderer *, unsigned int> RendererIntMap;
typedef std::map<BaseRenderer *, bool> RendererBoolMap;
RendererBoolMap m_RenderingAbortedMap;
RendererIntMap m_NextLODMap;
unsigned int m_MaxLOD;
bool m_LODIncreaseBlocked;
bool m_LODAbortMechanismEnabled;
BoolVector m_ShadingEnabled;
bool m_ClippingPlaneEnabled;
FloatVector m_ShadingValues;
static void RenderingStartCallback(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata);
static void RenderingProgressCallback(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata);
static void RenderingEndCallback(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata);
typedef std::map<vtkRenderWindow *, int> RenderWindowList;
RenderWindowList m_RenderWindowList;
RenderWindowVector m_AllRenderWindows;
struct RenderWindowCallbacks
{
vtkCallbackCommand *commands[3u];
};
typedef std::map<vtkRenderWindow *, RenderWindowCallbacks> RenderWindowCallbacksList;
RenderWindowCallbacksList m_RenderWindowCallbacksList;
- itk::SmartPointer<SliceNavigationController> m_TimeNavigationController;
+ itk::SmartPointer<TimeNavigationController> m_TimeNavigationController;
static RenderingManager::Pointer s_Instance;
static RenderingManagerFactory *s_RenderingManagerFactory;
PropertyList::Pointer m_PropertyList;
DataStoragePointer m_DataStorage;
bool m_ConstrainedPanningZooming;
private:
/**
* @brief Initialize the specified renderer to the given geometry.
*
* @param baseRenderer The specific renderer to update
* @param geometry The geometry to be used to initialize / update the
* render window's slice navigation controller
* @param boundingBoxInitialized If this parameter is set to true, the slice navigation controller will be
* initialized / updated with the given geometry. If set to false, the geometry
* of the slice navigation controller is not updated.
* @param mapperID The mapper ID is used to define if the given renderer is a 2D or a 3D renderer.
* In case of a 2D renderer and if "boundingBoxInitialized" is set to true (slice
* navigation controller will be updated with a new geometry), the position of the
* slice navigation controller is set to the center slice.
* @param resetCamera If this parameter is set to true, the camera controller will be
* set / fit to the center of the rendered image. If set to false, only the
* the slice navigation controller is reset to the geometry without changing
* the camera view / position.
*/
void InternalViewInitialization(BaseRenderer *baseRenderer,
const TimeGeometry *geometry,
bool boundingBoxInitialized,
int mapperID,
bool resetCamera);
/**
* @brief Extend the bounding box of the given geometry to make sure the bounding box has an extent bigger than
* zero in any direction.
*
* @param originalGeometry The original geometry to be extended
* @param modifiedGeometry The modified geometry where the new bounds (extended bounding box) are used / set
*/
bool ExtendGeometryForBoundingBox(const TimeGeometry* originalGeometry, TimeGeometry::Pointer& modifiedGeometry);
vtkRenderWindow *m_FocusedRenderWindow;
AntiAliasing m_AntiAliasing;
};
#pragma GCC visibility push(default)
itkEventMacroDeclaration(RenderingManagerEvent, itk::AnyEvent);
itkEventMacroDeclaration(RenderingManagerViewsInitializedEvent, RenderingManagerEvent);
#pragma GCC visibility pop
itkEventMacroDeclaration(FocusChangedEvent, itk::AnyEvent);
/**
* Generic RenderingManager implementation for "non-rendering-platform",
* e.g. for tests. Its factory (TestingRenderingManagerFactory) is
* automatically on start-up and is used by default if not other
* RenderingManagerFactory is instantiated explicitly thereafter.
* (see mitkRenderingManager.cpp)
*/
class MITKCORE_EXPORT TestingRenderingManager : public RenderingManager
{
public:
mitkClassMacro(TestingRenderingManager, RenderingManager);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
protected:
void GenerateRenderingRequestEvent() override {};
};
} // namespace mitk
#endif
diff --git a/Modules/Core/include/mitkSliceNavigationController.h b/Modules/Core/include/mitkSliceNavigationController.h
index 8e58f634d1..a91ad8dc14 100644
--- a/Modules/Core/include/mitkSliceNavigationController.h
+++ b/Modules/Core/include/mitkSliceNavigationController.h
@@ -1,426 +1,371 @@
/*============================================================================
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 mitkSliceNavigationController_h
#define mitkSliceNavigationController_h
#include <MitkCoreExports.h>
#include <mitkBaseController.h>
#include <mitkMessage.h>
#include <mitkAnatomicalPlanes.h>
#include <mitkRenderingManager.h>
-#include <mitkRestorePlanePositionOperation.h>
#include <mitkTimeGeometry.h>
#pragma GCC visibility push(default)
#include <itkEventObject.h>
#pragma GCC visibility pop
#include <itkCommand.h>
namespace mitk
{
#define mitkTimeGeometryEventMacro(classname, super) \
class MITKCORE_EXPORT classname : public super \
{ \
public: \
typedef classname Self; \
typedef super Superclass; \
classname(TimeGeometry *aTimeGeometry, unsigned int aPos) : Superclass(aTimeGeometry, aPos) {} \
virtual ~classname() {} \
virtual const char *GetEventName() const { return #classname; } \
virtual bool CheckEvent(const ::itk::EventObject *e) const { return dynamic_cast<const Self *>(e); } \
virtual ::itk::EventObject *MakeObject() const { return new Self(GetTimeGeometry(), GetPos()); } \
private: \
void operator=(const Self &); \
}
class PlaneGeometry;
class BaseGeometry;
class BaseRenderer;
/**
* \brief Controls the selection of the slice the associated BaseRenderer
* will display
*
- * A SliceNavigationController takes a BaseGeometry or a TimeGeometry as input world geometry
- * (TODO what are the exact requirements?) and generates a TimeGeometry
- * as output. The TimeGeometry holds a number of SlicedGeometry3Ds and
+ * A SliceNavigationController takes a TimeGeometry as input world time geometry
+ * and generates a different TimeGeometry as output, depending on the current
+ * view direction and the current time step.
+ * The TimeGeometry holds a number of SlicedGeometry3Ds and
* these in turn hold a series of PlaneGeometries. One of these PlaneGeometries is
* selected as world geometry for the BaseRenderers associated to 2D views.
*
- * The SliceNavigationController holds has Steppers (one for the slice, a
- * second for the time step), which control the selection of a single
- * PlaneGeometry from the TimeGeometry. SliceNavigationController generates
- * ITK events to tell observers, like a BaseRenderer, when the selected slice
- * or timestep changes.
+ * The SliceNavigationController holds a Stepper, which controls the
+ * slice-selection of a single PlaneGeometry from the TimeGeometry.
+ * SliceNavigationController generates ITK events to tell observers,
+ * like a BaseRenderer, when the selected slice changes.
*
* Example:
* \code
* // Initialization
* sliceCtrl = mitk::SliceNavigationController::New();
*
* // Tell the navigation controller the geometry to be sliced
* // (with geometry a BaseGeometry::ConstPointer)
* sliceCtrl->SetInputWorldTimeGeometry(geometry.GetPointer());
*
* // Tell the navigation controller in which direction it shall slice the data
* sliceCtrl->SetViewDirection(mitk::AnatomicalPlane::Axial);
*
* // Connect one or more BaseRenderer to this navigation controller, i.e.:
* // events sent by the navigation controller when stepping through the slices
- * // (e.g. by sliceCtrl->GetSlice()->Next()) will be received by the BaseRenderer
- * // (in this example only slice-changes, see also ConnectGeometryTimeEvent
- * // and ConnectGeometryEvents.)
+ * // (e.g. by sliceCtrl->GetStepper()->Next()) will be received by the BaseRenderer
+ * // (in this example only slice-changes, see also ConnectGeometryEvents.)
* sliceCtrl->ConnectGeometrySliceEvent(renderer.GetPointer());
*
* //create a world geometry and send the information to the connected renderer(s)
* sliceCtrl->Update();
* \endcode
*
*
* You can connect visible navigation widgets to a SliceNavigationController, e.g., a
* QmitkSliceNavigationWidget (for Qt):
*
* \code
* // Create the visible navigation widget (a slider with a spin-box)
* QmitkSliceNavigationWidget* navigationWidget =
* new QmitkSliceNavigationWidget(parent);
*
* // Connect the navigation widget to the slice-stepper of the
- * // SliceNavigationController. For initialization (position, mininal and
+ * // SliceNavigationController. For initialization (position, minimal and
* // maximal values) the values of the SliceNavigationController are used.
* // Thus, accessing methods of a navigation widget is normally not necessary,
* // since everything can be set via the (Qt-independent) SliceNavigationController.
* // The QmitkStepperAdapter converts the Qt-signals to Qt-independent
* // itk-events.
- * new QmitkStepperAdapter(navigationWidget, sliceCtrl->GetSlice());
+ * new QmitkStepperAdapter(navigationWidget, sliceCtrl->GetStepper());
* \endcode
*
* If you do not want that all renderwindows are updated when a new slice is
* selected, you can use a specific RenderingManager, which updates only those
* renderwindows that should be updated. This is sometimes useful when a 3D view
* does not need to be updated when the slices in some 2D views are changed.
*
* \code
* // create a specific RenderingManager
* mitk::RenderingManager::Pointer myManager = mitk::RenderingManager::New();
*
* // tell the RenderingManager to update only renderwindow1 and renderwindow2
* myManager->AddRenderWindow(renderwindow1);
* myManager->AddRenderWindow(renderwindow2);
*
* // tell the SliceNavigationController of renderwindow1 and renderwindow2
* // to use the specific RenderingManager instead of the global one
* renderwindow1->GetSliceNavigationController()->SetRenderingManager(myManager);
* renderwindow2->GetSliceNavigationController()->SetRenderingManager(myManager);
* \endcode
*
* \todo implement for non-evenly-timed geometry!
* \ingroup NavigationControl
*/
class MITKCORE_EXPORT SliceNavigationController : public BaseController
{
public:
mitkClassMacro(SliceNavigationController, BaseController);
itkNewMacro(Self);
/**
* \brief Set the input world time geometry out of which the
* geometries for slicing will be created.
*
- * Any previous previous set input geometry (3D or Time) will
- * be ignored in future.
+ * Any previous set input geometry (3D or Time) will
+ * be ignored in the future.
*/
void SetInputWorldTimeGeometry(const TimeGeometry* geometry);
itkGetConstObjectMacro(InputWorldTimeGeometry, TimeGeometry);
/**
* \brief Access the created geometry
*/
itkGetConstObjectMacro(CreatedWorldGeometry, TimeGeometry);
itkGetObjectMacro(CreatedWorldGeometry, TimeGeometry);
/**
* \brief Set the desired view directions
*
* \sa ViewDirection
* \sa Update(AnatomicalPlane viewDirection, bool top = true,
* bool frontside = true, bool rotated = false)
*/
itkSetEnumMacro(ViewDirection, AnatomicalPlane);
itkGetEnumMacro(ViewDirection, AnatomicalPlane);
/**
* \brief Set the default view direction
*
* This is used to re-initialize the view direction of the SNC to the
* default value with SetViewDirectionToDefault()
*
* \sa ViewDirection
* \sa Update(AnatomicalPlane viewDirection, bool top = true,
* bool frontside = true, bool rotated = false)
*/
itkSetEnumMacro(DefaultViewDirection, AnatomicalPlane);
itkGetEnumMacro(DefaultViewDirection, AnatomicalPlane);
const char *GetViewDirectionAsString() const;
virtual void SetViewDirectionToDefault();
/**
* \brief Do the actual creation and send it to the connected
* observers (renderers)
*
*/
virtual void Update();
/**
* \brief Extended version of Update, additionally allowing to
* specify the direction/orientation of the created geometry.
*
*/
virtual void Update(AnatomicalPlane viewDirection, bool top = true, bool frontside = true, bool rotated = false);
/**
* \brief Send the created geometry to the connected
* observers (renderers)
*
* Called by Update().
*/
virtual void SendCreatedWorldGeometry();
/**
* \brief Tell observers to re-read the currently selected 2D geometry
*
*/
virtual void SendCreatedWorldGeometryUpdate();
/**
* \brief Send the currently selected slice to the connected
* observers (renderers)
*
* Called by Update().
*/
virtual void SendSlice();
- /**
- * \brief Send the currently selected time to the connected
- * observers (renderers)
- *
- * Called by Update().
- */
- virtual void SendTime();
-
class MITKCORE_EXPORT TimeGeometryEvent : public itk::AnyEvent
{
public:
typedef TimeGeometryEvent Self;
typedef itk::AnyEvent Superclass;
TimeGeometryEvent(TimeGeometry* aTimeGeometry, unsigned int aPos) : m_TimeGeometry(aTimeGeometry), m_Pos(aPos) {}
~TimeGeometryEvent() override {}
const char* GetEventName() const override { return "TimeGeometryEvent"; }
bool CheckEvent(const ::itk::EventObject* e) const override { return dynamic_cast<const Self*>(e); }
::itk::EventObject* MakeObject() const override { return new Self(m_TimeGeometry, m_Pos); }
TimeGeometry* GetTimeGeometry() const { return m_TimeGeometry; }
unsigned int GetPos() const { return m_Pos; }
private:
TimeGeometry::Pointer m_TimeGeometry;
unsigned int m_Pos;
// TimeGeometryEvent(const Self&);
void operator=(const Self&); // just hide
};
mitkTimeGeometryEventMacro(GeometrySendEvent, TimeGeometryEvent);
mitkTimeGeometryEventMacro(GeometryUpdateEvent, TimeGeometryEvent);
- mitkTimeGeometryEventMacro(GeometryTimeEvent, TimeGeometryEvent);
mitkTimeGeometryEventMacro(GeometrySliceEvent, TimeGeometryEvent);
template <typename T>
void ConnectGeometrySendEvent(T* receiver)
{
auto eventReceptorCommand = itk::ReceptorMemberCommand<T>::New();
eventReceptorCommand->SetCallbackFunction(receiver, &T::SetGeometry);
unsigned long tag = AddObserver(GeometrySendEvent(nullptr, 0), eventReceptorCommand);
m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
}
template <typename T>
void ConnectGeometryUpdateEvent(T* receiver)
{
auto eventReceptorCommand = itk::ReceptorMemberCommand<T>::New();
eventReceptorCommand->SetCallbackFunction(receiver, &T::UpdateGeometry);
unsigned long tag = AddObserver(GeometryUpdateEvent(nullptr, 0), eventReceptorCommand);
m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
}
template <typename T>
void ConnectGeometrySliceEvent(T* receiver)
{
auto eventReceptorCommand = itk::ReceptorMemberCommand<T>::New();
eventReceptorCommand->SetCallbackFunction(receiver, &T::SetGeometrySlice);
unsigned long tag = AddObserver(GeometrySliceEvent(nullptr, 0), eventReceptorCommand);
m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
}
- template <typename T>
- void ConnectGeometryTimeEvent(T* receiver)
- {
- auto eventReceptorCommand = itk::ReceptorMemberCommand<T>::New();
- eventReceptorCommand->SetCallbackFunction(receiver, &T::SetGeometryTime);
- unsigned long tag = AddObserver(GeometryTimeEvent(nullptr, 0), eventReceptorCommand);
- m_ReceiverToObserverTagsMap[static_cast<void*>(receiver)].push_back(tag);
- }
-
- template <typename T>
- void ConnectGeometryEvents(T* receiver)
- {
- // connect sendEvent only once
- ConnectGeometrySliceEvent(receiver, false);
- ConnectGeometryTimeEvent(receiver);
- }
-
// use a templated method to get the right offset when casting to void*
template <typename T>
void Disconnect(T* receiver)
{
auto i = m_ReceiverToObserverTagsMap.find(static_cast<void*>(receiver));
if (i == m_ReceiverToObserverTagsMap.end())
return;
const std::list<unsigned long>& tags = i->second;
for (auto tagIter = tags.begin(); tagIter != tags.end(); ++tagIter)
{
RemoveObserver(*tagIter);
}
m_ReceiverToObserverTagsMap.erase(i);
}
Message1<const Point3D&> SetCrosshairEvent;
- /**
- * \brief To connect multiple SliceNavigationController, we can
- * act as an observer ourselves: implemented interface
- * \warning not implemented
- */
- virtual void SetGeometry(const itk::EventObject& geometrySliceEvent);
-
- /**
- * \brief To connect multiple SliceNavigationController, we can
- * act as an observer ourselves: implemented interface
- */
- virtual void SetGeometrySlice(const itk::EventObject& geometrySliceEvent);
-
- /**
- * \brief To connect multiple SliceNavigationController, we can
- * act as an observer ourselves: implemented interface
- */
- virtual void SetGeometryTime(const itk::EventObject& geometryTimeEvent);
-
/** \brief Positions the SNC according to the specified point */
void SelectSliceByPoint(const Point3D& point);
/** \brief Returns the BaseGeometry of the currently selected time step. */
const BaseGeometry* GetCurrentGeometry3D();
/** \brief Returns the currently selected Plane in the current
* BaseGeometry (if existent).
*/
const PlaneGeometry* GetCurrentPlaneGeometry();
/** \brief Sets / gets the BaseRenderer associated with this SNC (if any).
* While the BaseRenderer is not directly used by SNC, this is a convenience
* method to enable BaseRenderer access via the SNC.
*/
itkSetObjectMacro(Renderer, BaseRenderer);
itkGetMacro(Renderer, BaseRenderer*);
/** \brief Re-orients the slice stack. All slices will be oriented to the given normal vector.
The given point (world coordinates) defines the selected slice.
Careful: The resulting axis vectors are not clearly defined this way. If you want to define them clearly, use
ReorientSlices (const Point3D &point, const Vector3D &axisVec0, const Vector3D &axisVec1).
*/
void ReorientSlices(const Point3D& point, const Vector3D& normal);
/** \brief Re-orients the slice stack so that all planes are oriented according to the
* given axis vectors. The given Point eventually defines selected slice.
*/
void ReorientSlices(const Point3D& point, const Vector3D& axisVec0, const Vector3D& axisVec1);
void ExecuteOperation(Operation* operation) override;
/**
* \brief Feature option to lock planes during mouse interaction.
* This option flag disables the mouse event which causes the center
* cross to move near by.
*/
itkSetMacro(SliceLocked, bool);
itkGetMacro(SliceLocked, bool);
itkBooleanMacro(SliceLocked);
/**
* \brief Feature option to lock slice rotation.
*
* This option flag disables separately the rotation of a slice which is
* implemented in mitkSliceRotator.
*/
itkSetMacro(SliceRotationLocked, bool);
itkGetMacro(SliceRotationLocked, bool);
itkBooleanMacro(SliceRotationLocked);
/**
* \brief Adjusts the numerical range of the slice stepper according to
* the current geometry orientation of this SNC's SlicedGeometry.
*/
void AdjustSliceStepperRange();
- /** \brief Convenience method that returns the time step currently selected by the controller.*/
- TimeStepType GetSelectedTimeStep() const;
-
- /** \brief Convenience method that returns the time point that corresponds to the selected
- * time step. The conversion is done using the time geometry of the SliceNavigationController.
- * If the time geometry is not yet set, this function will always return 0.0.*/
- TimePointType GetSelectedTimePoint() const;
-
protected:
SliceNavigationController();
~SliceNavigationController() override;
void CreateWorldGeometry(bool top, bool frontside, bool rotated);
TimeGeometry::ConstPointer m_InputWorldTimeGeometry;
TimeGeometry::Pointer m_CreatedWorldGeometry;
AnatomicalPlane m_ViewDirection;
AnatomicalPlane m_DefaultViewDirection;
RenderingManager::Pointer m_RenderingManager;
BaseRenderer* m_Renderer;
bool m_BlockUpdate;
bool m_SliceLocked;
bool m_SliceRotationLocked;
typedef std::map<void*, std::list<unsigned long>> ObserverTagsMapType;
ObserverTagsMapType m_ReceiverToObserverTagsMap;
};
} // namespace mitk
#endif
diff --git a/Modules/Core/include/mitkTimeNavigationController.h b/Modules/Core/include/mitkTimeNavigationController.h
new file mode 100644
index 0000000000..16128e2106
--- /dev/null
+++ b/Modules/Core/include/mitkTimeNavigationController.h
@@ -0,0 +1,172 @@
+/*============================================================================
+
+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 TimeNavigationController_h
+#define TimeNavigationController_h
+
+#include <MitkCoreExports.h>
+
+#include <mitkBaseController.h>
+#include <mitkTimeGeometry.h>
+
+#include <itkCommand.h>
+
+namespace mitk
+{
+ /**
+ * \brief Controls the time-related properties of the time stepper, according to the
+ * given input world time geomtry.
+ *
+ * A TimeNavigationController takes a TimeGeometry as input world time geometry
+ * and sets the properties of the associated stepper (BaseController).
+ * The time-related properties are:
+ * - steps: the number of input time steps
+ * - pos: the current time step / position of the stepper
+ * - range: the time bounds for the slider (minimum, maximum)
+ *
+ * The timestep controls the selection of a specific time point from the TimeGeometry.
+ * The TimeNavigationController generates ITK events to tell observers,
+ * like a BaseRenderer, when the selected timestep changes.
+ *
+ * Example:
+ * \code
+ * // Initialize the time navigation controller.
+ * timeCtrl = mitk::TimeNavigationController::New();
+ *
+ * // Set the required input world time geomtry (a TimeGeometry::ConstPointer).
+ * timeCtrl->SetInputWorldTimeGeometry(geometry.GetPointer());
+ *
+ * // Set the time-related properties and send the information to the connected renderer(s).
+ * timeCtrl->Update();
+ * \endcode
+ *
+ * Vvisible navigation widgets can be connected to a TimeNavigationController, e.g., a
+ * QmitkSliceNavigationWidget (for Qt):
+ *
+ * \code
+ * // Create the visible navigation widget (a slider with a spin-box).
+ * QmitkSliceNavigationWidget* navigationWidget = new QmitkSliceNavigationWidget(parent);
+ *
+ * // Connect the navigation widget to the time-stepper of the
+ * // TimeNavigationController. For initialization (timestep, minimal and
+ * // maximal values) the values of the TimeNavigationController are used.
+ * // Thus, accessing methods of a navigation widget is normally not necessary,
+ * // since everything can be set via the (Qt-independent) TimeNavigationController.
+ * // The QmitkStepperAdapter converts the Qt-signals to Qt-independent
+ * // itk-events.
+ * new QmitkStepperAdapter(navigationWidget, timeCtrl->GetStepper());
+ * \endcode
+ */
+ class MITKCORE_EXPORT TimeNavigationController : public BaseController
+ {
+ public:
+
+ mitkClassMacro(TimeNavigationController, BaseController);
+ itkNewMacro(Self);
+
+ /**
+ * \brief Set the input time geometry out of which the
+ * time-related properties will be generated.
+ *
+ * Any previous set input geometry (3D or Time) will
+ * be ignored in the future.
+ */
+ void SetInputWorldTimeGeometry(const TimeGeometry* geometry);
+ itkGetConstObjectMacro(InputWorldTimeGeometry, mitk::TimeGeometry);
+
+ /**
+ * \brief Do the actual time-related properties extraction
+ and send the currently selected time step to the connecte
+ observers (renderers).
+ */
+ virtual void Update();
+
+ /**
+ * \brief Send the currently selected time step to the connected
+ * observers (renderers).
+ *
+ * Called by Update().
+ */
+ virtual void SendTime();
+
+ class MITKCORE_EXPORT TimeEvent : public itk::AnyEvent
+ {
+ public:
+
+ typedef TimeEvent Self;
+ typedef itk::AnyEvent Superclass;
+
+ TimeEvent(TimeStepType timeStep) : m_TimeStep(timeStep) {}
+ ~TimeEvent() override {}
+ const char *GetEventName() const override { return "TimeEvent"; }
+ bool CheckEvent(const ::itk::EventObject *e) const override { return dynamic_cast<const Self *>(e); }
+ ::itk::EventObject *MakeObject() const override { return new Self(m_TimeStep); }
+ TimeStepType GetTimeStep() const { return m_TimeStep; }
+ private:
+
+ TimeStepType m_TimeStep;
+ void operator=(const Self &);
+ };
+
+ template <typename T>
+ void ConnectTimeEvent(T* receiver)
+ {
+ typedef typename itk::ReceptorMemberCommand<T>::Pointer ReceptorMemberCommandPointer;
+ ReceptorMemberCommandPointer eventReceptorCommand = itk::ReceptorMemberCommand<T>::New();
+ eventReceptorCommand->SetCallbackFunction(receiver, &T::SetGeometryTime);
+ unsigned long tag = AddObserver(TimeEvent(0), eventReceptorCommand);
+ m_ReceiverToObserverTagsMap[static_cast<void *>(receiver)].push_back(tag);
+ }
+
+ // use a templated method to get the right offset when casting to void*
+ template <typename T>
+ void Disconnect(T* receiver)
+ {
+ auto i = m_ReceiverToObserverTagsMap.find(static_cast<void*>(receiver));
+ if (i == m_ReceiverToObserverTagsMap.end())
+ return;
+ const std::list<unsigned long>& tags = i->second;
+ for (auto tagIter = tags.begin(); tagIter != tags.end(); ++tagIter)
+ {
+ RemoveObserver(*tagIter);
+ }
+ m_ReceiverToObserverTagsMap.erase(i);
+ }
+
+ /**
+ * \brief Convenience method that returns the time step currently selected by the controller.
+ */
+ TimeStepType GetSelectedTimeStep() const;
+
+ /**
+ * \brief Convenience method that returns the time point that corresponds to the selected
+ * time step. The conversion is done using the time geometry of the controller.
+ * If the time geometry is not yet set, this function will always return 0.0.
+ */
+ TimePointType GetSelectedTimePoint() const;
+
+ protected:
+
+ TimeNavigationController();
+ ~TimeNavigationController() override;
+
+ TimeGeometry::ConstPointer m_InputWorldTimeGeometry;
+
+ bool m_BlockUpdate;
+
+ typedef std::map<void*, std::list<unsigned long>> ObserverTagsMapType;
+ ObserverTagsMapType m_ReceiverToObserverTagsMap;
+ };
+
+} // namespace mitk
+
+#endif
diff --git a/Modules/Core/src/Controllers/mitkBaseController.cpp b/Modules/Core/src/Controllers/mitkBaseController.cpp
index 135ac0763f..89342a64a9 100644
--- a/Modules/Core/src/Controllers/mitkBaseController.cpp
+++ b/Modules/Core/src/Controllers/mitkBaseController.cpp
@@ -1,48 +1,39 @@
/*============================================================================
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 "mitkBaseController.h"
#include "mitkBaseRenderer.h"
-mitk::BaseController::BaseController() : m_LastUpdateTime(0)
+mitk::BaseController::BaseController()
+ : m_LastUpdateTime(0)
{
- m_Slice = Stepper::New();
- m_Time = Stepper::New();
+ m_Stepper = Stepper::New();
}
mitk::BaseController::~BaseController()
{
}
void mitk::BaseController::ExecuteOperation(mitk::Operation * /* *operation */)
{
}
-mitk::Stepper *mitk::BaseController::GetSlice()
+mitk::Stepper *mitk::BaseController::GetStepper()
{
- return m_Slice.GetPointer();
+ return m_Stepper.GetPointer();
}
-const mitk::Stepper* mitk::BaseController::GetSlice() const
+const mitk::Stepper* mitk::BaseController::GetStepper() const
{
- return m_Slice.GetPointer();
+ return m_Stepper.GetPointer();
}
-mitk::Stepper *mitk::BaseController::GetTime()
-{
- return m_Time.GetPointer();
-}
-
-const mitk::Stepper* mitk::BaseController::GetTime() const
-{
- return m_Time.GetPointer();
-}
diff --git a/Modules/Core/src/Controllers/mitkCallbackFromGUIThread.cpp b/Modules/Core/src/Controllers/mitkCallbackFromGUIThread.cpp
index 1526f7294a..9550c6a4ff 100644
--- a/Modules/Core/src/Controllers/mitkCallbackFromGUIThread.cpp
+++ b/Modules/Core/src/Controllers/mitkCallbackFromGUIThread.cpp
@@ -1,50 +1,50 @@
/*============================================================================
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 "mitkCallbackFromGUIThread.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
mitk::CallbackFromGUIThread *mitk::CallbackFromGUIThread::m_Instance = nullptr;
mitk::CallbackFromGUIThreadImplementation *mitk::CallbackFromGUIThread::m_Implementation = nullptr;
namespace mitk
{
CallbackFromGUIThread::CallbackFromGUIThread() {}
CallbackFromGUIThread *CallbackFromGUIThread::GetInstance()
{
if (!m_Instance)
{
m_Instance = new CallbackFromGUIThread();
}
return m_Instance;
}
void CallbackFromGUIThread::RegisterImplementation(CallbackFromGUIThreadImplementation *implementation)
{
m_Implementation = implementation;
}
void CallbackFromGUIThread::CallThisFromGUIThread(itk::Command *cmd, itk::EventObject *e)
{
if (m_Implementation)
{
m_Implementation->CallThisFromGUIThread(cmd, e);
}
else
{
MITK_ERROR << "in mitk::CallbackFromGUIThread::CallbackFromGUIThread(): no implementation registered."
<< std::endl;
}
}
} // namespace
diff --git a/Modules/Core/src/Controllers/mitkCameraRotationController.cpp b/Modules/Core/src/Controllers/mitkCameraRotationController.cpp
index f6c94adbc5..a542ae61ec 100644
--- a/Modules/Core/src/Controllers/mitkCameraRotationController.cpp
+++ b/Modules/Core/src/Controllers/mitkCameraRotationController.cpp
@@ -1,89 +1,89 @@
/*============================================================================
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 "mitkCameraRotationController.h"
#include <itkCommand.h>
#include <vtkCamera.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include "mitkRenderingManager.h"
#include "mitkVtkPropRenderer.h"
mitk::CameraRotationController::CameraRotationController()
: BaseController(), m_LastStepperValue(180), m_Camera(nullptr), m_RenderWindow(nullptr)
{
- m_Slice->SetAutoRepeat(true);
- m_Slice->SetSteps(360);
- m_Slice->SetPos(180);
+ m_Stepper->SetAutoRepeat(true);
+ m_Stepper->SetSteps(360);
+ m_Stepper->SetPos(180);
itk::SimpleMemberCommand<CameraRotationController>::Pointer sliceStepperChangedCommand, timeStepperChangedCommand;
sliceStepperChangedCommand = itk::SimpleMemberCommand<CameraRotationController>::New();
sliceStepperChangedCommand->SetCallbackFunction(this, &CameraRotationController::RotateCamera);
- m_Slice->AddObserver(itk::ModifiedEvent(), sliceStepperChangedCommand);
+ m_Stepper->AddObserver(itk::ModifiedEvent(), sliceStepperChangedCommand);
}
mitk::CameraRotationController::~CameraRotationController()
{
}
void mitk::CameraRotationController::RotateCamera()
{
if (!m_Camera)
{
this->AcquireCamera();
}
if (m_Camera)
{
- int newStepperValue = m_Slice->GetPos();
+ int newStepperValue = m_Stepper->GetPos();
m_Camera->Azimuth(m_LastStepperValue - newStepperValue);
m_LastStepperValue = newStepperValue;
// const_cast< RenderWindow* >(m_RenderWindow)->RequestUpdate(); // TODO does not work with movie generator!
mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow);
// m_MultiWidget->RequestUpdate();
}
}
void mitk::CameraRotationController::AcquireCamera()
{
BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(m_RenderWindow);
const auto *propRenderer = dynamic_cast<const mitk::VtkPropRenderer *>(renderer);
if (propRenderer)
{
// get vtk renderer
vtkRenderer *vtkrenderer = propRenderer->GetVtkRenderer();
if (vtkrenderer)
{
// get vtk camera
vtkCamera *vtkcam = vtkrenderer->GetActiveCamera();
if (vtkcam)
{
// vtk smart pointer handling
if (!m_Camera)
{
m_Camera = vtkcam;
m_Camera->Register(nullptr);
}
else
{
m_Camera->UnRegister(nullptr);
m_Camera = vtkcam;
m_Camera->Register(nullptr);
}
}
}
}
}
diff --git a/Modules/Core/src/Controllers/mitkCrosshairManager.cpp b/Modules/Core/src/Controllers/mitkCrosshairManager.cpp
index 2a5d497f4c..527d8dbaf9 100644
--- a/Modules/Core/src/Controllers/mitkCrosshairManager.cpp
+++ b/Modules/Core/src/Controllers/mitkCrosshairManager.cpp
@@ -1,167 +1,168 @@
/*============================================================================
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 "mitkCrosshairManager.h"
#include <mitkException.h>
#include <mitkResliceMethodProperty.h>
#include <mitkCrosshairVtkMapper2D.h>
mitk::CrosshairManager::CrosshairManager(BaseRenderer* baseRenderer)
{
m_CrosshairDataNode = mitk::DataNode::New();
std::string rendererName = std::string(baseRenderer->GetName());
m_CrosshairDataNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New());
m_CrosshairDataNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(5));
m_CrosshairDataNode->SetProperty("Crosshair.Gap Size", mitk::IntProperty::New(32));
// set the crosshair only visible for this specific renderer
m_CrosshairDataNode->SetVisibility(false);
m_CrosshairDataNode->SetVisibility(true, baseRenderer);
m_CrosshairDataNode->SetProperty("name", mitk::StringProperty::New(std::string(rendererName + "crosshairData")));
m_CrosshairDataNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_CrosshairData = CrosshairData::New();
m_CrosshairDataNode->SetData(m_CrosshairData);
m_CrosshairDataNode->SetMapper(mitk::BaseRenderer::Standard2D, mitk::CrosshairVtkMapper2D::New());
}
mitk::CrosshairManager::~CrosshairManager()
{
}
void mitk::CrosshairManager::SetCrosshairPosition(const Point3D& selectedPoint)
{
if (m_CrosshairData.IsNull())
{
mitkThrow() << "No crosshair data available. Crosshair is in an invalid state.";
}
m_CrosshairData->SetPosition(selectedPoint);
}
void mitk::CrosshairManager::UpdateCrosshairPosition(const SliceNavigationController* sliceNavigationController)
{
if (m_CrosshairData.IsNull())
{
mitkThrow() << "No crosshair data available. Crosshair is in an invalid state.";
}
Point3D crosshairPosition = m_CrosshairData->GetPosition();
auto viewDirection = sliceNavigationController->GetViewDirection();
- unsigned int slicePosition = sliceNavigationController->GetSlice()->GetPos();
+ unsigned int slicePosition = sliceNavigationController->GetStepper()->GetPos();
+
switch (viewDirection)
{
case AnatomicalPlane::Original:
return;
case AnatomicalPlane::Axial:
{
crosshairPosition[2] = slicePosition;
break;
}
case AnatomicalPlane::Coronal:
{
crosshairPosition[1] = slicePosition;
break;
}
case AnatomicalPlane::Sagittal:
{
crosshairPosition[0] = slicePosition;
break;
}
}
m_CrosshairData->SetPosition(crosshairPosition);
}
mitk::Point3D mitk::CrosshairManager::GetCrosshairPosition() const
{
if (m_CrosshairData.IsNull())
{
mitkThrow() << "No crosshair data available. Crosshair is in an invalid state.";
}
return m_CrosshairData->GetPosition();
}
void mitk::CrosshairManager::SetCrosshairVisibility(bool visible, const BaseRenderer* baseRenderer)
{
if (m_CrosshairDataNode.IsNull())
{
mitkThrow() << "No crosshair data node available. Crosshair is in an invalid state.";
}
m_CrosshairDataNode->SetVisibility(visible, baseRenderer);
}
bool mitk::CrosshairManager::GetCrosshairVisibility(const BaseRenderer* baseRenderer) const
{
if (m_CrosshairDataNode.IsNull())
{
mitkThrow() << "No crosshair data node available. Crosshair is in an invalid state.";
}
bool visibility = false;
if (m_CrosshairDataNode->GetVisibility(visibility, baseRenderer))
{
return false;
}
return visibility;
}
void mitk::CrosshairManager::SetCrosshairGap(unsigned int gapSize)
{
if (m_CrosshairDataNode.IsNull())
{
mitkThrow() << "No crosshair data node available. Crosshair is in an invalid state.";
}
m_CrosshairDataNode->SetIntProperty("Crosshair.Gap Size", gapSize);
}
void mitk::CrosshairManager::AddCrosshairNodeToDataStorage(DataStorage* dataStorage)
{
if (m_CrosshairDataNode.IsNull())
{
mitkThrow() << "No crosshair data node available. Crosshair is in an invalid state.";
}
if (nullptr == dataStorage)
{
mitkThrow() << "Datastorage is invalid. Cannot add crosshair node.";
}
if (!dataStorage->Exists(m_CrosshairDataNode))
{
dataStorage->Add(m_CrosshairDataNode);
}
}
void mitk::CrosshairManager::RemoveCrosshairNodeFromDataStorage(DataStorage* dataStorage)
{
if (m_CrosshairDataNode.IsNull())
{
mitkThrow() << "No crosshair data node available. Crosshair is in an invalid state.";
}
if (nullptr == dataStorage)
{
mitkThrow() << "Datastorage is invalid. Cannot remove crosshair node.";
}
dataStorage->Remove(m_CrosshairDataNode);
}
diff --git a/Modules/Core/src/Controllers/mitkRenderingManager.cpp b/Modules/Core/src/Controllers/mitkRenderingManager.cpp
index 5df02a1a3e..3aee8165b1 100644
--- a/Modules/Core/src/Controllers/mitkRenderingManager.cpp
+++ b/Modules/Core/src/Controllers/mitkRenderingManager.cpp
@@ -1,791 +1,791 @@
/*============================================================================
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 <mitkRenderingManager.h>
#include <mitkRenderingManagerFactory.h>
#include <mitkBaseRenderer.h>
#include <mitkCameraController.h>
+#include <mitkTimeNavigationController.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkProportionalTimeGeometry.h>
#include <vtkCamera.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRendererCollection.h>
#include <itkCommand.h>
#include <mitkVtkPropRenderer.h>
namespace mitk
{
itkEventMacroDefinition(RenderingManagerEvent, itk::AnyEvent);
itkEventMacroDefinition(RenderingManagerViewsInitializedEvent, RenderingManagerEvent);
itkEventMacroDefinition(FocusChangedEvent, itk::AnyEvent);
RenderingManager::Pointer RenderingManager::s_Instance = nullptr;
RenderingManagerFactory *RenderingManager::s_RenderingManagerFactory = nullptr;
RenderingManager::RenderingManager()
: m_UpdatePending(false),
m_MaxLOD(1),
m_LODIncreaseBlocked(false),
m_LODAbortMechanismEnabled(false),
m_ClippingPlaneEnabled(false),
- m_TimeNavigationController(SliceNavigationController::New()),
+ m_TimeNavigationController(TimeNavigationController::New()),
m_DataStorage(nullptr),
m_ConstrainedPanningZooming(true),
m_FocusedRenderWindow(nullptr),
m_AntiAliasing(AntiAliasing::FastApproximate)
{
m_ShadingEnabled.assign(3, false);
m_ShadingValues.assign(4, 0.0);
InitializePropertyList();
}
RenderingManager::~RenderingManager()
{
// Decrease reference counts of all registered vtkRenderWindows for
// proper destruction
RenderWindowVector::iterator it;
for (it = m_AllRenderWindows.begin(); it != m_AllRenderWindows.end(); ++it)
{
(*it)->UnRegister(nullptr);
auto callbacks_it = this->m_RenderWindowCallbacksList.find(*it);
if (callbacks_it != this->m_RenderWindowCallbacksList.end())
{
(*it)->RemoveObserver(callbacks_it->second.commands[0u]);
(*it)->RemoveObserver(callbacks_it->second.commands[1u]);
(*it)->RemoveObserver(callbacks_it->second.commands[2u]);
}
}
}
void RenderingManager::SetFactory(RenderingManagerFactory *factory) { s_RenderingManagerFactory = factory; }
const RenderingManagerFactory *RenderingManager::GetFactory() { return s_RenderingManagerFactory; }
bool RenderingManager::HasFactory()
{
if (RenderingManager::s_RenderingManagerFactory)
{
return true;
}
else
{
return false;
}
}
RenderingManager::Pointer RenderingManager::New()
{
const RenderingManagerFactory *factory = GetFactory();
if (factory == nullptr)
return nullptr;
return factory->CreateRenderingManager();
}
RenderingManager *RenderingManager::GetInstance()
{
if (!RenderingManager::s_Instance)
{
if (s_RenderingManagerFactory)
{
s_Instance = s_RenderingManagerFactory->CreateRenderingManager();
}
}
return s_Instance;
}
bool RenderingManager::IsInstantiated()
{
if (RenderingManager::s_Instance)
return true;
else
return false;
}
void RenderingManager::AddRenderWindow(vtkRenderWindow *renderWindow)
{
if (renderWindow && (m_RenderWindowList.find(renderWindow) == m_RenderWindowList.end()))
{
m_RenderWindowList[renderWindow] = RENDERING_INACTIVE;
m_AllRenderWindows.push_back(renderWindow);
if (m_DataStorage.IsNotNull())
BaseRenderer::GetInstance(renderWindow)->SetDataStorage(m_DataStorage.GetPointer());
// Register vtkRenderWindow instance
renderWindow->Register(nullptr);
// Add callbacks for rendering abort mechanism
// BaseRenderer *renderer = BaseRenderer::GetInstance( renderWindow );
vtkCallbackCommand *startCallbackCommand = vtkCallbackCommand::New();
startCallbackCommand->SetCallback(RenderingManager::RenderingStartCallback);
renderWindow->AddObserver(vtkCommand::StartEvent, startCallbackCommand);
vtkCallbackCommand *progressCallbackCommand = vtkCallbackCommand::New();
progressCallbackCommand->SetCallback(RenderingManager::RenderingProgressCallback);
renderWindow->AddObserver(vtkCommand::AbortCheckEvent, progressCallbackCommand);
vtkCallbackCommand *endCallbackCommand = vtkCallbackCommand::New();
endCallbackCommand->SetCallback(RenderingManager::RenderingEndCallback);
renderWindow->AddObserver(vtkCommand::EndEvent, endCallbackCommand);
RenderWindowCallbacks callbacks;
callbacks.commands[0u] = startCallbackCommand;
callbacks.commands[1u] = progressCallbackCommand;
callbacks.commands[2u] = endCallbackCommand;
this->m_RenderWindowCallbacksList[renderWindow] = callbacks;
// Delete vtk variables correctly
startCallbackCommand->Delete();
progressCallbackCommand->Delete();
endCallbackCommand->Delete();
}
}
void RenderingManager::RemoveRenderWindow(vtkRenderWindow *renderWindow)
{
if (m_RenderWindowList.erase(renderWindow))
{
auto callbacks_it = this->m_RenderWindowCallbacksList.find(renderWindow);
if (callbacks_it != this->m_RenderWindowCallbacksList.end())
{
renderWindow->RemoveObserver(callbacks_it->second.commands[0u]);
renderWindow->RemoveObserver(callbacks_it->second.commands[1u]);
renderWindow->RemoveObserver(callbacks_it->second.commands[2u]);
this->m_RenderWindowCallbacksList.erase(callbacks_it);
}
auto rw_it =
std::find(m_AllRenderWindows.begin(), m_AllRenderWindows.end(), renderWindow);
if (rw_it != m_AllRenderWindows.cend())
{
// Decrease reference count for proper destruction
(*rw_it)->UnRegister(nullptr);
m_AllRenderWindows.erase(rw_it);
}
}
}
const RenderingManager::RenderWindowVector &RenderingManager::GetAllRegisteredRenderWindows()
{
return m_AllRenderWindows;
}
void RenderingManager::RequestUpdate(vtkRenderWindow *renderWindow)
{
// If the renderWindow is not valid, we do not want to inadvertently create
// an entry in the m_RenderWindowList map. It is possible if the user is
// regularly calling AddRenderer and RemoveRenderer for a rendering update
// to come into this method with a renderWindow pointer that is valid in the
// sense that the window does exist within the application, but that
// renderWindow has been temporarily removed from this RenderingManager for
// performance reasons.
if (m_RenderWindowList.find(renderWindow) == m_RenderWindowList.cend())
{
return;
}
m_RenderWindowList[renderWindow] = RENDERING_REQUESTED;
if (!m_UpdatePending)
{
m_UpdatePending = true;
this->GenerateRenderingRequestEvent();
}
}
void RenderingManager::ForceImmediateUpdate(vtkRenderWindow *renderWindow)
{
// If the renderWindow is not valid, we do not want to inadvertently create
// an entry in the m_RenderWindowList map. It is possible if the user is
// regularly calling AddRenderer and RemoveRenderer for a rendering update
// to come into this method with a renderWindow pointer that is valid in the
// sense that the window does exist within the application, but that
// renderWindow has been temporarily removed from this RenderingManager for
// performance reasons.
if (m_RenderWindowList.find(renderWindow) == m_RenderWindowList.cend())
{
return;
}
// Erase potentially pending requests for this window
m_RenderWindowList[renderWindow] = RENDERING_INACTIVE;
m_UpdatePending = false;
// Immediately repaint this window (implementation platform specific)
// If the size is 0 it crashes
int *size = renderWindow->GetSize();
if (0 != size[0] && 0 != size[1])
{
// prepare the camera etc. before rendering
// Note: this is a very important step which should be called before the VTK render!
// If you modify the camera anywhere else or after the render call, the scene cannot be seen.
auto *vPR = dynamic_cast<VtkPropRenderer *>(BaseRenderer::GetInstance(renderWindow));
if (vPR)
vPR->PrepareRender();
// Execute rendering
renderWindow->Render();
}
}
void RenderingManager::RequestUpdateAll(RequestType type)
{
RenderWindowList::const_iterator it;
for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it)
{
int id = BaseRenderer::GetInstance(it->first)->GetMapperID();
if ((type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) ||
((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)))
{
this->RequestUpdate(it->first);
}
}
}
void RenderingManager::ForceImmediateUpdateAll(RequestType type)
{
RenderWindowList::const_iterator it;
for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it)
{
int id = BaseRenderer::GetInstance(it->first)->GetMapperID();
if ((type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) ||
((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)))
{
// Immediately repaint this window (implementation platform specific)
// If the size is 0, it crashes
this->ForceImmediateUpdate(it->first);
}
}
}
void RenderingManager::InitializeViewsByBoundingObjects(const DataStorage* dataStorage)
{
if (nullptr == dataStorage)
{
return;
}
// get all nodes that have not set "includeInBoundingBox" to false
auto pred = NodePredicateNot::New(NodePredicateProperty::New("includeInBoundingBox", BoolProperty::New(false)));
DataStorage::SetOfObjects::ConstPointer filteredNodes = dataStorage->GetSubset(pred);
TimeGeometry::ConstPointer boundingGeometry;
if (!filteredNodes->empty())
{
// calculate bounding geometry of these nodes
boundingGeometry = dataStorage->ComputeBoundingGeometry3D(filteredNodes, "visible");
}
// initialize the views to the bounding geometry
this->InitializeViews(boundingGeometry);
}
void RenderingManager::InitializeViewByBoundingObjects(vtkRenderWindow* renderWindow, const DataStorage* dataStorage, bool resetCamera)
{
if (nullptr == dataStorage)
{
return;
}
// get all nodes that have not set "includeInBoundingBox" to false
auto pred = NodePredicateNot::New(NodePredicateProperty::New("includeInBoundingBox", BoolProperty::New(false)));
DataStorage::SetOfObjects::ConstPointer filteredNodes = dataStorage->GetSubset(pred);
BaseRenderer* baseRenderer = BaseRenderer::GetInstance(renderWindow);
TimeGeometry::ConstPointer boundingGeometry;
if (!filteredNodes->empty())
{
// calculate bounding geometry of these nodes
boundingGeometry = dataStorage->ComputeBoundingGeometry3D(filteredNodes, "visible", baseRenderer);
}
// initialize the views to the bounding geometry
this->InitializeView(renderWindow, boundingGeometry, resetCamera);
}
bool RenderingManager::InitializeViews(const BaseGeometry* geometry, RequestType type, bool resetCamera)
{
ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New();
propTimeGeometry->Initialize(dynamic_cast<BaseGeometry *>(geometry->Clone().GetPointer()), 1);
return this->InitializeViews(propTimeGeometry, type, resetCamera);
}
bool RenderingManager::InitializeViews(const TimeGeometry* geometry, RequestType type, bool resetCamera)
{
bool boundingBoxInitialized = false;
TimeGeometry::Pointer modifiedGeometry = nullptr;
try
{
boundingBoxInitialized = this->ExtendGeometryForBoundingBox(geometry, modifiedGeometry);
}
catch (Exception& exception)
{
mitkReThrow(exception);
}
+ if (boundingBoxInitialized)
+ {
+ this->GetTimeNavigationController()->SetInputWorldTimeGeometry(modifiedGeometry);
+ }
+ this->GetTimeNavigationController()->Update();
+
RenderWindowVector allRenderWindows = this->GetAllRegisteredRenderWindows();
RenderWindowVector::const_iterator it;
for (it = allRenderWindows.cbegin(); it != allRenderWindows.cend(); ++it)
{
BaseRenderer *baseRenderer = BaseRenderer::GetInstance(*it);
baseRenderer->SetConstrainZoomingAndPanning(this->GetConstrainedPanningZooming());
int id = baseRenderer->GetMapperID();
if ((type == REQUEST_UPDATE_ALL) ||
((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) ||
((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)))
{
this->InternalViewInitialization(baseRenderer, modifiedGeometry, boundingBoxInitialized, id, resetCamera);
}
}
- if (boundingBoxInitialized)
- {
- this->GetTimeNavigationController()->SetInputWorldTimeGeometry(modifiedGeometry);
- }
- this->GetTimeNavigationController()->Update();
-
this->RequestUpdateAll(type);
// inform listeners that views have been initialized
this->InvokeEvent(RenderingManagerViewsInitializedEvent());
return boundingBoxInitialized;
}
bool RenderingManager::InitializeViews(RequestType type)
{
const RenderWindowVector allRenderWindows = this->GetAllRegisteredRenderWindows();
RenderWindowVector::const_iterator it;
for (it = allRenderWindows.cbegin(); it != allRenderWindows.cend(); ++it)
{
BaseRenderer *baseRenderer = BaseRenderer::GetInstance(*it);
int id = baseRenderer->GetMapperID();
if ((type == REQUEST_UPDATE_ALL) ||
((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) ||
((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)))
{
this->InternalViewInitialization(baseRenderer, nullptr, false, id, false);
}
}
this->RequestUpdateAll(type);
// inform listeners that views have been initialized
this->InvokeEvent(RenderingManagerViewsInitializedEvent());
return true;
}
bool RenderingManager::InitializeView(vtkRenderWindow* renderWindow, const BaseGeometry* geometry, bool resetCamera)
{
ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New();
propTimeGeometry->Initialize(dynamic_cast<BaseGeometry*>(geometry->Clone().GetPointer()), 1);
return this->InitializeView(renderWindow, propTimeGeometry, resetCamera);
}
bool RenderingManager::InitializeView(vtkRenderWindow* renderWindow, const TimeGeometry* geometry, bool resetCamera)
{
bool boundingBoxInitialized = false;
TimeGeometry::Pointer modifiedGeometry = nullptr;
try
{
boundingBoxInitialized = this->ExtendGeometryForBoundingBox(geometry, modifiedGeometry);
}
catch (Exception &exception)
{
mitkReThrow(exception);
}
- BaseRenderer* baseRenderer = BaseRenderer::GetInstance(renderWindow);
- baseRenderer->SetConstrainZoomingAndPanning(this->GetConstrainedPanningZooming());
-
- int id = baseRenderer->GetMapperID();
- this->InternalViewInitialization(baseRenderer, modifiedGeometry, boundingBoxInitialized, id, resetCamera);
-
if (boundingBoxInitialized)
{
this->GetTimeNavigationController()->SetInputWorldTimeGeometry(modifiedGeometry);
}
-
this->GetTimeNavigationController()->Update();
+ BaseRenderer* baseRenderer = BaseRenderer::GetInstance(renderWindow);
+ baseRenderer->SetConstrainZoomingAndPanning(this->GetConstrainedPanningZooming());
+
+ const int id = baseRenderer->GetMapperID();
+ this->InternalViewInitialization(baseRenderer, modifiedGeometry, boundingBoxInitialized, id, resetCamera);
+
this->RequestUpdate(renderWindow);
// inform listeners that views have been initialized
this->InvokeEvent(RenderingManagerViewsInitializedEvent());
return boundingBoxInitialized;
}
bool RenderingManager::InitializeView(vtkRenderWindow *renderWindow)
{
BaseRenderer *baseRenderer = BaseRenderer::GetInstance(renderWindow);
int id = baseRenderer->GetMapperID();
this->InternalViewInitialization(baseRenderer, nullptr, false, id, false);
this->RequestUpdate(renderWindow);
// inform listeners that views have been initialized
this->InvokeEvent(RenderingManagerViewsInitializedEvent());
return true;
}
void RenderingManager::InternalViewInitialization(BaseRenderer *baseRenderer, const TimeGeometry *geometry,
bool boundingBoxInitialized, int mapperID, bool resetCamera)
{
SliceNavigationController *nc = baseRenderer->GetSliceNavigationController();
nc->SetViewDirectionToDefault();
if (boundingBoxInitialized)
{
// Set geometry for NC
nc->SetInputWorldTimeGeometry(geometry);
nc->Update();
if (resetCamera)
{
if (mapperID == BaseRenderer::Standard2D)
{
// For 2D SNCs, steppers are set so that the cross is centered in the image
- nc->GetSlice()->SetPos(nc->GetSlice()->GetSteps() / 2);
+ nc->GetStepper()->SetPos(nc->GetStepper()->GetSteps() / 2);
baseRenderer->GetCameraController()->Fit();
}
else if (mapperID == BaseRenderer::Standard3D)
{
baseRenderer->GetCameraController()->SetViewToAnterior();
}
}
}
else
{
nc->Update();
}
}
bool RenderingManager::ExtendGeometryForBoundingBox(const TimeGeometry *geometry,
TimeGeometry::Pointer& modifiedGeometry)
{
bool boundingBoxInitialized = false;
if (nullptr == geometry)
{
return boundingBoxInitialized;
}
modifiedGeometry = geometry->Clone();
if (modifiedGeometry.IsNull())
{
return boundingBoxInitialized;
}
if (modifiedGeometry->GetBoundingBoxInWorld()->GetDiagonalLength2() > eps)
{
boundingBoxInitialized = true;
}
// make sure bounding box has an extent bigger than zero in any direction
for (TimeStepType step = 0; step < modifiedGeometry->CountTimeSteps(); ++step)
{
BaseGeometry::BoundsArrayType newBounds = modifiedGeometry->GetGeometryForTimeStep(step)->GetBounds();
for (unsigned int dimension = 0; (2 * dimension) < newBounds.Size(); dimension++)
{
// check for equality but for an epsilon
if (Equal(newBounds[2 * dimension], newBounds[2 * dimension + 1]))
{
newBounds[2 * dimension + 1] += 1;
if (Equal(
newBounds[2 * dimension],
newBounds[2 * dimension + 1])) // newBounds will still be equal if values are beyond double precision
{
mitkThrow() << "One dimension of object data has zero length, please make sure you're not using numbers "
"beyond double precision as coordinates.";
}
}
}
modifiedGeometry->GetGeometryForTimeStep(step)->SetBounds(newBounds);
}
return boundingBoxInitialized;
}
- const SliceNavigationController *RenderingManager::GetTimeNavigationController() const
+ const TimeNavigationController *RenderingManager::GetTimeNavigationController() const
{
return m_TimeNavigationController.GetPointer();
}
- SliceNavigationController *RenderingManager::GetTimeNavigationController()
+ TimeNavigationController *RenderingManager::GetTimeNavigationController()
{
return m_TimeNavigationController.GetPointer();
}
void RenderingManager::ExecutePendingRequests()
{
m_UpdatePending = false;
// Satisfy all pending update requests
RenderWindowList::const_iterator it;
int i = 0;
for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it, ++i)
{
if (it->second == RENDERING_REQUESTED)
{
this->ForceImmediateUpdate(it->first);
}
}
}
void RenderingManager::RenderingStartCallback(vtkObject *caller, unsigned long, void *, void *)
{
auto renderingManager = RenderingManager::GetInstance();
auto renderWindow = dynamic_cast<vtkRenderWindow*>(caller);
if (nullptr != renderWindow)
renderingManager->m_RenderWindowList[renderWindow] = RENDERING_INPROGRESS;
renderingManager->m_UpdatePending = false;
}
void RenderingManager::RenderingProgressCallback(vtkObject *caller, unsigned long, void *, void *)
{
auto renderingManager = RenderingManager::GetInstance();
if (renderingManager->m_LODAbortMechanismEnabled)
{
auto renderWindow = dynamic_cast<vtkRenderWindow *>(caller);
if (nullptr != renderWindow)
{
auto renderer = BaseRenderer::GetInstance(renderWindow);
if (nullptr != renderer && 0 < renderer->GetNumberOfVisibleLODEnabledMappers())
renderingManager->DoMonitorRendering();
}
}
}
void RenderingManager::RenderingEndCallback(vtkObject *caller, unsigned long, void *, void *)
{
auto renderWindow = dynamic_cast<vtkRenderWindow*>(caller);
if (nullptr == renderWindow)
{
return;
}
auto renderer = BaseRenderer::GetInstance(renderWindow);
if (nullptr == renderer)
{
return;
}
auto renderingManager = RenderingManager::GetInstance();
renderingManager->m_RenderWindowList[renderer->GetRenderWindow()] = RENDERING_INACTIVE;
if (0 < renderer->GetNumberOfVisibleLODEnabledMappers())
{
if (0 == renderingManager->m_NextLODMap[renderer])
{
renderingManager->StartOrResetTimer();
}
else
{
renderingManager->m_NextLODMap[renderer] = 0;
}
}
}
bool RenderingManager::IsRendering() const
{
RenderWindowList::const_iterator it;
for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it)
{
if (it->second == RENDERING_INPROGRESS)
{
return true;
}
}
return false;
}
void RenderingManager::AbortRendering()
{
RenderWindowList::const_iterator it;
for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it)
{
if (it->second == RENDERING_INPROGRESS)
{
it->first->SetAbortRender(true);
m_RenderingAbortedMap[BaseRenderer::GetInstance(it->first)] = true;
}
}
}
int RenderingManager::GetNextLOD(BaseRenderer *renderer)
{
if (renderer != nullptr)
{
return m_NextLODMap[renderer];
}
else
{
return 0;
}
}
void RenderingManager::ExecutePendingHighResRenderingRequest()
{
RenderWindowList::const_iterator it;
for (it = m_RenderWindowList.cbegin(); it != m_RenderWindowList.cend(); ++it)
{
BaseRenderer *renderer = BaseRenderer::GetInstance(it->first);
if (renderer->GetNumberOfVisibleLODEnabledMappers() > 0)
{
if (m_NextLODMap[renderer] == 0)
{
m_NextLODMap[renderer] = 1;
RequestUpdate(it->first);
}
}
}
}
void RenderingManager::SetMaximumLOD(unsigned int max) { m_MaxLOD = max; }
// enable/disable shading
void RenderingManager::SetShading(bool state, unsigned int lod)
{
if (lod > m_MaxLOD)
{
itkWarningMacro(<< "LOD out of range requested: " << lod << " maxLOD: " << m_MaxLOD);
return;
}
m_ShadingEnabled[lod] = state;
}
bool RenderingManager::GetShading(unsigned int lod)
{
if (lod > m_MaxLOD)
{
itkWarningMacro(<< "LOD out of range requested: " << lod << " maxLOD: " << m_MaxLOD);
return false;
}
return m_ShadingEnabled[lod];
}
// enable/disable the clipping plane
void RenderingManager::SetClippingPlaneStatus(bool status) { m_ClippingPlaneEnabled = status; }
bool RenderingManager::GetClippingPlaneStatus() { return m_ClippingPlaneEnabled; }
void RenderingManager::SetShadingValues(float ambient, float diffuse, float specular, float specpower)
{
m_ShadingValues[0] = ambient;
m_ShadingValues[1] = diffuse;
m_ShadingValues[2] = specular;
m_ShadingValues[3] = specpower;
}
RenderingManager::FloatVector &RenderingManager::GetShadingValues() { return m_ShadingValues; }
void RenderingManager::InitializePropertyList()
{
if (m_PropertyList.IsNull())
{
m_PropertyList = PropertyList::New();
}
this->SetProperty("coupled-zoom", BoolProperty::New(false));
this->SetProperty("coupled-plane-rotation", BoolProperty::New(false));
this->SetProperty("MIP-slice-rendering", BoolProperty::New(false));
}
PropertyList::Pointer RenderingManager::GetPropertyList() const { return m_PropertyList; }
BaseProperty *RenderingManager::GetProperty(const char *propertyKey) const
{
return m_PropertyList->GetProperty(propertyKey);
}
void RenderingManager::SetProperty(const char *propertyKey, BaseProperty *propertyValue)
{
m_PropertyList->SetProperty(propertyKey, propertyValue);
}
void RenderingManager::SetDataStorage(DataStorage *storage)
{
if (storage != nullptr)
{
m_DataStorage = storage;
RenderingManager::RenderWindowVector::const_iterator iter;
for (iter = m_AllRenderWindows.cbegin(); iter < m_AllRenderWindows.cend(); ++iter)
{
BaseRenderer::GetInstance((*iter))->SetDataStorage(m_DataStorage.GetPointer());
}
}
}
void RenderingManager::SetRenderWindowFocus(vtkRenderWindow *focusWindow)
{
if (focusWindow != m_FocusedRenderWindow)
{
if (!focusWindow || (m_RenderWindowList.find(focusWindow) != m_RenderWindowList.cend()))
{
m_FocusedRenderWindow = focusWindow;
this->InvokeEvent(FocusChangedEvent());
return;
}
MITK_ERROR << "Tried to set a RenderWindow that does not exist.";
}
}
void RenderingManager::SetAntiAliasing(AntiAliasing antiAliasing)
{
if (m_AntiAliasing != antiAliasing)
{
auto renderingManager = RenderingManager::GetInstance();
auto renderWindows = renderingManager->GetAllRegisteredRenderWindows();
for (auto renderWindow : renderWindows)
{
auto renderers = renderWindow->GetRenderers();
if (nullptr != renderers)
{
renderers->InitTraversal();
auto renderer = renderers->GetNextItem();
while (nullptr != renderer)
{
renderer->SetUseFXAA(AntiAliasing::FastApproximate == antiAliasing);
renderer = renderers->GetNextItem();
}
renderingManager->RequestUpdate(renderWindow);
}
}
m_AntiAliasing = antiAliasing;
}
}
// Create and register generic RenderingManagerFactory.
TestingRenderingManagerFactory renderingManagerFactory;
} // namespace
diff --git a/Modules/Core/src/Controllers/mitkSliceNavigationController.cpp b/Modules/Core/src/Controllers/mitkSliceNavigationController.cpp
index 9eacf0b0f3..689c473f14 100644
--- a/Modules/Core/src/Controllers/mitkSliceNavigationController.cpp
+++ b/Modules/Core/src/Controllers/mitkSliceNavigationController.cpp
@@ -1,542 +1,471 @@
/*============================================================================
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 "mitkSliceNavigationController.h"
+#include <mitkSliceNavigationController.h>
#include <mitkSliceNavigationHelper.h>
-#include "mitkBaseRenderer.h"
-#include "mitkOperation.h"
-#include "mitkOperationActor.h"
-
-#include "mitkProportionalTimeGeometry.h"
-#include "mitkArbitraryTimeGeometry.h"
-#include "mitkSlicedGeometry3D.h"
-#include "mitkVtkPropRenderer.h"
-
-#include "mitkImage.h"
-#include "mitkImagePixelReadAccessor.h"
-#include "mitkInteractionConst.h"
-#include "mitkNodePredicateDataType.h"
-#include "mitkOperationEvent.h"
-#include "mitkPixelTypeMultiplex.h"
-#include "mitkPlaneGeometry.h"
-#include "mitkPlaneOperation.h"
-#include "mitkPointOperation.h"
-
-#include "mitkApplyTransformMatrixOperation.h"
+#include <mitkBaseRenderer.h>
+#include <mitkOperation.h>
+#include <mitkOperationActor.h>
+#include <mitkProportionalTimeGeometry.h>
+#include <mitkArbitraryTimeGeometry.h>
+#include <mitkSlicedGeometry3D.h>
+#include <mitkTimeNavigationController.h>
+#include <mitkVtkPropRenderer.h>
+
+#include <mitkImage.h>
+#include <mitkImagePixelReadAccessor.h>
+#include <mitkInteractionConst.h>
+#include <mitkNodePredicateDataType.h>
+#include <mitkOperationEvent.h>
+#include <mitkPixelTypeMultiplex.h>
+#include <mitkPlaneGeometry.h>
+#include <mitkPlaneOperation.h>
+#include <mitkPointOperation.h>
+
+#include <mitkApplyTransformMatrixOperation.h>
namespace mitk
{
SliceNavigationController::SliceNavigationController()
: BaseController()
, m_InputWorldTimeGeometry(TimeGeometry::ConstPointer())
, m_CreatedWorldGeometry(TimeGeometry::Pointer())
, m_ViewDirection(AnatomicalPlane::Axial)
, m_DefaultViewDirection(AnatomicalPlane::Axial)
, m_RenderingManager(RenderingManager::Pointer())
, m_Renderer(nullptr)
, m_BlockUpdate(false)
, m_SliceLocked(false)
, m_SliceRotationLocked(false)
{
typedef itk::SimpleMemberCommand<SliceNavigationController> SNCCommandType;
- SNCCommandType::Pointer sliceStepperChangedCommand, timeStepperChangedCommand;
+ SNCCommandType::Pointer sliceStepperChangedCommand;
sliceStepperChangedCommand = SNCCommandType::New();
- timeStepperChangedCommand = SNCCommandType::New();
-
sliceStepperChangedCommand->SetCallbackFunction(this, &SliceNavigationController::SendSlice);
- timeStepperChangedCommand->SetCallbackFunction(this, &SliceNavigationController::SendTime);
-
- m_Slice->AddObserver(itk::ModifiedEvent(), sliceStepperChangedCommand);
- m_Time->AddObserver(itk::ModifiedEvent(), timeStepperChangedCommand);
-
- m_Slice->SetUnitName("mm");
- m_Time->SetUnitName("ms");
+ m_Stepper->AddObserver(itk::ModifiedEvent(), sliceStepperChangedCommand);
+ m_Stepper->SetUnitName("mm");
}
SliceNavigationController::~SliceNavigationController()
{
// nothing here
}
void SliceNavigationController::SetInputWorldTimeGeometry(const TimeGeometry* geometry)
{
if (nullptr != geometry)
{
if (geometry->GetBoundingBoxInWorld()->GetDiagonalLength2() < eps)
{
itkWarningMacro("setting an empty bounding-box");
geometry = nullptr;
}
}
if (m_InputWorldTimeGeometry != geometry)
{
m_InputWorldTimeGeometry = geometry;
this->Modified();
}
}
void SliceNavigationController::SetViewDirectionToDefault()
{
m_ViewDirection = m_DefaultViewDirection;
}
const char* SliceNavigationController::GetViewDirectionAsString() const
{
const char* viewDirectionString;
switch (m_ViewDirection)
{
case AnatomicalPlane::Axial:
viewDirectionString = "Axial";
break;
case AnatomicalPlane::Sagittal:
viewDirectionString = "Sagittal";
break;
case AnatomicalPlane::Coronal:
viewDirectionString = "Coronal";
break;
case AnatomicalPlane::Original:
viewDirectionString = "Original";
break;
default:
viewDirectionString = "No view direction available";
break;
}
return viewDirectionString;
}
void SliceNavigationController::Update()
{
if (!m_BlockUpdate)
{
if (m_ViewDirection == AnatomicalPlane::Sagittal)
{
this->Update(AnatomicalPlane::Sagittal, true, true, false);
}
else if (m_ViewDirection == AnatomicalPlane::Coronal)
{
this->Update(AnatomicalPlane::Coronal, false, true, false);
}
else if (m_ViewDirection == AnatomicalPlane::Axial)
{
this->Update(AnatomicalPlane::Axial, false, false, true);
}
else
{
this->Update(m_ViewDirection);
}
}
}
void SliceNavigationController::Update(AnatomicalPlane viewDirection,
bool top,
bool frontside,
bool rotated)
{
if (m_BlockUpdate)
{
return;
}
if (m_InputWorldTimeGeometry.IsNull())
{
return;
}
if (0 == m_InputWorldTimeGeometry->CountTimeSteps())
{
return;
}
m_BlockUpdate = true;
if (m_LastUpdateTime < m_InputWorldTimeGeometry->GetMTime())
{
Modified();
}
this->SetViewDirection(viewDirection);
if (m_LastUpdateTime < GetMTime())
{
m_LastUpdateTime = GetMTime();
this->CreateWorldGeometry(top, frontside, rotated);
}
// unblock update; we may do this now, because if m_BlockUpdate was already
// true before this method was entered, then we will never come here.
m_BlockUpdate = false;
// Send the geometry. Do this even if nothing was changed, because maybe
- // Update() was only called to re-send the old geometry and time/slice data.
+ // Update() was only called to re-send the old geometry and slice data.
this->SendCreatedWorldGeometry();
this->SendSlice();
- this->SendTime();
// Adjust the stepper range of slice stepper according to geometry
this->AdjustSliceStepperRange();
}
void SliceNavigationController::SendCreatedWorldGeometry()
{
if (!m_BlockUpdate)
{
this->InvokeEvent(GeometrySendEvent(m_CreatedWorldGeometry, 0));
}
}
void SliceNavigationController::SendCreatedWorldGeometryUpdate()
{
if (!m_BlockUpdate)
{
- this->InvokeEvent(GeometryUpdateEvent(m_CreatedWorldGeometry, m_Slice->GetPos()));
+ this->InvokeEvent(GeometryUpdateEvent(m_CreatedWorldGeometry, m_Stepper->GetPos()));
}
}
void SliceNavigationController::SendSlice()
{
if (!m_BlockUpdate)
{
if (m_CreatedWorldGeometry.IsNotNull())
{
- this->InvokeEvent(GeometrySliceEvent(m_CreatedWorldGeometry, m_Slice->GetPos()));
- RenderingManager::GetInstance()->RequestUpdateAll();
- }
- }
- }
-
- void SliceNavigationController::SendTime()
- {
- if (!m_BlockUpdate)
- {
- if (m_CreatedWorldGeometry.IsNotNull())
- {
- this->InvokeEvent(GeometryTimeEvent(m_CreatedWorldGeometry, m_Time->GetPos()));
+ this->InvokeEvent(GeometrySliceEvent(m_CreatedWorldGeometry, m_Stepper->GetPos()));
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
}
- void SliceNavigationController::SetGeometry(const itk::EventObject&)
- {
- // not implemented
- }
-
- void SliceNavigationController::SetGeometryTime(const itk::EventObject& geometryTimeEvent)
- {
- if (m_CreatedWorldGeometry.IsNull())
- {
- return;
- }
-
- const auto* timeEvent = dynamic_cast<const SliceNavigationController::GeometryTimeEvent*>(&geometryTimeEvent);
- assert(timeEvent != nullptr);
-
- TimeGeometry* timeGeometry = timeEvent->GetTimeGeometry();
- assert(timeGeometry != nullptr);
-
- auto timeStep = (int)timeEvent->GetPos();
- ScalarType timeInMS;
- timeInMS = timeGeometry->TimeStepToTimePoint(timeStep);
- timeStep = m_CreatedWorldGeometry->TimePointToTimeStep(timeInMS);
- this->GetTime()->SetPos(timeStep);
- }
-
- void SliceNavigationController::SetGeometrySlice(const itk::EventObject& geometrySliceEvent)
- {
- const auto* sliceEvent = dynamic_cast<const SliceNavigationController::GeometrySliceEvent*>(&geometrySliceEvent);
- assert(sliceEvent != nullptr);
-
- this->GetSlice()->SetPos(sliceEvent->GetPos());
- }
-
void SliceNavigationController::SelectSliceByPoint(const Point3D& point)
{
if (m_CreatedWorldGeometry.IsNull())
{
return;
}
int selectedSlice = -1;
try
{
selectedSlice = SliceNavigationHelper::SelectSliceByPoint(m_CreatedWorldGeometry, point);
}
catch (const mitk::Exception& e)
{
MITK_ERROR << "Unable to select a slice by the given point " << point << "\n"
<< "Reason: " << e.GetDescription();
}
if (-1 == selectedSlice)
{
return;
}
- this->GetSlice()->SetPos(selectedSlice);
+ m_Stepper->SetPos(selectedSlice);
this->SendCreatedWorldGeometryUpdate();
// send crosshair event
SetCrosshairEvent.Send(point);
}
void SliceNavigationController::ReorientSlices(const Point3D& point, const Vector3D& normal)
{
if (m_CreatedWorldGeometry.IsNull())
{
return;
}
PlaneOperation op(OpORIENT, point, normal);
m_CreatedWorldGeometry->ExecuteOperation(&op);
this->SendCreatedWorldGeometryUpdate();
}
void SliceNavigationController::ReorientSlices(const Point3D& point,
const Vector3D& axisVec0,
const Vector3D& axisVec1)
{
if (m_CreatedWorldGeometry.IsNull())
{
return;
}
PlaneOperation op(OpORIENT, point, axisVec0, axisVec1);
m_CreatedWorldGeometry->ExecuteOperation(&op);
this->SendCreatedWorldGeometryUpdate();
}
const BaseGeometry* SliceNavigationController::GetCurrentGeometry3D()
{
if (m_CreatedWorldGeometry.IsNull())
{
return nullptr;
+
}
- return m_CreatedWorldGeometry->GetGeometryForTimeStep(this->GetTime()->GetPos());
+ const auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ if (nullptr == timeNavigationController)
+ {
+ return nullptr;
+ }
+
+ const TimeStepType selectedTimestep = timeNavigationController->GetSelectedTimeStep();
+ return m_CreatedWorldGeometry->GetGeometryForTimeStep(selectedTimestep);
}
const PlaneGeometry* SliceNavigationController::GetCurrentPlaneGeometry()
{
const auto* slicedGeometry = dynamic_cast<const SlicedGeometry3D*>(this->GetCurrentGeometry3D());
if (nullptr == slicedGeometry)
{
return nullptr;
}
- return slicedGeometry->GetPlaneGeometry(this->GetSlice()->GetPos());
+ return slicedGeometry->GetPlaneGeometry(m_Stepper->GetPos());
}
void SliceNavigationController::AdjustSliceStepperRange()
{
const auto* slicedGeometry = dynamic_cast<const SlicedGeometry3D*>(this->GetCurrentGeometry3D());
const Vector3D& direction = slicedGeometry->GetDirectionVector();
int c = 0;
int i, k = 0;
for (i = 0; i < 3; ++i)
{
if (fabs(direction[i]) < 0.000000001)
{
++c;
}
else
{
k = i;
}
}
if (c == 2)
{
ScalarType min = slicedGeometry->GetOrigin()[k];
ScalarType max = min + slicedGeometry->GetExtentInMM(k);
- m_Slice->SetRange(min, max);
+ m_Stepper->SetRange(min, max);
}
else
{
- m_Slice->InvalidateRange();
+ m_Stepper->InvalidateRange();
}
}
void SliceNavigationController::ExecuteOperation(Operation* operation)
{
// switch on type
// - select best slice for a given point
// - rotate created world geometry according to Operation->SomeInfo()
if (!operation || m_CreatedWorldGeometry.IsNull())
{
return;
}
switch (operation->GetOperationType())
{
case OpMOVE: // should be a point operation
{
if (!m_SliceLocked) // do not move the cross position
{
// select a slice
auto* po = dynamic_cast<PointOperation*>(operation);
if (po && po->GetIndex() == -1)
{
this->SelectSliceByPoint(po->GetPoint());
}
else if (po &&
po->GetIndex() != -1) // undo case because index != -1, index holds the old position of this slice
{
- this->GetSlice()->SetPos(po->GetIndex());
+ m_Stepper->SetPos(po->GetIndex());
}
}
break;
}
case OpRESTOREPLANEPOSITION:
{
m_CreatedWorldGeometry->ExecuteOperation(operation);
this->SendCreatedWorldGeometryUpdate();
break;
}
case OpAPPLYTRANSFORMMATRIX:
{
m_CreatedWorldGeometry->ExecuteOperation(operation);
this->SendCreatedWorldGeometryUpdate();
break;
}
default:
{
// do nothing
break;
}
}
}
- TimeStepType SliceNavigationController::GetSelectedTimeStep() const
- {
- return this->GetTime()->GetPos();
- }
-
- TimePointType SliceNavigationController::GetSelectedTimePoint() const
+ void SliceNavigationController::CreateWorldGeometry(bool top, bool frontside, bool rotated)
{
- auto timeStep = this->GetSelectedTimeStep();
-
- if (m_CreatedWorldGeometry.IsNull())
- {
- return 0.0;
- }
-
- if (!m_CreatedWorldGeometry->IsValidTimeStep(timeStep))
+ const auto timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ if (nullptr == timeNavigationController)
{
- mitkThrow() << "SliceNavigationController is in an invalid state. It has a time step"
- << "selected that is not covered by its time geometry. Selected time step: " << timeStep
- << "; TimeGeometry steps count: " << m_CreatedWorldGeometry->CountTimeSteps();
+ return;
}
- return m_CreatedWorldGeometry->TimeStepToTimePoint(timeStep);
- }
-
- void SliceNavigationController::CreateWorldGeometry(bool top, bool frontside, bool rotated)
- {
// initialize the viewplane
SlicedGeometry3D::Pointer slicedWorldGeometry;
BaseGeometry::ConstPointer currentGeometry;
// get the BaseGeometry (ArbitraryTimeGeometry or ProportionalTimeGeometry) of the current time step
- auto currentTimeStep = this->GetTime()->GetPos();
- if (m_InputWorldTimeGeometry->IsValidTimeStep(currentTimeStep))
+ const TimeStepType selectedTimestep = timeNavigationController->GetSelectedTimeStep();
+ if (m_InputWorldTimeGeometry->IsValidTimeStep(selectedTimestep))
{
- currentGeometry = m_InputWorldTimeGeometry->GetGeometryForTimeStep(currentTimeStep);
+ currentGeometry = m_InputWorldTimeGeometry->GetGeometryForTimeStep(selectedTimestep);
}
else
{
currentGeometry = m_InputWorldTimeGeometry->GetGeometryForTimeStep(0);
}
if (AnatomicalPlane::Original == m_ViewDirection)
{
slicedWorldGeometry = dynamic_cast<SlicedGeometry3D*>(
- m_InputWorldTimeGeometry->GetGeometryForTimeStep(currentTimeStep).GetPointer());
+ m_InputWorldTimeGeometry->GetGeometryForTimeStep(selectedTimestep).GetPointer());
if (slicedWorldGeometry.IsNull())
{
slicedWorldGeometry = SlicedGeometry3D::New();
slicedWorldGeometry->InitializePlanes(currentGeometry, AnatomicalPlane::Original, top, frontside, rotated);
slicedWorldGeometry->SetSliceNavigationController(this);
}
}
else
{
slicedWorldGeometry = SlicedGeometry3D::New();
slicedWorldGeometry->InitializePlanes(currentGeometry, m_ViewDirection, top, frontside, rotated);
slicedWorldGeometry->SetSliceNavigationController(this);
}
// reset the stepper
- m_Slice->SetSteps(slicedWorldGeometry->GetSlices());
- m_Slice->SetPos(0);
-
- TimeStepType inputTimeSteps = m_InputWorldTimeGeometry->CountTimeSteps();
- const TimeBounds& timeBounds = m_InputWorldTimeGeometry->GetTimeBounds();
- m_Time->SetSteps(inputTimeSteps);
- m_Time->SetPos(0);
- m_Time->SetRange(timeBounds[0], timeBounds[1]);
-
- currentTimeStep = this->GetTime()->GetPos();
- assert(m_InputWorldTimeGeometry->GetGeometryForTimeStep(currentTimeStep).IsNotNull());
+ m_Stepper->SetSteps(slicedWorldGeometry->GetSlices());
+ m_Stepper->SetPos(0);
+ const TimeStepType inputTimeSteps = m_InputWorldTimeGeometry->CountTimeSteps();
// create new time geometry and initialize it according to the type of the 'm_InputWorldTimeGeometry'
// the created world geometry will either have equidistant timesteps (ProportionalTimeGeometry)
// or individual time bounds for each timestep (ArbitraryTimeGeometry)
m_CreatedWorldGeometry = mitk::TimeGeometry::Pointer();
if (nullptr != dynamic_cast<const mitk::ProportionalTimeGeometry*>(m_InputWorldTimeGeometry.GetPointer()))
{
- const TimePointType minimumTimePoint = m_InputWorldTimeGeometry->TimeStepToTimePoint(currentTimeStep);
+ const TimePointType minimumTimePoint = m_InputWorldTimeGeometry->TimeStepToTimePoint(0);
const TimePointType stepDuration =
- m_InputWorldTimeGeometry->TimeStepToTimePoint(currentTimeStep + 1) - minimumTimePoint;
+ m_InputWorldTimeGeometry->TimeStepToTimePoint(1) - minimumTimePoint;
auto createdTimeGeometry = ProportionalTimeGeometry::New();
createdTimeGeometry->Initialize(slicedWorldGeometry, inputTimeSteps);
createdTimeGeometry->SetFirstTimePoint(minimumTimePoint);
createdTimeGeometry->SetStepDuration(stepDuration);
m_CreatedWorldGeometry = createdTimeGeometry;
}
else
{
auto createdTimeGeometry = mitk::ArbitraryTimeGeometry::New();
createdTimeGeometry->ReserveSpaceForGeometries(inputTimeSteps);
const BaseGeometry::Pointer clonedGeometry = slicedWorldGeometry->Clone();
for (TimeStepType i = 0; i < inputTimeSteps; ++i)
{
const auto bounds = m_InputWorldTimeGeometry->GetTimeBounds(i);
createdTimeGeometry->AppendNewTimeStep(clonedGeometry, bounds[0], bounds[1]);
}
createdTimeGeometry->Update();
m_CreatedWorldGeometry = createdTimeGeometry;
}
}
} // namespace mitk
diff --git a/Modules/Core/src/Controllers/mitkSliceNavigationHelper.cpp b/Modules/Core/src/Controllers/mitkSliceNavigationHelper.cpp
index 0dc248112a..54eef948c8 100644
--- a/Modules/Core/src/Controllers/mitkSliceNavigationHelper.cpp
+++ b/Modules/Core/src/Controllers/mitkSliceNavigationHelper.cpp
@@ -1,144 +1,144 @@
/*============================================================================
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 "mitkSliceNavigationHelper.h"
#include <mitkArbitraryTimeGeometry.h>
#include <mitkProportionalTimeGeometry.h>
#include <mitkPoint.h>
#include <mitkRenderingManager.h>
#include <mitkSlicedGeometry3D.h>
-#include <mitkSliceNavigationController.h>
+#include <mitkTimeNavigationController.h>
unsigned int mitk::SliceNavigationHelper::SelectSliceByPoint(const TimeGeometry* timeGeometry,
const Point3D& point)
{
int selectedSlice = -1;
if (nullptr == timeGeometry)
{
return selectedSlice;
}
// get the BaseGeometry of the selected time point
- auto selectedTimePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
- auto currentGeometry = timeGeometry->GetGeometryForTimePoint(selectedTimePoint);
+ const auto selectedTimePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+ const auto currentGeometry = timeGeometry->GetGeometryForTimePoint(selectedTimePoint);
if (nullptr == currentGeometry)
{
// time point not valid for the ime geometry
mitkThrow() << "Cannot extract a base geometry. A time point is selected that is not covered by"
<< "the given time geometry. Selected time point: " << selectedTimePoint;
}
const auto* slicedGeometry = dynamic_cast<mitk::SlicedGeometry3D*>(currentGeometry.GetPointer());
if (nullptr == slicedGeometry)
{
return selectedSlice;
}
double bestDistance = itk::NumericTraits<double>::max();
if (slicedGeometry->GetEvenlySpaced())
{
PlaneGeometry* plane = slicedGeometry->GetPlaneGeometry(0);
const Vector3D& direction = slicedGeometry->GetDirectionVector();
Point3D projectedPoint;
plane->Project(point, projectedPoint);
// check whether the point is somewhere within the slice stack volume
if (direction[0] * (point[0] - projectedPoint[0]) + direction[1] * (point[1] - projectedPoint[1]) +
direction[2] * (point[2] - projectedPoint[2]) >= 0)
{
selectedSlice = static_cast<int>(plane->Distance(point) / slicedGeometry->GetSpacing()[2] + 0.5);
}
}
else
{
- int numberOfSlices = slicedGeometry->GetSlices();
+ const int numberOfSlices = slicedGeometry->GetSlices();
Point3D projectedPoint;
for (int slice = 0; slice < numberOfSlices; ++slice)
{
slicedGeometry->GetPlaneGeometry(slice)->Project(point, projectedPoint);
const Vector3D distance = projectedPoint - point;
ScalarType currentDistance = distance.GetSquaredNorm();
if (currentDistance < bestDistance)
{
bestDistance = currentDistance;
selectedSlice = slice;
}
}
}
if (selectedSlice < 0)
{
selectedSlice = 0; // do not allow negative slices
}
return selectedSlice;
}
mitk::TimeGeometry::Pointer mitk::SliceNavigationHelper::CreateOrientedTimeGeometry(const TimeGeometry* timeGeometry,
AnatomicalPlane orientation,
bool top,
bool frontside,
bool rotated)
{
if (nullptr == timeGeometry)
{
return nullptr;
}
// initialize the viewplane
SlicedGeometry3D::Pointer slicedGeometry;
BaseGeometry::ConstPointer currentGeometry;
// get the BaseGeometry of the selected time point
- auto selectedTimePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+ const auto selectedTimePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
currentGeometry = timeGeometry->GetGeometryForTimePoint(selectedTimePoint);
if(nullptr == currentGeometry)
{
// time point not valid for the time geometry
mitkThrow() << "Cannot extract a base geometry. A time point is selected that is not covered by"
<< "the given time geometry. Selected time point: " << selectedTimePoint;
}
slicedGeometry = SlicedGeometry3D::New();
slicedGeometry->InitializePlanes(currentGeometry, orientation, top, frontside, rotated);
// use the existing time geometry but replace all time steps with the newly created
// sliced geometry (base geometry), initialized to the desired plane orientation
auto createdTimeGeometry = timeGeometry->Clone();
createdTimeGeometry->ReplaceTimeStepGeometries(slicedGeometry);
return createdTimeGeometry;
}
mitk::PlaneGeometry* mitk::SliceNavigationHelper::GetCurrentPlaneGeometry(const TimeGeometry* timeGeometry,
TimePointType timePoint,
unsigned int slicePosition)
{
if (nullptr == timeGeometry)
{
return nullptr;
}
const auto* slicedGeometry =
dynamic_cast<SlicedGeometry3D*>(timeGeometry->GetGeometryForTimePoint(timePoint).GetPointer());
if (nullptr == slicedGeometry)
{
// time point not valid for the time geometry
mitkThrow() << "Cannot extract a sliced geometry. A time point is selected that is not covered by"
<< "the given time geometry. Selected time point: " << timePoint;
}
return slicedGeometry->GetPlaneGeometry(slicePosition);
}
diff --git a/Modules/Core/src/Controllers/mitkTimeNavigationController.cpp b/Modules/Core/src/Controllers/mitkTimeNavigationController.cpp
new file mode 100644
index 0000000000..4766eb9732
--- /dev/null
+++ b/Modules/Core/src/Controllers/mitkTimeNavigationController.cpp
@@ -0,0 +1,129 @@
+/*============================================================================
+
+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 <mitkTimeNavigationController.h>
+
+#include <mitkRenderingManager.h>
+#include <mitkVtkPropRenderer.h>
+
+ mitk::TimeNavigationController::TimeNavigationController()
+ : BaseController()
+ , m_InputWorldTimeGeometry(mitk::TimeGeometry::ConstPointer())
+ , m_BlockUpdate(false)
+{
+ typedef itk::SimpleMemberCommand<TimeNavigationController> SNCCommandType;
+ SNCCommandType::Pointer timeStepperChangedCommand;
+
+ timeStepperChangedCommand = SNCCommandType::New();
+ timeStepperChangedCommand->SetCallbackFunction(this, &TimeNavigationController::SendTime);
+ m_Stepper->AddObserver(itk::ModifiedEvent(), timeStepperChangedCommand);
+ m_Stepper->SetUnitName("ms");
+}
+
+mitk::TimeNavigationController::~TimeNavigationController() {}
+
+void mitk::TimeNavigationController::SetInputWorldTimeGeometry(const TimeGeometry* geometry)
+{
+ if (geometry != nullptr)
+ {
+ if (geometry->GetBoundingBoxInWorld()->GetDiagonalLength2() < eps)
+ {
+ itkWarningMacro("setting an empty bounding-box");
+ geometry = nullptr;
+ }
+ }
+ if (m_InputWorldTimeGeometry != geometry)
+ {
+ m_InputWorldTimeGeometry = geometry;
+ this->Modified();
+ }
+}
+
+void mitk::TimeNavigationController::Update()
+{
+ if (m_BlockUpdate)
+ {
+ return;
+ }
+
+ if (m_InputWorldTimeGeometry.IsNull())
+ {
+ return;
+ }
+
+ if (0 == m_InputWorldTimeGeometry->CountTimeSteps())
+ {
+ return;
+ }
+
+ m_BlockUpdate = true;
+
+ if (m_LastUpdateTime < m_InputWorldTimeGeometry->GetMTime())
+ {
+ Modified();
+ }
+
+ if (m_LastUpdateTime < GetMTime())
+ {
+ m_LastUpdateTime = GetMTime();
+
+ TimeStepType inputTimeSteps = m_InputWorldTimeGeometry->CountTimeSteps();
+ const TimeBounds &timeBounds = m_InputWorldTimeGeometry->GetTimeBounds();
+ m_Stepper->SetSteps(inputTimeSteps);
+ m_Stepper->SetPos(0);
+ m_Stepper->SetRange(timeBounds[0], timeBounds[1]);
+ }
+
+ // unblock update; we may do this now, because if m_BlockUpdate was already
+ // true before this method was entered, then we will never come here.
+ m_BlockUpdate = false;
+
+ // Send the time. Do this even if nothing was changed, because maybe
+ // Update() was only called to re-send the old time data.
+ this->SendTime();
+}
+
+void mitk::TimeNavigationController::SendTime()
+{
+ if (!m_BlockUpdate)
+ {
+ if (m_InputWorldTimeGeometry.IsNotNull())
+ {
+ this->InvokeEvent(TimeEvent(m_Stepper->GetPos()));
+ RenderingManager::GetInstance()->RequestUpdateAll();
+ }
+ }
+}
+
+mitk::TimeStepType mitk::TimeNavigationController::GetSelectedTimeStep() const
+{
+ return m_Stepper->GetPos();
+}
+
+mitk::TimePointType mitk::TimeNavigationController::GetSelectedTimePoint() const
+{
+ const auto timeStep = this->GetSelectedTimeStep();
+
+ if (m_InputWorldTimeGeometry.IsNull())
+ {
+ return 0.0;
+ }
+
+ if (!m_InputWorldTimeGeometry->IsValidTimeStep(timeStep))
+ {
+ mitkThrow() << "SliceNavigationController is in an invalid state. It has a time step"
+ << "selected that is not covered by its time geometry. Selected time step: " << timeStep
+ << "; TimeGeometry steps count: " << m_InputWorldTimeGeometry->CountTimeSteps();
+ }
+
+ return m_InputWorldTimeGeometry->TimeStepToTimePoint(timeStep);
+}
diff --git a/Modules/Core/src/DataManagement/mitkApplicationCursor.cpp b/Modules/Core/src/DataManagement/mitkApplicationCursor.cpp
index 3252ed94bc..94132ece64 100644
--- a/Modules/Core/src/DataManagement/mitkApplicationCursor.cpp
+++ b/Modules/Core/src/DataManagement/mitkApplicationCursor.cpp
@@ -1,104 +1,104 @@
/*============================================================================
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 "mitkApplicationCursor.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <iostream>
mitk::ApplicationCursorImplementation *mitk::ApplicationCursor::m_Implementation = nullptr;
namespace mitk
{
ApplicationCursor::ApplicationCursor() {}
ApplicationCursor *ApplicationCursor::GetInstance()
{
static ApplicationCursor *m_Instance = nullptr;
if (!m_Instance)
{
m_Instance = new ApplicationCursor();
}
return m_Instance;
}
void ApplicationCursor::RegisterImplementation(ApplicationCursorImplementation *implementation)
{
m_Implementation = implementation;
}
void ApplicationCursor::PushCursor(std::istream &cursor, int hotspotX, int hotspotY)
{
if (m_Implementation)
{
m_Implementation->PushCursor(cursor, hotspotX, hotspotY);
}
else
{
MITK_ERROR << "in mitk::ApplicationCursor::PushCursor(): no implementation registered." << std::endl;
throw std::logic_error("No implementation registered for mitk::ApplicationCursor.");
}
}
void ApplicationCursor::PushCursor(const char *XPM[], int hotspotX, int hotspotY)
{
if (m_Implementation)
{
m_Implementation->PushCursor(XPM, hotspotX, hotspotY);
}
else
{
MITK_ERROR << "in mitk::ApplicationCursor::PushCursor(): no implementation registered." << std::endl;
throw std::logic_error("No implementation registered for mitk::ApplicationCursor.");
}
}
void ApplicationCursor::PopCursor()
{
if (m_Implementation)
{
m_Implementation->PopCursor();
}
else
{
MITK_ERROR << "in mitk::ApplicationCursor::PopCursor(): no implementation registered." << std::endl;
throw std::logic_error("No implementation registered for mitk::ApplicationCursor.");
}
}
const Point2I ApplicationCursor::GetCursorPosition()
{
if (m_Implementation)
{
return m_Implementation->GetCursorPosition();
}
else
{
MITK_ERROR << "in mitk::ApplicationCursor::GetCursorPosition(): no implementation registered." << std::endl;
throw std::logic_error("No implementation registered for mitk::ApplicationCursor.");
}
}
void ApplicationCursor::SetCursorPosition(const Point2I &p)
{
if (m_Implementation)
{
m_Implementation->SetCursorPosition(p);
}
else
{
MITK_ERROR << "in mitk::ApplicationCursor::SetCursorPosition(): no implementation registered." << std::endl;
throw std::logic_error("No implementation registered for mitk::ApplicationCursor.");
}
}
} // namespace
diff --git a/Modules/Core/src/DataManagement/mitkPlaneOperation.cpp b/Modules/Core/src/DataManagement/mitkPlaneOperation.cpp
index 27268eb3b1..01e007c04a 100644
--- a/Modules/Core/src/DataManagement/mitkPlaneOperation.cpp
+++ b/Modules/Core/src/DataManagement/mitkPlaneOperation.cpp
@@ -1,33 +1,33 @@
/*============================================================================
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 "mitkPlaneOperation.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
namespace mitk
{
PlaneOperation::PlaneOperation(OperationType operationType, Point3D point, Vector3D normal)
: PointOperation(operationType, point), m_Normal(normal), m_AreAxisDefined(false)
{
}
PlaneOperation::PlaneOperation(OperationType operationType, Point3D point, Vector3D axisVec0, Vector3D axisVec1)
: PointOperation(operationType, point), m_AxisVec0(axisVec0), m_AxisVec1(axisVec1), m_AreAxisDefined(true)
{
}
PlaneOperation::~PlaneOperation() {}
Vector3D mitk::PlaneOperation::GetNormal() { return m_Normal; }
Vector3D mitk::PlaneOperation::GetAxisVec0() { return m_AxisVec0; }
Vector3D mitk::PlaneOperation::GetAxisVec1() { return m_AxisVec1; }
bool mitk::PlaneOperation::AreAxisDefined() { return m_AreAxisDefined; }
} // namespace mitk
diff --git a/Modules/Core/src/DataManagement/mitkSlicedGeometry3D.cpp b/Modules/Core/src/DataManagement/mitkSlicedGeometry3D.cpp
index be03c44fd6..6e23ef32d9 100644
--- a/Modules/Core/src/DataManagement/mitkSlicedGeometry3D.cpp
+++ b/Modules/Core/src/DataManagement/mitkSlicedGeometry3D.cpp
@@ -1,962 +1,962 @@
/*============================================================================
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 <itkSpatialOrientationAdapter.h>
#include "mitkSlicedGeometry3D.h"
#include "mitkAbstractTransformGeometry.h"
#include "mitkApplyTransformMatrixOperation.h"
#include "mitkInteractionConst.h"
#include "mitkPlaneGeometry.h"
#include "mitkPlaneOperation.h"
#include "mitkRestorePlanePositionOperation.h"
#include "mitkRotationOperation.h"
#include "mitkSliceNavigationController.h"
const mitk::ScalarType PI = 3.14159265359;
mitk::SlicedGeometry3D::SlicedGeometry3D()
: m_EvenlySpaced(true), m_Slices(0), m_ReferenceGeometry(nullptr), m_SliceNavigationController(nullptr)
{
m_DirectionVector.Fill(0);
this->InitializeSlicedGeometry(m_Slices);
}
mitk::SlicedGeometry3D::SlicedGeometry3D(const SlicedGeometry3D &other)
: Superclass(other),
m_EvenlySpaced(other.m_EvenlySpaced),
m_Slices(other.m_Slices),
m_ReferenceGeometry(other.m_ReferenceGeometry),
m_SliceNavigationController(other.m_SliceNavigationController)
{
m_DirectionVector.Fill(0);
SetSpacing(other.GetSpacing());
SetDirectionVector(other.GetDirectionVector());
if (m_EvenlySpaced)
{
assert(!other.m_PlaneGeometries.empty() && "This may happen when you use one of the old Initialize methods, which had a bool parameter that is implicitly casted to the number of slices now.");
PlaneGeometry::Pointer geometry = other.m_PlaneGeometries[0]->Clone();
assert(geometry.IsNotNull());
SetPlaneGeometry(geometry, 0);
}
else
{
unsigned int s;
for (s = 0; s < other.m_Slices; ++s)
{
if (other.m_PlaneGeometries[s].IsNull())
{
assert(other.m_EvenlySpaced);
m_PlaneGeometries[s] = nullptr;
}
else
{
PlaneGeometry *geometry2D = other.m_PlaneGeometries[s]->Clone();
assert(geometry2D != nullptr);
SetPlaneGeometry(geometry2D, s);
}
}
}
}
mitk::SlicedGeometry3D::~SlicedGeometry3D()
{
}
mitk::PlaneGeometry *mitk::SlicedGeometry3D::GetPlaneGeometry(int s) const
{
mitk::PlaneGeometry::Pointer geometry2D = nullptr;
if (this->IsValidSlice(s))
{
geometry2D = m_PlaneGeometries[s];
// If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored
// for the requested slice, and (c) the first slice (s=0)
// is a PlaneGeometry instance, then we calculate the geometry of the
// requested as the plane of the first slice shifted by m_Spacing[2]*s
// in the direction of m_DirectionVector.
if ((m_EvenlySpaced) && (geometry2D.IsNull()))
{
PlaneGeometry *firstSlice = m_PlaneGeometries[0];
if (firstSlice != nullptr &&
dynamic_cast<AbstractTransformGeometry *>(m_PlaneGeometries[0].GetPointer()) == nullptr)
{
if ((m_DirectionVector[0] == 0.0) && (m_DirectionVector[1] == 0.0) && (m_DirectionVector[2] == 0.0))
{
m_DirectionVector = firstSlice->GetNormal();
m_DirectionVector.Normalize();
}
Vector3D direction;
direction = m_DirectionVector * this->GetSpacing()[2];
mitk::PlaneGeometry::Pointer requestedslice;
requestedslice = static_cast<mitk::PlaneGeometry *>(firstSlice->Clone().GetPointer());
requestedslice->SetOrigin(requestedslice->GetOrigin() + direction * s);
geometry2D = requestedslice;
m_PlaneGeometries[s] = geometry2D;
}
}
return geometry2D;
}
else
{
return nullptr;
}
}
const mitk::BoundingBox *mitk::SlicedGeometry3D::GetBoundingBox() const
{
assert(this->IsBoundingBoxNull() == false);
return Superclass::GetBoundingBox();
}
bool mitk::SlicedGeometry3D::SetPlaneGeometry(mitk::PlaneGeometry *geometry2D, int s)
{
if (this->IsValidSlice(s))
{
m_PlaneGeometries[s] = geometry2D;
m_PlaneGeometries[s]->SetReferenceGeometry(m_ReferenceGeometry);
return true;
}
return false;
}
void mitk::SlicedGeometry3D::InitializeSlicedGeometry(unsigned int slices)
{
Superclass::Initialize();
m_Slices = slices;
PlaneGeometry::Pointer gnull = nullptr;
m_PlaneGeometries.assign(m_Slices, gnull);
Vector3D spacing;
spacing.Fill(1.0);
this->SetSpacing(spacing);
m_DirectionVector.Fill(0);
}
void mitk::SlicedGeometry3D::InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, unsigned int slices)
{
assert(geometry2D != nullptr);
this->InitializeEvenlySpaced(geometry2D, geometry2D->GetExtentInMM(2) / geometry2D->GetExtent(2), slices);
}
void mitk::SlicedGeometry3D::InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D,
mitk::ScalarType zSpacing,
unsigned int slices)
{
assert(geometry2D != nullptr);
assert(geometry2D->GetExtent(0) > 0);
assert(geometry2D->GetExtent(1) > 0);
geometry2D->Register();
Superclass::Initialize();
m_Slices = slices;
BoundingBox::BoundsArrayType bounds = geometry2D->GetBounds();
bounds[4] = 0;
bounds[5] = slices;
// clear and reserve
PlaneGeometry::Pointer gnull = nullptr;
m_PlaneGeometries.assign(m_Slices, gnull);
Vector3D directionVector = geometry2D->GetAxisVector(2);
directionVector.Normalize();
directionVector *= zSpacing;
// Normally we should use the following four lines to create a copy of
// the transform contained in geometry2D, because it may not be changed
// by us. But we know that SetSpacing creates a new transform without
// changing the old (coming from geometry2D), so we can use the fifth
// line instead. We check this at (**).
//
// AffineTransform3D::Pointer transform = AffineTransform3D::New();
// transform->SetMatrix(geometry2D->GetIndexToWorldTransform()->GetMatrix());
// transform->SetOffset(geometry2D->GetIndexToWorldTransform()->GetOffset());
// SetIndexToWorldTransform(transform);
this->SetIndexToWorldTransform(geometry2D->GetIndexToWorldTransform());
mitk::Vector3D spacing;
FillVector3D(spacing, geometry2D->GetExtentInMM(0) / bounds[1], geometry2D->GetExtentInMM(1) / bounds[3], zSpacing);
this->SetDirectionVector(directionVector);
this->SetBounds(bounds);
this->SetPlaneGeometry(geometry2D, 0);
this->SetSpacing(spacing, true);
this->SetEvenlySpaced();
// this->SetTimeBounds( geometry2D->GetTimeBounds() );
assert(this->GetIndexToWorldTransform() != geometry2D->GetIndexToWorldTransform()); // (**) see above.
this->SetFrameOfReferenceID(geometry2D->GetFrameOfReferenceID());
this->SetImageGeometry(geometry2D->GetImageGeometry());
geometry2D->UnRegister();
}
void mitk::SlicedGeometry3D::InitializePlanes(const mitk::BaseGeometry *geometry3D,
mitk::AnatomicalPlane orientation,
bool top,
bool frontside,
bool rotated)
{
m_ReferenceGeometry = geometry3D;
PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane(geometry3D, top, orientation, frontside, rotated);
int worldAxis =
orientation == AnatomicalPlane::Sagittal ? 0 :
orientation == AnatomicalPlane::Coronal ? 1 : 2;
// Inspired by:
// http://www.na-mic.org/Wiki/index.php/Coordinate_System_Conversion_Between_ITK_and_Slicer3
mitk::AffineTransform3D::MatrixType matrix = geometry3D->GetIndexToWorldTransform()->GetMatrix();
matrix.GetVnlMatrix().normalize_columns();
mitk::AffineTransform3D::MatrixType::InternalMatrixType inverseMatrix = matrix.GetTranspose();
int dominantAxis = planeGeometry->CalculateDominantAxes(inverseMatrix).at(worldAxis);
ScalarType viewSpacing = geometry3D->GetSpacing()[dominantAxis];
/// Although the double value returned by GetExtent() holds a round number,
/// you need to add 0.5 to safely convert it to unsigned it. I have seen a
/// case when the result was less by one without this.
auto slices = static_cast<unsigned int>(geometry3D->GetExtent(dominantAxis) + 0.5);
if ( slices == 0 && geometry3D->GetExtent(dominantAxis) > 0) {
// require at least one slice if there is _some_ extent
slices = 1;
}
#ifndef NDEBUG
int upDirection = itk::Function::Sign(inverseMatrix[dominantAxis][worldAxis]);
/// The normal vector of an imaginary plane that points from the world origin (bottom left back
/// corner or the world, with the lowest physical coordinates) towards the inside of the volume,
/// along the renderer axis. Length is the slice thickness.
Vector3D worldPlaneNormal = inverseMatrix.get_row(dominantAxis) * (upDirection * viewSpacing);
/// The normal of the standard plane geometry just created.
Vector3D standardPlaneNormal = planeGeometry->GetNormal();
/// The standard plane must be parallel to the 'world plane'. The normal of the standard plane
/// must point against the world plane if and only if 'top' is 'false'. The length of the
/// standard plane normal must be equal to the slice thickness.
assert((standardPlaneNormal - (top ? 1.0 : -1.0) * worldPlaneNormal).GetSquaredNorm() < 0.000001);
#endif
this->InitializeEvenlySpaced(planeGeometry, viewSpacing, slices);
#ifndef NDEBUG
/// The standard plane normal and the z axis vector of the sliced geometry must point in
/// the same direction.
Vector3D zAxisVector = this->GetAxisVector(2);
Vector3D upscaledStandardPlaneNormal = standardPlaneNormal;
upscaledStandardPlaneNormal *= slices;
assert((zAxisVector - upscaledStandardPlaneNormal).GetSquaredNorm() < 0.000001);
/// You can use this test is to check the handedness of the coordinate system of the current
/// geometry. In principle, you can use either left- or right-handed coordinate systems, but
/// you normally want it to be consistent, that is the handedness should be the same across
/// the renderers of the same viewer.
// ScalarType det = vnl_det(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix());
// MITK_DEBUG << "world axis: " << worldAxis << (det > 0 ? " ; right-handed" : " ; left-handed");
#endif
}
void mitk::SlicedGeometry3D::ReinitializePlanes(const Point3D &center, const Point3D &referencePoint)
{
// Need a reference frame to align the rotated planes
if (!m_ReferenceGeometry)
{
return;
}
// Get first plane of plane stack
PlaneGeometry *firstPlane = m_PlaneGeometries[0];
// If plane stack is empty, exit
if (!firstPlane || dynamic_cast<AbstractTransformGeometry *>(firstPlane))
{
return;
}
// Calculate the "directed" spacing when taking the plane (defined by its axes
// vectors and normal) as the reference coordinate frame.
//
// This is done by calculating the radius of the ellipsoid defined by the
// original volume spacing axes, in the direction of the respective axis of the
// reference frame.
mitk::Vector3D axis0 = firstPlane->GetAxisVector(0);
mitk::Vector3D axis1 = firstPlane->GetAxisVector(1);
mitk::Vector3D normal = firstPlane->GetNormal();
normal.Normalize();
Vector3D spacing;
spacing[0] = this->CalculateSpacing(axis0);
spacing[1] = this->CalculateSpacing(axis1);
spacing[2] = this->CalculateSpacing(normal);
Superclass::SetSpacing(spacing);
// Now we need to calculate the number of slices in the plane's normal
// direction, so that the entire volume is covered. This is done by first
// calculating the dot product between the volume diagonal (the maximum
// distance inside the volume) and the normal, and dividing this value by
// the directed spacing calculated above.
ScalarType directedExtent = std::abs(m_ReferenceGeometry->GetExtentInMM(0) * normal[0]) +
std::abs(m_ReferenceGeometry->GetExtentInMM(1) * normal[1]) +
std::abs(m_ReferenceGeometry->GetExtentInMM(2) * normal[2]);
if (directedExtent >= spacing[2])
{
m_Slices = static_cast<unsigned int>(directedExtent / spacing[2] + 0.5);
}
else
{
m_Slices = 1;
}
// The origin of our "first plane" needs to be adapted to this new extent.
// To achieve this, we first calculate the current distance to the volume's
// center, and then shift the origin in the direction of the normal by the
// difference between this distance and half of the new extent.
double centerOfRotationDistance = firstPlane->SignedDistanceFromPlane(center);
if (centerOfRotationDistance > 0)
{
firstPlane->SetOrigin(firstPlane->GetOrigin() + normal * (centerOfRotationDistance - directedExtent / 2.0));
m_DirectionVector = normal;
}
else
{
firstPlane->SetOrigin(firstPlane->GetOrigin() + normal * (directedExtent / 2.0 + centerOfRotationDistance));
m_DirectionVector = -normal;
}
// Now we adjust this distance according with respect to the given reference
// point: we need to make sure that the point is touched by one slice of the
// new slice stack.
double referencePointDistance = firstPlane->SignedDistanceFromPlane(referencePoint);
auto referencePointSlice = static_cast<int>(referencePointDistance / spacing[2]);
double alignmentValue = referencePointDistance / spacing[2] - referencePointSlice;
firstPlane->SetOrigin(firstPlane->GetOrigin() + normal * alignmentValue * spacing[2]);
// Finally, we can clear the previous geometry stack and initialize it with
// our re-initialized "first plane".
m_PlaneGeometries.assign(m_Slices, PlaneGeometry::Pointer(nullptr));
if (m_Slices > 0)
{
m_PlaneGeometries[0] = firstPlane;
}
// Reinitialize SNC with new number of slices
- m_SliceNavigationController->GetSlice()->SetSteps(m_Slices);
+ m_SliceNavigationController->GetStepper()->SetSteps(m_Slices);
this->Modified();
}
double mitk::SlicedGeometry3D::CalculateSpacing(const mitk::Vector3D &d) const
{
// Need the spacing of the underlying dataset / geometry
if (!m_ReferenceGeometry)
{
return 1.0;
}
const mitk::Vector3D &spacing = m_ReferenceGeometry->GetSpacing();
return SlicedGeometry3D::CalculateSpacing(spacing, d);
}
double mitk::SlicedGeometry3D::CalculateSpacing(const mitk::Vector3D &spacing, const mitk::Vector3D &d)
{
// The following can be derived from the ellipsoid equation
//
// 1 = x^2/a^2 + y^2/b^2 + z^2/c^2
//
// where (a,b,c) = spacing of original volume (ellipsoid radii)
// and (x,y,z) = scaled coordinates of vector d (according to ellipsoid)
//
double scaling = d[0] * d[0] / (spacing[0] * spacing[0]) + d[1] * d[1] / (spacing[1] * spacing[1]) +
d[2] * d[2] / (spacing[2] * spacing[2]);
scaling = sqrt(scaling);
return (sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) / scaling);
}
mitk::Vector3D mitk::SlicedGeometry3D::AdjustNormal(const mitk::Vector3D &normal) const
{
TransformType::Pointer inverse = TransformType::New();
m_ReferenceGeometry->GetIndexToWorldTransform()->GetInverse(inverse);
Vector3D transformedNormal = inverse->TransformVector(normal);
transformedNormal.Normalize();
return transformedNormal;
}
void mitk::SlicedGeometry3D::SetImageGeometry(const bool isAnImageGeometry)
{
Superclass::SetImageGeometry(isAnImageGeometry);
unsigned int s;
for (s = 0; s < m_Slices; ++s)
{
mitk::BaseGeometry *geometry = m_PlaneGeometries[s];
if (geometry != nullptr)
{
geometry->SetImageGeometry(isAnImageGeometry);
}
}
}
void mitk::SlicedGeometry3D::ChangeImageGeometryConsideringOriginOffset(const bool isAnImageGeometry)
{
unsigned int s;
for (s = 0; s < m_Slices; ++s)
{
mitk::BaseGeometry *geometry = m_PlaneGeometries[s];
if (geometry != nullptr)
{
geometry->ChangeImageGeometryConsideringOriginOffset(isAnImageGeometry);
}
}
Superclass::ChangeImageGeometryConsideringOriginOffset(isAnImageGeometry);
}
bool mitk::SlicedGeometry3D::IsValidSlice(int s) const
{
return ((s >= 0) && (s < (int)m_Slices));
}
const mitk::BaseGeometry *mitk::SlicedGeometry3D::GetReferenceGeometry() const
{
return m_ReferenceGeometry;
}
void mitk::SlicedGeometry3D::SetReferenceGeometry(const BaseGeometry *referenceGeometry)
{
m_ReferenceGeometry = referenceGeometry;
std::vector<PlaneGeometry::Pointer>::iterator it;
for (it = m_PlaneGeometries.begin(); it != m_PlaneGeometries.end(); ++it)
{
(*it)->SetReferenceGeometry(referenceGeometry);
}
}
bool mitk::SlicedGeometry3D::HasReferenceGeometry() const
{
return ( m_ReferenceGeometry != nullptr );
}
void mitk::SlicedGeometry3D::PreSetSpacing(const mitk::Vector3D &aSpacing)
{
bool hasEvenlySpacedPlaneGeometry = false;
mitk::Point3D origin;
mitk::Vector3D rightDV, bottomDV;
BoundingBox::BoundsArrayType bounds;
// Check for valid spacing
if (!(aSpacing[0] > 0 && aSpacing[1] > 0 && aSpacing[2] > 0))
{
mitkThrow() << "You try to set a spacing with at least one element equal or "
"smaller to \"0\". This might lead to a crash during rendering. Please double"
" check your data!";
}
// In case of evenly-spaced data: re-initialize instances of PlaneGeometry,
// since the spacing influences them
if ((m_EvenlySpaced) && (m_PlaneGeometries.size() > 0))
{
const PlaneGeometry *planeGeometry = m_PlaneGeometries[0];
if (planeGeometry && !dynamic_cast<const AbstractTransformGeometry *>(planeGeometry))
{
this->WorldToIndex(planeGeometry->GetOrigin(), origin);
this->WorldToIndex(planeGeometry->GetAxisVector(0), rightDV);
this->WorldToIndex(planeGeometry->GetAxisVector(1), bottomDV);
bounds = planeGeometry->GetBounds();
hasEvenlySpacedPlaneGeometry = true;
}
}
BaseGeometry::_SetSpacing(aSpacing);
mitk::PlaneGeometry::Pointer firstGeometry;
// In case of evenly-spaced data: re-initialize instances of PlaneGeometry,
// since the spacing influences them
if (hasEvenlySpacedPlaneGeometry)
{
// create planeGeometry according to new spacing
this->IndexToWorld(origin, origin);
this->IndexToWorld(rightDV, rightDV);
this->IndexToWorld(bottomDV, bottomDV);
mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->SetImageGeometry(this->GetImageGeometry());
planeGeometry->SetReferenceGeometry(m_ReferenceGeometry);
// Store spacing, as Initialize... needs a pointer
mitk::Vector3D lokalSpacing = this->GetSpacing();
planeGeometry->InitializeStandardPlane(rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &lokalSpacing);
planeGeometry->SetOrigin(origin);
planeGeometry->SetBounds(bounds);
firstGeometry = planeGeometry;
}
else if ((m_EvenlySpaced) && (m_PlaneGeometries.size() > 0))
{
firstGeometry = m_PlaneGeometries[0].GetPointer();
}
// clear and reserve
PlaneGeometry::Pointer gnull = nullptr;
m_PlaneGeometries.assign(m_Slices, gnull);
if (m_Slices > 0)
{
m_PlaneGeometries[0] = firstGeometry;
}
this->Modified();
}
void mitk::SlicedGeometry3D::SetSliceNavigationController(SliceNavigationController *snc)
{
m_SliceNavigationController = snc;
}
mitk::SliceNavigationController *mitk::SlicedGeometry3D::GetSliceNavigationController()
{
return m_SliceNavigationController;
}
void mitk::SlicedGeometry3D::SetEvenlySpaced(bool on)
{
if (m_EvenlySpaced != on)
{
m_EvenlySpaced = on;
this->Modified();
}
}
void mitk::SlicedGeometry3D::SetDirectionVector(const mitk::Vector3D &directionVector)
{
Vector3D newDir = directionVector;
newDir.Normalize();
if (newDir != m_DirectionVector)
{
m_DirectionVector = newDir;
this->Modified();
}
}
// void
// mitk::SlicedGeometry3D::SetTimeBounds( const mitk::TimeBounds& timebounds )
//{
// Superclass::SetTimeBounds( timebounds );
//
// unsigned int s;
// for ( s = 0; s < m_Slices; ++s )
// {
// if(m_Geometry2Ds[s].IsNotNull())
// {
// m_Geometry2Ds[s]->SetTimeBounds( timebounds );
// }
// }
// m_TimeBounds = timebounds;
//}
itk::LightObject::Pointer mitk::SlicedGeometry3D::InternalClone() const
{
Self::Pointer newGeometry = new SlicedGeometry3D(*this);
newGeometry->UnRegister();
return newGeometry.GetPointer();
}
void mitk::SlicedGeometry3D::PrintSelf(std::ostream &os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
os << indent << " EvenlySpaced: " << m_EvenlySpaced << std::endl;
if (m_EvenlySpaced)
{
os << indent << " DirectionVector: " << m_DirectionVector << std::endl;
}
os << indent << " Slices: " << m_Slices << std::endl;
os << std::endl;
os << indent << " GetPlaneGeometry(0): ";
if (this->GetPlaneGeometry(0) == nullptr)
{
os << "nullptr" << std::endl;
}
else
{
this->GetPlaneGeometry(0)->Print(os, indent);
}
}
void mitk::SlicedGeometry3D::ExecuteOperation(Operation *operation)
{
PlaneGeometry::Pointer geometry2D;
ApplyTransformMatrixOperation *applyMatrixOp;
Point3D center;
switch (operation->GetOperationType())
{
case OpNOTHING:
break;
case OpROTATE:
if (m_EvenlySpaced)
{
// Need a reference frame to align the rotation
if (m_ReferenceGeometry)
{
// Clear all generated geometries and then rotate only the first slice.
// The other slices will be re-generated on demand
// Save first slice
PlaneGeometry::Pointer geometry2D = m_PlaneGeometries[0];
auto *rotOp = dynamic_cast<RotationOperation *>(operation);
// Generate a RotationOperation using the dataset center instead of
// the supplied rotation center. This is necessary so that the rotated
// zero-plane does not shift away. The supplied center is instead used
// to adjust the slice stack afterwards.
Point3D center = m_ReferenceGeometry->GetCenter();
RotationOperation centeredRotation(
rotOp->GetOperationType(), center, rotOp->GetVectorOfRotation(), rotOp->GetAngleOfRotation());
// Rotate first slice
geometry2D->ExecuteOperation(&centeredRotation);
// Clear the slice stack and adjust it according to the center of
// the dataset and the supplied rotation center (see documentation of
// ReinitializePlanes)
this->ReinitializePlanes(center, rotOp->GetCenterOfRotation());
geometry2D->SetSpacing(this->GetSpacing());
if (m_SliceNavigationController)
{
m_SliceNavigationController->SelectSliceByPoint(rotOp->GetCenterOfRotation());
m_SliceNavigationController->AdjustSliceStepperRange();
}
BaseGeometry::ExecuteOperation(&centeredRotation);
}
else
{
// we also have to consider the case, that there is no reference geometry available.
if (m_PlaneGeometries.size() > 0)
{
// Reach through to all slices in my container
for (auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
{
// Test for empty slices, which can happen if evenly spaced geometry
if ((*iter).IsNotNull())
{
(*iter)->ExecuteOperation(operation);
}
}
// rotate overall geometry
auto *rotOp = dynamic_cast<RotationOperation *>(operation);
BaseGeometry::ExecuteOperation(rotOp);
}
}
}
else
{
// Reach through to all slices
for (auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
{
(*iter)->ExecuteOperation(operation);
}
}
break;
case OpORIENT:
if (m_EvenlySpaced)
{
// get operation data
auto *planeOp = dynamic_cast<PlaneOperation *>(operation);
// Get first slice
PlaneGeometry::Pointer planeGeometry = m_PlaneGeometries[0];
// Need a PlaneGeometry, a PlaneOperation and a reference frame to
// carry out the re-orientation. If not all available, stop here
if (!m_ReferenceGeometry ||
(!planeGeometry || dynamic_cast<AbstractTransformGeometry *>(planeGeometry.GetPointer())) || !planeOp)
{
break;
}
// General Behavior:
// Clear all generated geometries and then rotate only the first slice.
// The other slices will be re-generated on demand
//
// 1st Step: Reorient Normal Vector of first plane
//
Point3D center = planeOp->GetPoint(); // m_ReferenceGeometry->GetCenter();
mitk::Vector3D currentNormal = planeGeometry->GetNormal();
mitk::Vector3D newNormal;
if (planeOp->AreAxisDefined())
{
// If planeOp was defined by one centerpoint and two axis vectors
newNormal = CrossProduct(planeOp->GetAxisVec0(), planeOp->GetAxisVec1());
}
else
{
// If planeOp was defined by one centerpoint and one normal vector
newNormal = planeOp->GetNormal();
}
// Get Rotation axis und angle
currentNormal.Normalize();
newNormal.Normalize();
ScalarType rotationAngle = angle(currentNormal.GetVnlVector(), newNormal.GetVnlVector());
rotationAngle *= 180.0 / vnl_math::pi; // from rad to deg
Vector3D rotationAxis = itk::CrossProduct(currentNormal, newNormal);
if (std::abs(rotationAngle - 180) < mitk::eps)
{
// current Normal and desired normal are not linear independent!!(e.g 1,0,0 and -1,0,0).
// Rotation Axis should be ANY vector that is 90� to current Normal
mitk::Vector3D helpNormal;
helpNormal = currentNormal;
helpNormal[0] += 1;
helpNormal[1] -= 1;
helpNormal[2] += 1;
helpNormal.Normalize();
rotationAxis = itk::CrossProduct(helpNormal, currentNormal);
}
RotationOperation centeredRotation(mitk::OpROTATE, center, rotationAxis, rotationAngle);
// Rotate first slice
planeGeometry->ExecuteOperation(&centeredRotation);
// Reinitialize planes and select slice, if my rotations are all done.
if (!planeOp->AreAxisDefined())
{
// Clear the slice stack and adjust it according to the center of
// rotation and plane position (see documentation of ReinitializePlanes)
this->ReinitializePlanes(center, planeOp->GetPoint());
planeGeometry->SetSpacing(this->GetSpacing());
if (m_SliceNavigationController)
{
m_SliceNavigationController->SelectSliceByPoint(planeOp->GetPoint());
m_SliceNavigationController->AdjustSliceStepperRange();
}
}
// Also apply rotation on the slicedGeometry - Geometry3D (Bounding geometry)
BaseGeometry::ExecuteOperation(&centeredRotation);
//
// 2nd step. If axis vectors were defined, rotate the plane around its normal to fit these
//
if (planeOp->AreAxisDefined())
{
mitk::Vector3D vecAxixNew = planeOp->GetAxisVec0();
vecAxixNew.Normalize();
mitk::Vector3D VecAxisCurr = planeGeometry->GetAxisVector(0);
VecAxisCurr.Normalize();
ScalarType rotationAngle = angle(VecAxisCurr.GetVnlVector(), vecAxixNew.GetVnlVector());
rotationAngle = rotationAngle * 180 / PI; // Rad to Deg
// we rotate around the normal of the plane, but we do not know, if we need to rotate clockwise
// or anti-clockwise. So we rotate around the crossproduct of old and new Axisvector.
// Since both axis vectors lie in the plane, the crossproduct is the planes normal or the negative planes
// normal
rotationAxis = itk::CrossProduct(VecAxisCurr, vecAxixNew);
if (std::abs(rotationAngle - 180) < mitk::eps)
{
// current axisVec and desired axisVec are not linear independent!!(e.g 1,0,0 and -1,0,0).
// Rotation Axis can be just plane Normal. (have to rotate by 180�)
rotationAxis = newNormal;
}
// Perform Rotation
mitk::RotationOperation op(mitk::OpROTATE, center, rotationAxis, rotationAngle);
planeGeometry->ExecuteOperation(&op);
// Apply changes on first slice to whole slice stack
this->ReinitializePlanes(center, planeOp->GetPoint());
planeGeometry->SetSpacing(this->GetSpacing());
if (m_SliceNavigationController)
{
m_SliceNavigationController->SelectSliceByPoint(planeOp->GetPoint());
m_SliceNavigationController->AdjustSliceStepperRange();
}
// Also apply rotation on the slicedGeometry - Geometry3D (Bounding geometry)
BaseGeometry::ExecuteOperation(&op);
}
}
else
{
// Reach through to all slices
for (auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
{
(*iter)->ExecuteOperation(operation);
}
}
break;
case OpRESTOREPLANEPOSITION:
if (m_EvenlySpaced)
{
// Save first slice
PlaneGeometry::Pointer planeGeometry = m_PlaneGeometries[0];
auto *restorePlaneOp = dynamic_cast<RestorePlanePositionOperation *>(operation);
// Need a PlaneGeometry, a PlaneOperation and a reference frame to
// carry out the re-orientation
if (m_ReferenceGeometry &&
(planeGeometry && dynamic_cast<AbstractTransformGeometry *>(planeGeometry.GetPointer()) == nullptr) &&
restorePlaneOp)
{
// Clear all generated geometries and then rotate only the first slice.
// The other slices will be re-generated on demand
// Rotate first slice
planeGeometry->ExecuteOperation(restorePlaneOp);
m_DirectionVector = restorePlaneOp->GetDirectionVector();
double centerOfRotationDistance = planeGeometry->SignedDistanceFromPlane(m_ReferenceGeometry->GetCenter());
if (centerOfRotationDistance <= 0)
{
m_DirectionVector = -m_DirectionVector;
}
Vector3D spacing = restorePlaneOp->GetSpacing();
Superclass::SetSpacing(spacing);
// /*Now we need to calculate the number of slices in the plane's normal
// direction, so that the entire volume is covered. This is done by first
// calculating the dot product between the volume diagonal (the maximum
// distance inside the volume) and the normal, and dividing this value by
// the directed spacing calculated above.*/
ScalarType directedExtent = std::abs(m_ReferenceGeometry->GetExtentInMM(0) * m_DirectionVector[0]) +
std::abs(m_ReferenceGeometry->GetExtentInMM(1) * m_DirectionVector[1]) +
std::abs(m_ReferenceGeometry->GetExtentInMM(2) * m_DirectionVector[2]);
if (directedExtent >= spacing[2])
{
m_Slices = static_cast<unsigned int>(directedExtent / spacing[2] + 0.5);
}
else
{
m_Slices = 1;
}
m_PlaneGeometries.assign(m_Slices, PlaneGeometry::Pointer(nullptr));
if (m_Slices > 0)
{
m_PlaneGeometries[0] = planeGeometry;
}
- m_SliceNavigationController->GetSlice()->SetSteps(m_Slices);
+ m_SliceNavigationController->GetStepper()->SetSteps(m_Slices);
this->Modified();
// End Reinitialization
if (m_SliceNavigationController)
{
- m_SliceNavigationController->GetSlice()->SetPos(restorePlaneOp->GetPos());
+ m_SliceNavigationController->GetStepper()->SetPos(restorePlaneOp->GetPos());
m_SliceNavigationController->AdjustSliceStepperRange();
}
BaseGeometry::ExecuteOperation(restorePlaneOp);
}
}
else
{
// Reach through to all slices
for (auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
{
(*iter)->ExecuteOperation(operation);
}
}
break;
case OpAPPLYTRANSFORMMATRIX:
// Clear all generated geometries and then transform only the first slice.
// The other slices will be re-generated on demand
// Save first slice
geometry2D = m_PlaneGeometries[0];
applyMatrixOp = dynamic_cast<ApplyTransformMatrixOperation *>(operation);
// Apply transformation to first plane
geometry2D->ExecuteOperation(applyMatrixOp);
// Generate a ApplyTransformMatrixOperation using the dataset center instead of
// the supplied rotation center. The supplied center is instead used to adjust the
// slice stack afterwards (see OpROTATE).
center = m_ReferenceGeometry->GetCenter();
// Clear the slice stack and adjust it according to the center of
// the dataset and the supplied rotation center (see documentation of
// ReinitializePlanes)
this->ReinitializePlanes(center, applyMatrixOp->GetReferencePoint());
BaseGeometry::ExecuteOperation(applyMatrixOp);
break;
default: // let handle by base class if we don't do anything
BaseGeometry::ExecuteOperation(operation);
}
this->Modified();
}
diff --git a/Modules/Core/src/IO/mitkFileReaderWriterBase.cpp b/Modules/Core/src/IO/mitkFileReaderWriterBase.cpp
index dc26e2f832..ec9ee85217 100644
--- a/Modules/Core/src/IO/mitkFileReaderWriterBase.cpp
+++ b/Modules/Core/src/IO/mitkFileReaderWriterBase.cpp
@@ -1,208 +1,208 @@
/*============================================================================
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 "mitkFileReaderWriterBase.h"
#include "mitkCoreServices.h"
#include "mitkIMimeTypeProvider.h"
#include "mitkIOMimeTypes.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <usGetModuleContext.h>
#include <usLDAPProp.h>
namespace mitk
{
FileReaderWriterBase::FileReaderWriterBase() : m_Ranking(0), m_MimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".")
{
}
FileReaderWriterBase::~FileReaderWriterBase() { this->UnregisterMimeType(); }
FileReaderWriterBase::FileReaderWriterBase(const FileReaderWriterBase &other)
: m_Description(other.m_Description),
m_Ranking(other.m_Ranking),
m_MimeTypePrefix(other.m_MimeTypePrefix),
m_Options(other.m_Options),
m_DefaultOptions(other.m_DefaultOptions),
m_CustomMimeType(other.m_CustomMimeType->Clone())
{
}
FileReaderWriterBase::Options FileReaderWriterBase::GetOptions() const
{
Options options = m_Options;
options.insert(m_DefaultOptions.begin(), m_DefaultOptions.end());
return options;
}
us::Any FileReaderWriterBase::GetOption(const std::string &name) const
{
auto iter = m_Options.find(name);
if (iter != m_Options.end())
{
return iter->second;
}
iter = m_DefaultOptions.find(name);
if (iter != m_DefaultOptions.end())
{
return iter->second;
}
return us::Any();
}
void FileReaderWriterBase::SetOptions(const FileReaderWriterBase::Options &options)
{
for (const auto &option : options)
{
this->SetOption(option.first, option.second);
}
}
void FileReaderWriterBase::SetOption(const std::string &name, const us::Any &value)
{
if (m_DefaultOptions.find(name) == m_DefaultOptions.end())
{
MITK_WARN << "Ignoring unknown IFileReader option '" << name << "'";
}
else
{
if (value.Empty())
{
// an empty Any signals 'reset to default value'
m_Options.erase(name);
}
else
{
m_Options[name] = value;
}
}
}
void FileReaderWriterBase::SetDefaultOptions(const FileReaderWriterBase::Options &defaultOptions)
{
m_DefaultOptions = defaultOptions;
}
FileReaderWriterBase::Options FileReaderWriterBase::GetDefaultOptions() const { return m_DefaultOptions; }
void FileReaderWriterBase::SetRanking(int ranking) { m_Ranking = ranking; }
int FileReaderWriterBase::GetRanking() const { return m_Ranking; }
void FileReaderWriterBase::SetMimeType(const CustomMimeType &mimeType) { m_CustomMimeType.reset(mimeType.Clone()); }
const CustomMimeType *FileReaderWriterBase::GetMimeType() const { return m_CustomMimeType.get(); }
CustomMimeType *FileReaderWriterBase::GetMimeType() { return m_CustomMimeType.get(); }
MimeType FileReaderWriterBase::GetRegisteredMimeType() const
{
MimeType result;
if (!m_MimeTypeReg)
{
if (!m_CustomMimeType->GetName().empty())
{
CoreServicePointer<IMimeTypeProvider> mimeTypeProvider(
CoreServices::GetMimeTypeProvider(us::GetModuleContext()));
return mimeTypeProvider->GetMimeTypeForName(m_CustomMimeType->GetName());
}
return result;
}
us::ServiceReferenceU reference = m_MimeTypeReg.GetReference();
try
{
int rank = 0;
us::Any rankProp = reference.GetProperty(us::ServiceConstants::SERVICE_RANKING());
if (!rankProp.Empty())
{
rank = us::any_cast<int>(rankProp);
}
auto id = us::any_cast<long>(reference.GetProperty(us::ServiceConstants::SERVICE_ID()));
result = MimeType(*m_CustomMimeType, rank, id);
}
catch (const us::BadAnyCastException &e)
{
MITK_WARN << "Unexpected exception: " << e.what();
}
return result;
}
void FileReaderWriterBase::SetMimeTypePrefix(const std::string &prefix) { m_MimeTypePrefix = prefix; }
std::string FileReaderWriterBase::GetMimeTypePrefix() const { return m_MimeTypePrefix; }
void FileReaderWriterBase::SetDescription(const std::string &description) { m_Description = description; }
std::string FileReaderWriterBase::GetDescription() const { return m_Description; }
void FileReaderWriterBase::AddProgressCallback(const FileReaderWriterBase::ProgressCallback &callback)
{
m_ProgressMessage += callback;
}
void FileReaderWriterBase::RemoveProgressCallback(const FileReaderWriterBase::ProgressCallback &callback)
{
m_ProgressMessage -= callback;
}
us::ServiceRegistration<CustomMimeType> FileReaderWriterBase::RegisterMimeType(us::ModuleContext *context)
{
if (context == nullptr)
throw std::invalid_argument("The context argument must not be nullptr.");
CoreServicePointer<IMimeTypeProvider> mimeTypeProvider(CoreServices::GetMimeTypeProvider(context));
const std::vector<std::string> extensions = m_CustomMimeType->GetExtensions();
// If the mime type name is set and the list of extensions is empty,
// look up the mime type in the registry and print a warning if
// there is none
if (!m_CustomMimeType->GetName().empty() && extensions.empty())
{
if (!mimeTypeProvider->GetMimeTypeForName(m_CustomMimeType->GetName()).IsValid())
{
MITK_WARN << "Registering a MITK reader or writer with an unknown MIME type " << m_CustomMimeType->GetName();
}
return m_MimeTypeReg;
}
// If the mime type name and extensions list is empty, print a warning
if (m_CustomMimeType->GetName().empty() && extensions.empty())
{
MITK_WARN << "Trying to register a MITK reader or writer with an empty mime type name and empty extension list.";
return m_MimeTypeReg;
}
// extensions is not empty
if (m_CustomMimeType->GetName().empty())
{
// Create a synthetic mime type name from the
// first extension in the list
m_CustomMimeType->SetName(m_MimeTypePrefix + extensions.front());
}
// Register a new mime type
// us::ServiceProperties props;
// props["name"] = m_CustomMimeType.GetName();
// props["extensions"] = m_CustomMimeType.GetExtensions();
m_MimeTypeReg = context->RegisterService<CustomMimeType>(m_CustomMimeType.get());
return m_MimeTypeReg;
}
void FileReaderWriterBase::UnregisterMimeType()
{
if (m_MimeTypeReg)
{
try
{
m_MimeTypeReg.Unregister();
}
catch (const std::logic_error &)
{
// service already unregistered
}
}
}
}
diff --git a/Modules/Core/src/IO/mitkIOMimeTypes.cpp b/Modules/Core/src/IO/mitkIOMimeTypes.cpp
index 0dd2af91a8..01a3d23c15 100644
--- a/Modules/Core/src/IO/mitkIOMimeTypes.cpp
+++ b/Modules/Core/src/IO/mitkIOMimeTypes.cpp
@@ -1,365 +1,365 @@
/*============================================================================
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 "mitkIOMimeTypes.h"
#include "mitkCustomMimeType.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <mitkUtf8Util.h>
#include "itkGDCMImageIO.h"
#include "itkMetaDataObject.h"
#include <itksys/SystemTools.hxx>
#include <itksys/Directory.hxx>
namespace mitk
{
IOMimeTypes::BaseDicomMimeType::BaseDicomMimeType(const std::string& name) : CustomMimeType(name)
{
this->AddExtension("gdcm");
this->AddExtension("dcm");
this->AddExtension("DCM");
this->AddExtension("dc3");
this->AddExtension("DC3");
this->AddExtension("ima");
this->AddExtension("img");
this->SetCategory(CATEGORY_IMAGES());
this->SetComment("DICOM");
}
bool IOMimeTypes::BaseDicomMimeType::AppliesTo(const std::string &path) const
{
// check whether directory or file
// if directory try to find first file within it instead
bool pathIsDirectory = itksys::SystemTools::FileIsDirectory(Utf8Util::Local8BitToUtf8(path));
std::string filepath = path;
if (pathIsDirectory)
{
itksys::Directory input;
input.Load(path.c_str());
std::vector<std::string> files;
for (unsigned long idx = 0; idx<input.GetNumberOfFiles(); idx++)
{
auto filename = Utf8Util::Local8BitToUtf8(input.GetFile(idx));
if (!itksys::SystemTools::FileIsDirectory(filename) && this->MatchesExtension(filename))
{
std::string fullpath = path + "/" + std::string(input.GetFile(idx));
files.push_back(fullpath.c_str());
}
}
if (!files.empty())
{
filepath = files.front();
}
}
// Ask the GDCM ImageIO class directly
itk::GDCMImageIO::Pointer gdcmIO = itk::GDCMImageIO::New();
gdcmIO->SetFileName(filepath);
try {
gdcmIO->ReadImageInformation();
}
catch (const itk::ExceptionObject & /*err*/) {
return false;
}
//DICOMRT modalities have specific reader, don't read with normal DICOM readers
std::string modality;
itk::MetaDataDictionary& dict = gdcmIO->GetMetaDataDictionary();
itk::ExposeMetaData<std::string>(dict, "0008|0060", modality);
MITK_DEBUG << "DICOM Modality detected by MimeType "<< this->GetName() << " is " << modality;
if (modality == "RTSTRUCT" || modality == "RTDOSE" || modality == "RTPLAN") {
return false;
}
else {
return gdcmIO->CanReadFile(filepath.c_str());
}
}
IOMimeTypes::BaseDicomMimeType*IOMimeTypes::BaseDicomMimeType::Clone() const { return new BaseDicomMimeType(*this); }
IOMimeTypes::DicomMimeType::DicomMimeType() : BaseDicomMimeType(DICOM_MIMETYPE_NAME())
{
}
IOMimeTypes::DicomMimeType* IOMimeTypes::DicomMimeType::Clone() const { return new DicomMimeType(*this); }
std::vector<CustomMimeType *> IOMimeTypes::Get()
{
std::vector<CustomMimeType *> mimeTypes;
// order matters here (descending rank for mime types)
mimeTypes.push_back(NRRD_MIMETYPE().Clone());
mimeTypes.push_back(NIFTI_MIMETYPE().Clone());
mimeTypes.push_back(VTK_IMAGE_MIMETYPE().Clone());
mimeTypes.push_back(VTK_PARALLEL_IMAGE_MIMETYPE().Clone());
mimeTypes.push_back(VTK_IMAGE_LEGACY_MIMETYPE().Clone());
mimeTypes.push_back(DICOM_MIMETYPE().Clone());
mimeTypes.push_back(VTK_POLYDATA_MIMETYPE().Clone());
mimeTypes.push_back(VTK_PARALLEL_POLYDATA_MIMETYPE().Clone());
mimeTypes.push_back(VTK_POLYDATA_LEGACY_MIMETYPE().Clone());
mimeTypes.push_back(STEREOLITHOGRAPHY_MIMETYPE().Clone());
mimeTypes.push_back(WAVEFRONT_OBJ_MIMETYPE().Clone());
mimeTypes.push_back(STANFORD_PLY_MIMETYPE().Clone());
mimeTypes.push_back(RAW_MIMETYPE().Clone());
mimeTypes.push_back(POINTSET_MIMETYPE().Clone());
return mimeTypes;
}
CustomMimeType IOMimeTypes::VTK_IMAGE_MIMETYPE()
{
CustomMimeType mimeType(VTK_IMAGE_NAME());
mimeType.AddExtension("vti");
mimeType.SetCategory(CATEGORY_IMAGES());
mimeType.SetComment("VTK Image");
return mimeType;
}
CustomMimeType IOMimeTypes::VTK_IMAGE_LEGACY_MIMETYPE()
{
CustomMimeType mimeType(VTK_IMAGE_LEGACY_NAME());
mimeType.AddExtension("vtk");
mimeType.SetCategory(CATEGORY_IMAGES());
mimeType.SetComment("VTK Legacy Image");
return mimeType;
}
CustomMimeType IOMimeTypes::VTK_PARALLEL_IMAGE_MIMETYPE()
{
CustomMimeType mimeType(VTK_PARALLEL_IMAGE_NAME());
mimeType.AddExtension("pvti");
mimeType.SetCategory(CATEGORY_IMAGES());
mimeType.SetComment("VTK Parallel Image");
return mimeType;
}
CustomMimeType IOMimeTypes::VTK_POLYDATA_MIMETYPE()
{
CustomMimeType mimeType(VTK_POLYDATA_NAME());
mimeType.AddExtension("vtp");
mimeType.SetCategory(CATEGORY_SURFACES());
mimeType.SetComment("VTK PolyData");
return mimeType;
}
CustomMimeType IOMimeTypes::VTK_POLYDATA_LEGACY_MIMETYPE()
{
CustomMimeType mimeType(VTK_POLYDATA_LEGACY_NAME());
mimeType.AddExtension("vtk");
mimeType.SetCategory(CATEGORY_SURFACES());
mimeType.SetComment("VTK Legacy PolyData");
return mimeType;
}
CustomMimeType IOMimeTypes::VTK_PARALLEL_POLYDATA_MIMETYPE()
{
CustomMimeType mimeType(VTK_PARALLEL_POLYDATA_NAME());
mimeType.AddExtension("pvtp");
mimeType.SetCategory(CATEGORY_SURFACES());
mimeType.SetComment("VTK Parallel PolyData");
return mimeType;
}
CustomMimeType IOMimeTypes::STEREOLITHOGRAPHY_MIMETYPE()
{
CustomMimeType mimeType(STEREOLITHOGRAPHY_NAME());
mimeType.AddExtension("stl");
mimeType.SetCategory(CATEGORY_SURFACES());
mimeType.SetComment("Stereolithography");
return mimeType;
}
CustomMimeType IOMimeTypes::WAVEFRONT_OBJ_MIMETYPE()
{
CustomMimeType mimeType(WAVEFRONT_OBJ_NAME());
mimeType.AddExtension("obj");
mimeType.SetCategory(CATEGORY_SURFACES());
mimeType.SetComment("Wavefront OBJ");
return mimeType;
}
CustomMimeType IOMimeTypes::STANFORD_PLY_MIMETYPE()
{
CustomMimeType mimeType(STANFORD_PLY_NAME());
mimeType.AddExtension("ply");
mimeType.SetCategory(CATEGORY_SURFACES());
mimeType.SetComment("Stanford PLY");
return mimeType;
}
std::string IOMimeTypes::STEREOLITHOGRAPHY_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".stl";
return name;
}
std::string IOMimeTypes::WAVEFRONT_OBJ_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".obj";
return name;
}
std::string IOMimeTypes::STANFORD_PLY_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".ply";
return name;
}
std::string IOMimeTypes::DEFAULT_BASE_NAME()
{
static std::string name = "application/vnd.mitk";
return name;
}
std::string IOMimeTypes::CATEGORY_IMAGES()
{
static std::string cat = "Images";
return cat;
}
std::string IOMimeTypes::CATEGORY_SURFACES()
{
static std::string cat = "Surfaces";
return cat;
}
std::string IOMimeTypes::VTK_IMAGE_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".vtk.image";
return name;
}
std::string IOMimeTypes::VTK_IMAGE_LEGACY_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".vtk.image.legacy";
return name;
}
std::string IOMimeTypes::VTK_PARALLEL_IMAGE_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.image";
return name;
}
std::string IOMimeTypes::VTK_POLYDATA_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata";
return name;
}
std::string IOMimeTypes::VTK_POLYDATA_LEGACY_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata.legacy";
return name;
}
std::string IOMimeTypes::VTK_PARALLEL_POLYDATA_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.polydata";
return name;
}
CustomMimeType IOMimeTypes::NRRD_MIMETYPE()
{
CustomMimeType mimeType(NRRD_MIMETYPE_NAME());
mimeType.AddExtension("nrrd");
mimeType.AddExtension("nhdr");
mimeType.SetCategory("Images");
mimeType.SetComment("NRRD");
return mimeType;
}
CustomMimeType IOMimeTypes::NIFTI_MIMETYPE()
{
CustomMimeType mimeType(NIFTI_MIMETYPE_NAME());
mimeType.AddExtension("nii");
mimeType.AddExtension("nii.gz");
mimeType.AddExtension("hdr");
mimeType.AddExtension("hdr.gz");
mimeType.AddExtension("img");
mimeType.AddExtension("img.gz");
mimeType.AddExtension("nia");
mimeType.SetCategory("Images");
mimeType.SetComment("Nifti");
return mimeType;
}
CustomMimeType IOMimeTypes::RAW_MIMETYPE()
{
CustomMimeType mimeType(RAW_MIMETYPE_NAME());
mimeType.AddExtension("raw");
mimeType.SetCategory("Images");
mimeType.SetComment("Raw data");
return mimeType;
}
IOMimeTypes::DicomMimeType IOMimeTypes::DICOM_MIMETYPE() { return DicomMimeType(); }
std::string IOMimeTypes::NRRD_MIMETYPE_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".image.nrrd";
return name;
}
std::string IOMimeTypes::NIFTI_MIMETYPE_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".image.nifti";
return name;
}
std::string IOMimeTypes::RAW_MIMETYPE_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".image.raw";
return name;
}
std::string IOMimeTypes::DICOM_MIMETYPE_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".image.dicom";
return name;
}
CustomMimeType IOMimeTypes::POINTSET_MIMETYPE()
{
CustomMimeType mimeType(POINTSET_MIMETYPE_NAME());
mimeType.AddExtension("mps");
mimeType.SetCategory("Point Sets");
mimeType.SetComment("MITK Point Set");
return mimeType;
}
std::string IOMimeTypes::POINTSET_MIMETYPE_NAME()
{
static std::string name = DEFAULT_BASE_NAME() + ".pointset";
return name;
}
CustomMimeType IOMimeTypes::GEOMETRY_DATA_MIMETYPE()
{
mitk::CustomMimeType mimeType(DEFAULT_BASE_NAME() + ".geometrydata");
mimeType.AddExtension("mitkgeometry");
mimeType.SetCategory("Geometries");
mimeType.SetComment("GeometryData object");
return mimeType;
}
}
diff --git a/Modules/Core/src/IO/mitkItkLoggingAdapter.cpp b/Modules/Core/src/IO/mitkItkLoggingAdapter.cpp
index ebf27b6df2..e404ae6435 100644
--- a/Modules/Core/src/IO/mitkItkLoggingAdapter.cpp
+++ b/Modules/Core/src/IO/mitkItkLoggingAdapter.cpp
@@ -1,32 +1,32 @@
/*============================================================================
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 "mitkItkLoggingAdapter.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
void mitk::ItkLoggingAdapter::Initialize()
{
itk::OutputWindow::SetInstance(mitk::ItkLoggingAdapter::New());
}
void mitk::ItkLoggingAdapter::DisplayText(const char *s)
{
MITK_INFO("ItkLogging") << s;
}
mitk::ItkLoggingAdapter::ItkLoggingAdapter()
{
}
mitk::ItkLoggingAdapter::~ItkLoggingAdapter()
{
}
diff --git a/Modules/Core/src/IO/mitkLocaleSwitch.cpp b/Modules/Core/src/IO/mitkLocaleSwitch.cpp
index 29edf535e9..0f159b6e0c 100644
--- a/Modules/Core/src/IO/mitkLocaleSwitch.cpp
+++ b/Modules/Core/src/IO/mitkLocaleSwitch.cpp
@@ -1,66 +1,66 @@
/*============================================================================
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 "mitkLocaleSwitch.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <clocale>
#include <string>
namespace mitk
{
struct LocaleSwitch::Impl
{
explicit Impl(const std::string &newLocale);
~Impl();
private:
/// locale at instantiation of object
std::string m_OldLocale;
/// locale during life-time of object
const std::string m_NewLocale;
};
LocaleSwitch::Impl::Impl(const std::string &newLocale) : m_NewLocale(newLocale)
{
// query and keep the current locale
const char *currentLocale = std::setlocale(LC_ALL, nullptr);
if (currentLocale != nullptr)
m_OldLocale = currentLocale;
else
m_OldLocale = "";
// install the new locale if it different from the current one
if (m_NewLocale != m_OldLocale)
{
if (!std::setlocale(LC_ALL, m_NewLocale.c_str()))
{
MITK_INFO << "Could not switch to locale " << m_NewLocale;
m_OldLocale = "";
}
}
}
LocaleSwitch::Impl::~Impl()
{
if (!m_OldLocale.empty() && m_OldLocale != m_NewLocale && !std::setlocale(LC_ALL, m_OldLocale.c_str()))
{
MITK_INFO << "Could not reset original locale " << m_OldLocale;
}
}
LocaleSwitch::LocaleSwitch(const char *newLocale) : m_LocaleSwitchImpl(new Impl(newLocale)) {}
LocaleSwitch::~LocaleSwitch() { delete m_LocaleSwitchImpl; }
}
diff --git a/Modules/Core/src/IO/mitkLog.cpp b/Modules/Core/src/IO/mitkLogBackend.cpp
similarity index 75%
rename from Modules/Core/src/IO/mitkLog.cpp
rename to Modules/Core/src/IO/mitkLogBackend.cpp
index 64fbe3a00a..7d4dfe32dc 100644
--- a/Modules/Core/src/IO/mitkLog.cpp
+++ b/Modules/Core/src/IO/mitkLogBackend.cpp
@@ -1,249 +1,248 @@
/*============================================================================
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 <mitkExceptionMacro.h>
-#include <mitkLog.h>
-#include <mitkLogMacros.h>
+#include <mitkLogBackend.h>
#include <itkOutputWindow.h>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <mutex>
static std::mutex logMutex;
-static mitk::LoggingBackend *mitkLogBackend = nullptr;
+static mitk::LogBackend *mitkLogBackend = nullptr;
static std::ofstream *logFile = nullptr;
static std::string logFileName = "";
static std::stringstream *outputWindow = nullptr;
static bool logOutputWindow = false;
-void mitk::LoggingBackend::EnableAdditionalConsoleWindow(bool enable)
+void mitk::LogBackend::EnableAdditionalConsoleWindow(bool enable)
{
logOutputWindow = enable;
}
-void mitk::LoggingBackend::ProcessMessage(const mbilog::LogMessage &l)
+void mitk::LogBackend::ProcessMessage(const LogMessage& message)
{
logMutex.lock();
#ifdef _WIN32
- FormatSmart(l, (int)GetCurrentThreadId());
+ FormatSmart(message, (int)GetCurrentThreadId());
#else
- FormatSmart(l);
+ FormatSmart(message);
#endif
if (logFile)
{
#ifdef _WIN32
- FormatFull(*logFile, l, (int)GetCurrentThreadId());
+ FormatFull(*logFile, message, (int)GetCurrentThreadId());
#else
- FormatFull(*logFile, l);
+ FormatFull(*logFile, message);
#endif
}
if (logOutputWindow)
{
if (outputWindow == nullptr)
{
outputWindow = new std::stringstream();
}
outputWindow->str("");
outputWindow->clear();
#ifdef _WIN32
- FormatFull(*outputWindow, l, (int)GetCurrentThreadId());
+ FormatFull(*outputWindow, message, (int)GetCurrentThreadId());
#else
- FormatFull(*outputWindow, l);
+ FormatFull(*outputWindow, message);
#endif
itk::OutputWindow::GetInstance()->DisplayText(outputWindow->str().c_str());
}
logMutex.unlock();
}
-void mitk::LoggingBackend::Register()
+void mitk::LogBackend::Register()
{
if (mitkLogBackend)
return;
- mitkLogBackend = new mitk::LoggingBackend();
- mbilog::RegisterBackend(mitkLogBackend);
+ mitkLogBackend = new LogBackend;
+ RegisterBackend(mitkLogBackend);
}
-void mitk::LoggingBackend::Unregister()
+void mitk::LogBackend::Unregister()
{
if (mitkLogBackend)
{
- SetLogFile(nullptr);
- mbilog::UnregisterBackend(mitkLogBackend);
+ SetLogFile("");
+ UnregisterBackend(mitkLogBackend);
delete mitkLogBackend;
mitkLogBackend = nullptr;
}
}
-void mitk::LoggingBackend::SetLogFile(const char *file)
+void mitk::LogBackend::SetLogFile(const std::string& file)
{
// closing old logfile
{
bool closed = false;
std::string closedFileName;
logMutex.lock();
if (logFile)
{
closed = true;
closedFileName = logFileName;
logFile->close();
delete logFile;
logFile = nullptr;
logFileName = "";
}
logMutex.unlock();
if (closed)
{
MITK_INFO << "closing logfile (" << closedFileName << ")";
}
}
// opening new logfile
- if (file)
+ if (!file.empty())
{
logMutex.lock();
logFileName = file;
logFile = new std::ofstream();
logFile->open(file, std::ios_base::out | std::ios_base::app);
if (logFile->good())
{
logMutex.unlock();
MITK_INFO << "Logfile: " << logFileName;
}
else
{
delete logFile;
logFile = nullptr;
logMutex.unlock();
MITK_WARN << "opening logfile '" << file << "' for writing failed";
}
// mutex is now unlocked
}
}
-std::string mitk::LoggingBackend::GetLogFile()
+std::string mitk::LogBackend::GetLogFile()
{
return logFileName;
}
-void mitk::LoggingBackend::CatchLogFileCommandLineParameter(int &argc, char **argv)
+void mitk::LogBackend::CatchLogFileCommandLineParameter(int &argc, char **argv)
{
int r;
for (r = 1; r < argc; r++)
{
if (std::string(argv[r]) == "--logfile")
{
if (r + 1 >= argc)
{
--argc;
MITK_ERROR << "--logfile parameter found, but no file given";
return;
}
- mitk::LoggingBackend::SetLogFile(argv[r + 1]);
+ SetLogFile(argv[r + 1]);
for (r += 2; r < argc; r++)
argv[r - 2] = argv[r];
argc -= 2;
return;
}
}
}
-void mitk::LoggingBackend::RotateLogFiles(const std::string &prefixPath)
+void mitk::LogBackend::RotateLogFiles(const std::string &prefixPath)
{
static const int numLogFiles = 10;
std::string newEmptyLogFileName;
// first: rotate the old log files to get a new, free logfile name
newEmptyLogFileName = IncrementLogFileNames(prefixPath, numLogFiles);
// now: use the new empty logfile name as name for this run
- mitk::LoggingBackend::SetLogFile(newEmptyLogFileName.c_str());
+ SetLogFile(newEmptyLogFileName.c_str());
}
-std::string mitk::LoggingBackend::IncrementLogFileNames(const std::string &prefixPath, int numLogFiles)
+std::string mitk::LogBackend::IncrementLogFileNames(const std::string &prefixPath, int numLogFiles)
{
// delete last one
{
std::stringstream s;
s << prefixPath.c_str() << "-" << numLogFiles - 1 << ".log";
// check if the file exists
if (CheckIfFileExists(s.str())) // if yes: delete it
{
int retVal = ::remove(s.str().c_str());
if (retVal != 0)
{
mitkThrow()
<< "Problem while deleting the oldest log file. Maybe the access to this files is blocked. Aborting!";
}
}
}
// rename the others
for (int r = numLogFiles - 1; r >= 1; r--)
{
std::stringstream dst;
dst << prefixPath.c_str() << "-" << r << ".log";
std::stringstream src;
src << prefixPath.c_str() << "-" << r - 1 << ".log";
// check if the source exists
if (CheckIfFileExists(src.str())) // if yes: rename it
{
int retVal = ::rename(src.str().c_str(), dst.str().c_str());
if (retVal != 0)
{
mitkThrow() << "Problem while renaming the log files. Maybe the access to this files is blocked. Aborting!";
}
}
}
// create new empty name and return it
{
std::stringstream s;
s << prefixPath.c_str() << "-0.log";
return s.str();
}
}
-bool mitk::LoggingBackend::CheckIfFileExists(const std::string &filename)
+bool mitk::LogBackend::CheckIfFileExists(const std::string &filename)
{
bool returnValue = false;
std::ifstream File(filename.c_str());
if (File.good())
{
returnValue = true;
}
else
{
returnValue = false;
}
File.close();
return returnValue;
}
-mbilog::OutputType mitk::LoggingBackend::GetOutputType() const
+mitk::LogBackendBase::OutputType mitk::LogBackend::GetOutputType() const
{
- return mbilog::Console;
+ return OutputType::Console;
}
diff --git a/Modules/Core/src/IO/mitkMimeTypeProvider.cpp b/Modules/Core/src/IO/mitkMimeTypeProvider.cpp
index eb6017fb8d..ec52cd3f15 100644
--- a/Modules/Core/src/IO/mitkMimeTypeProvider.cpp
+++ b/Modules/Core/src/IO/mitkMimeTypeProvider.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.
============================================================================*/
#include "mitkMimeTypeProvider.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <usGetModuleContext.h>
#include <usModuleContext.h>
#include <itksys/SystemTools.hxx>
#ifdef _MSC_VER
#pragma warning(disable : 4503) // decorated name length exceeded, name was truncated
#pragma warning(disable : 4355)
#endif
namespace mitk
{
MimeTypeProvider::MimeTypeProvider() : m_Tracker(nullptr) {}
MimeTypeProvider::~MimeTypeProvider() { delete m_Tracker; }
void MimeTypeProvider::Start()
{
if (m_Tracker == nullptr)
{
m_Tracker = new us::ServiceTracker<CustomMimeType, MimeTypeTrackerTypeTraits>(us::GetModuleContext(), this);
}
m_Tracker->Open();
}
void MimeTypeProvider::Stop() { m_Tracker->Close(); }
std::vector<MimeType> MimeTypeProvider::GetMimeTypes() const
{
std::vector<MimeType> result;
for (const auto &elem : m_NameToMimeType)
{
result.push_back(elem.second);
}
return result;
}
std::vector<MimeType> MimeTypeProvider::GetMimeTypesForFile(const std::string &filePath) const
{
std::vector<MimeType> result;
for (const auto &elem : m_NameToMimeType)
{
if (elem.second.AppliesTo(filePath))
{
result.push_back(elem.second);
}
}
std::sort(result.begin(), result.end());
std::reverse(result.begin(), result.end());
return result;
}
std::vector<MimeType> MimeTypeProvider::GetMimeTypesForCategory(const std::string &category) const
{
std::vector<MimeType> result;
for (const auto &elem : m_NameToMimeType)
{
if (elem.second.GetCategory() == category)
{
result.push_back(elem.second);
}
}
return result;
}
MimeType MimeTypeProvider::GetMimeTypeForName(const std::string &name) const
{
auto iter = m_NameToMimeType.find(name);
if (iter != m_NameToMimeType.end())
return iter->second;
return MimeType();
}
std::vector<std::string> MimeTypeProvider::GetCategories() const
{
std::vector<std::string> result;
for (const auto &elem : m_NameToMimeType)
{
std::string category = elem.second.GetCategory();
if (!category.empty())
{
result.push_back(category);
}
}
std::sort(result.begin(), result.end());
result.erase(std::unique(result.begin(), result.end()), result.end());
return result;
}
MimeTypeProvider::TrackedType MimeTypeProvider::AddingService(const ServiceReferenceType &reference)
{
MimeType result = this->GetMimeType(reference);
if (result.IsValid())
{
std::string name = result.GetName();
m_NameToMimeTypes[name].insert(result);
// get the highest ranked mime-type
m_NameToMimeType[name] = *(m_NameToMimeTypes[name].rbegin());
}
return result;
}
void MimeTypeProvider::ModifiedService(const ServiceReferenceType & /*reference*/, TrackedType /*mimetype*/)
{
// should we track changes in the ranking property?
}
void MimeTypeProvider::RemovedService(const ServiceReferenceType & /*reference*/, TrackedType mimeType)
{
std::string name = mimeType.GetName();
std::set<MimeType> &mimeTypes = m_NameToMimeTypes[name];
mimeTypes.erase(mimeType);
if (mimeTypes.empty())
{
m_NameToMimeTypes.erase(name);
m_NameToMimeType.erase(name);
}
else
{
// get the highest ranked mime-type
m_NameToMimeType[name] = *(mimeTypes.rbegin());
}
}
MimeType MimeTypeProvider::GetMimeType(const ServiceReferenceType &reference) const
{
MimeType result;
if (!reference)
return result;
CustomMimeType *mimeType = us::GetModuleContext()->GetService(reference);
if (mimeType != nullptr)
{
try
{
int rank = 0;
us::Any rankProp = reference.GetProperty(us::ServiceConstants::SERVICE_RANKING());
if (!rankProp.Empty())
{
rank = us::any_cast<int>(rankProp);
}
auto id = us::any_cast<long>(reference.GetProperty(us::ServiceConstants::SERVICE_ID()));
result = MimeType(*mimeType, rank, id);
}
catch (const us::BadAnyCastException &e)
{
MITK_WARN << "Unexpected exception: " << e.what();
}
us::GetModuleContext()->UngetService(reference);
}
return result;
}
}
diff --git a/Modules/Core/src/IO/mitkPixelType.cpp b/Modules/Core/src/IO/mitkPixelType.cpp
index 0d4c304d91..b6fa58301e 100644
--- a/Modules/Core/src/IO/mitkPixelType.cpp
+++ b/Modules/Core/src/IO/mitkPixelType.cpp
@@ -1,178 +1,178 @@
/*============================================================================
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 "mitkPixelType.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
mitk::PixelType::PixelType(const mitk::PixelType &other)
: m_ComponentType(other.m_ComponentType),
m_PixelType(other.m_PixelType),
m_ComponentTypeName(other.m_ComponentTypeName),
m_PixelTypeName(other.m_PixelTypeName),
m_NumberOfComponents(other.m_NumberOfComponents),
m_BytesPerComponent(other.m_BytesPerComponent)
{
}
mitk::PixelType &mitk::PixelType::operator=(const PixelType &other)
{
m_ComponentType = other.m_ComponentType;
m_PixelType = other.m_PixelType;
m_ComponentTypeName = other.m_ComponentTypeName;
m_PixelTypeName = other.m_PixelTypeName;
m_NumberOfComponents = other.m_NumberOfComponents;
m_BytesPerComponent = other.m_BytesPerComponent;
return *this;
}
mitk::PixelType::ItkIOPixelType mitk::PixelType::GetPixelType() const
{
return m_PixelType;
}
mitk::PixelType::ItkIOComponentType mitk::PixelType::GetComponentType() const
{
return m_ComponentType;
}
std::string mitk::PixelType::GetPixelTypeAsString() const
{
return m_PixelTypeName;
}
std::string mitk::PixelType::GetComponentTypeAsString() const
{
return m_ComponentTypeName;
}
std::string mitk::PixelType::GetTypeAsString() const
{
return m_PixelTypeName + " (" + m_ComponentTypeName + ")";
}
size_t mitk::PixelType::GetSize() const
{
return (m_NumberOfComponents * m_BytesPerComponent);
}
size_t mitk::PixelType::GetBpe() const
{
return this->GetSize() * 8;
}
size_t mitk::PixelType::GetNumberOfComponents() const
{
return m_NumberOfComponents;
}
size_t mitk::PixelType::GetBitsPerComponent() const
{
return m_BytesPerComponent * 8;
}
mitk::PixelType::~PixelType()
{
}
mitk::PixelType::PixelType(ItkIOComponentType componentType,
ItkIOPixelType pixelType,
std::size_t bytesPerComponent,
std::size_t numberOfComponents,
const std::string &componentTypeName,
const std::string &pixelTypeName)
: m_ComponentType(componentType),
m_PixelType(pixelType),
m_ComponentTypeName(componentTypeName),
m_PixelTypeName(pixelTypeName),
m_NumberOfComponents(numberOfComponents),
m_BytesPerComponent(bytesPerComponent)
{
}
bool mitk::PixelType::operator==(const mitk::PixelType &rhs) const
{
bool returnValue = ( this->m_PixelType == rhs.m_PixelType
&& this->m_ComponentType == rhs.m_ComponentType
&& this->m_NumberOfComponents == rhs.m_NumberOfComponents
&& this->m_BytesPerComponent == rhs.m_BytesPerComponent );
MITK_DEBUG << "|> mitk::PixelType::operator== rhs, lhs: \n"
<< "| m_BytesPerComponent = " << m_BytesPerComponent << ", " << rhs.m_BytesPerComponent << '\n'
<< "| m_NumberOfComponents = " << m_NumberOfComponents << ", " << rhs.m_NumberOfComponents << '\n'
<< "| m_PixelTypeName = " << m_PixelTypeName << ", " << rhs.m_PixelTypeName << '\n'
<< "| m_ComponentTypeName = " << m_ComponentTypeName << ", " << rhs.m_ComponentTypeName << '\n'
<< "| m_PixelType = " << m_PixelType << ", " << rhs.m_PixelType << '\n'
<< "| m_ComponentType = " << m_ComponentType << ", " << rhs.m_ComponentType
<< ", returnValue = " << returnValue << (returnValue ? "[True]" : "[False]") << ". <|";
return returnValue;
}
bool mitk::PixelType::operator!=(const mitk::PixelType &rhs) const
{
return !(this->operator==(rhs));
}
mitk::PixelType mitk::MakePixelType(vtkImageData *vtkimagedata)
{
int numOfComponents = vtkimagedata->GetNumberOfScalarComponents();
switch (vtkimagedata->GetScalarType())
{
case VTK_BIT:
case VTK_CHAR:
return mitk::MakePixelType<char, char>(numOfComponents);
break;
case VTK_UNSIGNED_CHAR:
return mitk::MakePixelType<unsigned char, unsigned char>(numOfComponents);
break;
case VTK_SHORT:
return mitk::MakePixelType<short, short>(numOfComponents);
break;
case VTK_UNSIGNED_SHORT:
return mitk::MakePixelType<unsigned short, unsigned short>(numOfComponents);
break;
case VTK_INT:
return mitk::MakePixelType<int, int>(numOfComponents);
break;
case VTK_UNSIGNED_INT:
return mitk::MakePixelType<unsigned int, unsigned int>(numOfComponents);
break;
case VTK_LONG:
return mitk::MakePixelType<long, long>(numOfComponents);
break;
case VTK_UNSIGNED_LONG:
return mitk::MakePixelType<unsigned long, unsigned long>(numOfComponents);
break;
case VTK_FLOAT:
return mitk::MakePixelType<float, float>(numOfComponents);
break;
case VTK_DOUBLE:
return mitk::MakePixelType<double, double>(numOfComponents);
break;
default:
break;
}
mitkThrow() << "tried to make pixeltype from vtkimage of unknown data type(short, char, int, ...)";
}
diff --git a/Modules/Core/src/IO/mitkStandardFileLocations.cpp b/Modules/Core/src/IO/mitkStandardFileLocations.cpp
index 903f49eefe..12ff940335 100644
--- a/Modules/Core/src/IO/mitkStandardFileLocations.cpp
+++ b/Modules/Core/src/IO/mitkStandardFileLocations.cpp
@@ -1,239 +1,239 @@
/*============================================================================
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 <mitkStandardFileLocations.h>
#include <itkMacro.h>
#include <itkObject.h>
#include <itksys/SystemTools.hxx>
#include <mitkConfig.h>
#include <mitkUtf8Util.h>
#include <algorithm>
mitk::StandardFileLocations::StandardFileLocations()
{
}
mitk::StandardFileLocations::~StandardFileLocations()
{
}
mitk::StandardFileLocations *mitk::StandardFileLocations::GetInstance()
{
static StandardFileLocations::Pointer m_Instance = nullptr;
if (m_Instance.IsNull())
m_Instance = StandardFileLocations::New();
return m_Instance;
}
void mitk::StandardFileLocations::AddDirectoryForSearch(const char *dir, bool insertInFrontOfSearchList)
{
// Do nothing if directory is already included into search list (TODO more clever: search only once!)
FileSearchVectorType::iterator iter;
if (m_SearchDirectories.size() > 0)
{
iter = std::find(m_SearchDirectories.begin(), m_SearchDirectories.end(), std::string(dir));
if (iter != m_SearchDirectories.end())
return;
}
// insert dir into queue
if (insertInFrontOfSearchList)
{
auto it = m_SearchDirectories.begin();
m_SearchDirectories.insert(it, std::string(dir));
}
else
m_SearchDirectories.push_back(std::string(dir));
}
void mitk::StandardFileLocations::RemoveDirectoryForSearch(const char *dir)
{
FileSearchVectorType::iterator it;
// background layers
if (m_SearchDirectories.size() > 0)
{
it = std::find(m_SearchDirectories.begin(), m_SearchDirectories.end(), std::string(dir));
if (it != m_SearchDirectories.end())
{
m_SearchDirectories.erase(it);
return;
}
}
}
std::string mitk::StandardFileLocations::SearchDirectoriesForFile(const char *filename)
{
FileSearchVectorType::iterator it;
for (it = m_SearchDirectories.begin(); it != m_SearchDirectories.end(); ++it)
{
std::string currDir = (*it);
// Perhaps append "/" before appending filename
if (currDir.find_last_of("\\") + 1 != currDir.size() || currDir.find_last_of("/") + 1 != currDir.size())
currDir += "/";
// Append filename
currDir += filename;
// Perhaps remove "/" after filename
if (currDir.find_last_of("\\") + 1 == currDir.size() || currDir.find_last_of("/") + 1 == currDir.size())
currDir.erase(currDir.size() - 1, currDir.size());
// convert to OS dependent path schema
currDir = Utf8Util::Utf8ToLocal8Bit(itksys::SystemTools::ConvertToOutputPath(Utf8Util::Local8BitToUtf8(currDir).c_str()));
// On windows systems, the ConvertToOutputPath method quotes paths that contain empty spaces.
// These quotes are not expected by the FileExists method and therefore removed, if existing.
if (currDir.find_last_of("\"") + 1 == currDir.size())
currDir.erase(currDir.size() - 1, currDir.size());
if (currDir.find_last_of("\"") == 0)
currDir.erase(0, 1);
// Return first found path
if (itksys::SystemTools::FileExists(Utf8Util::Local8BitToUtf8(currDir).c_str()))
return currDir;
}
return std::string("");
}
std::string mitk::StandardFileLocations::FindFile(const char *filename, const char *pathInSourceDir)
{
std::string directoryPath;
// 1. look for MITKCONF environment variable
const char *mitkConf = itksys::SystemTools::GetEnv("MITKCONF");
if (mitkConf != nullptr)
AddDirectoryForSearch(mitkConf, false);
// 2. use .mitk-subdirectory in home directory of the user
#if defined(_WIN32) && !defined(__CYGWIN__)
const char *homeDrive = itksys::SystemTools::GetEnv("HOMEDRIVE");
const char *homePath = itksys::SystemTools::GetEnv("HOMEPATH");
if ((homeDrive != nullptr) || (homePath != nullptr))
{
directoryPath = homeDrive;
directoryPath += homePath;
directoryPath += "/.mitk/";
AddDirectoryForSearch(directoryPath.c_str(), false);
}
#else
const char *homeDirectory = itksys::SystemTools::GetEnv("HOME");
if (homeDirectory != nullptr)
{
directoryPath = homeDirectory;
directoryPath += "/.mitk/";
AddDirectoryForSearch(directoryPath.c_str(), false);
}
#endif // defined(_WIN32) && !defined(__CYGWIN__)
// 3. look in the current working directory
directoryPath = "";
AddDirectoryForSearch(directoryPath.c_str());
directoryPath = Utf8Util::Utf8ToLocal8Bit(itksys::SystemTools::GetCurrentWorkingDirectory());
AddDirectoryForSearch(directoryPath.c_str(), false);
std::string directoryBinPath = directoryPath + "/bin";
AddDirectoryForSearch(directoryBinPath.c_str(), false);
// 4. use a source tree location from compile time
directoryPath = MITK_ROOT;
if (pathInSourceDir)
{
directoryPath += pathInSourceDir;
}
directoryPath += '/';
AddDirectoryForSearch(directoryPath.c_str(), false);
return SearchDirectoriesForFile(filename);
}
std::string mitk::StandardFileLocations::GetOptionDirectory()
{
const char *mitkoptions = itksys::SystemTools::GetEnv("MITKOPTIONS");
std::string optionsDirectory;
if (mitkoptions != nullptr)
{
// 1. look for MITKOPTIONS environment variable
optionsDirectory = mitkoptions;
optionsDirectory += "/";
}
else
{
// 2. use .mitk-subdirectory in home directory of the user
std::string homeDirectory;
#if defined(_WIN32) && !defined(__CYGWIN__)
const char *homeDrive = itksys::SystemTools::GetEnv("HOMEDRIVE");
const char *homePath = itksys::SystemTools::GetEnv("HOMEPATH");
if ((homeDrive == nullptr) || (homePath == nullptr))
{
itkGenericOutputMacro(<< "Environment variables HOMEDRIVE and/or HOMEPATH not set"
<< ". Using current working directory as home directory: "
<< Utf8Util::Utf8ToLocal8Bit(itksys::SystemTools::GetCurrentWorkingDirectory()));
homeDirectory = Utf8Util::Utf8ToLocal8Bit(itksys::SystemTools::GetCurrentWorkingDirectory());
}
else
{
homeDirectory = homeDrive;
homeDirectory += homePath;
}
if (itksys::SystemTools::FileExists(Utf8Util::Local8BitToUtf8(homeDirectory).c_str()) == false)
{
itkGenericOutputMacro(<< "Could not find home directory at " << homeDirectory
<< ". Using current working directory as home directory: "
<< Utf8Util::Utf8ToLocal8Bit(itksys::SystemTools::GetCurrentWorkingDirectory()));
homeDirectory = Utf8Util::Utf8ToLocal8Bit(itksys::SystemTools::GetCurrentWorkingDirectory());
}
#else
const char *home = itksys::SystemTools::GetEnv("HOME");
if (home == nullptr)
{
itkGenericOutputMacro(<< "Environment variable HOME not set"
<< ". Using current working directory as home directory: "
<< itksys::SystemTools::GetCurrentWorkingDirectory());
homeDirectory = itksys::SystemTools::GetCurrentWorkingDirectory();
}
else
homeDirectory = home;
if (itksys::SystemTools::FileExists(homeDirectory.c_str()) == false)
{
itkGenericOutputMacro(<< "Could not find home directory at " << homeDirectory
<< ". Using current working directory as home directory: "
<< itksys::SystemTools::GetCurrentWorkingDirectory());
homeDirectory = itksys::SystemTools::GetCurrentWorkingDirectory();
}
#endif // defined(_WIN32) && !defined(__CYGWIN__)
optionsDirectory = homeDirectory;
optionsDirectory += "/.mitk";
}
optionsDirectory = itksys::SystemTools::ConvertToOutputPath(Utf8Util::Local8BitToUtf8(optionsDirectory).c_str());
if (itksys::SystemTools::CountChar(optionsDirectory.c_str(), '"') > 0)
{
char *unquoted = itksys::SystemTools::RemoveChars(optionsDirectory.c_str(), "\"");
optionsDirectory = unquoted;
delete[] unquoted;
}
- if (itksys::SystemTools::MakeDirectory(optionsDirectory.c_str()) == false)
+ if (!itksys::SystemTools::MakeDirectory(optionsDirectory.c_str()).IsSuccess())
{
itkGenericExceptionMacro(<< "Could not create .mitk directory at " << Utf8Util::Utf8ToLocal8Bit(optionsDirectory));
}
return Utf8Util::Utf8ToLocal8Bit(optionsDirectory);
}
diff --git a/Modules/Core/src/IO/mitkVtkLoggingAdapter.cpp b/Modules/Core/src/IO/mitkVtkLoggingAdapter.cpp
index 63a14921a0..83a6441dbb 100644
--- a/Modules/Core/src/IO/mitkVtkLoggingAdapter.cpp
+++ b/Modules/Core/src/IO/mitkVtkLoggingAdapter.cpp
@@ -1,52 +1,52 @@
/*============================================================================
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 "mitkVtkLoggingAdapter.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <vtkObjectFactory.h>
namespace mitk
{
vtkStandardNewMacro(VtkLoggingAdapter);
}
void mitk::VtkLoggingAdapter::Initialize()
{
mitk::VtkLoggingAdapter *vtklog = mitk::VtkLoggingAdapter::New();
vtkOutputWindow::SetInstance(vtklog);
vtklog->Delete();
}
void mitk::VtkLoggingAdapter::DisplayText(const char *t)
{
MITK_INFO("VtkText") << t;
}
void mitk::VtkLoggingAdapter::DisplayErrorText(const char *t)
{
MITK_ERROR("VtkError") << t;
}
void mitk::VtkLoggingAdapter::DisplayWarningText(const char *t)
{
MITK_WARN("VtkWarning") << t;
}
void mitk::VtkLoggingAdapter::DisplayGenericWarningText(const char *t)
{
MITK_WARN("VtkGenericWarning") << t;
}
void mitk::VtkLoggingAdapter::DisplayDebugText(const char *t)
{
MITK_DEBUG("VtkDebug") << t;
}
diff --git a/Modules/Core/src/IO/mitkXMLPreferencesStorage.cpp b/Modules/Core/src/IO/mitkXMLPreferencesStorage.cpp
index c0ee7f6c7a..c67a9270b9 100644
--- a/Modules/Core/src/IO/mitkXMLPreferencesStorage.cpp
+++ b/Modules/Core/src/IO/mitkXMLPreferencesStorage.cpp
@@ -1,114 +1,114 @@
/*============================================================================
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 "mitkXMLPreferencesStorage.h"
#include "mitkPreferences.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <tinyxml2.h>
namespace
{
std::string GetStringAttribute(const tinyxml2::XMLElement* xmlElement, const char* name)
{
const auto* attribute = xmlElement->Attribute(name);
return attribute != nullptr
? attribute
: "";
}
mitk::Preferences* Deserialize(const tinyxml2::XMLElement* xmlPreferenceElement, mitk::Preferences* parentPreferences, mitk::IPreferencesStorage* storage)
{
const std::string name = GetStringAttribute(xmlPreferenceElement, "name");
const auto* xmlPropertyElement = xmlPreferenceElement->FirstChildElement("property");
mitk::Preferences::Properties properties;
while (xmlPropertyElement != nullptr)
{
properties[GetStringAttribute(xmlPropertyElement, "name")] = GetStringAttribute(xmlPropertyElement, "value");
xmlPropertyElement = xmlPropertyElement->NextSiblingElement("property");
}
auto* preferences = new mitk::Preferences(properties, name, parentPreferences, storage);
const auto* xmlPreferenceChildElement = xmlPreferenceElement->FirstChildElement("preferences");
while (xmlPreferenceChildElement != nullptr)
{
Deserialize(xmlPreferenceChildElement, preferences, storage);
xmlPreferenceChildElement = xmlPreferenceChildElement->NextSiblingElement("preferences");
}
return preferences;
}
void Serialize(const mitk::Preferences* preferences, tinyxml2::XMLNode* xmlParentNode)
{
auto* xmlDocument = xmlParentNode->GetDocument();
auto* xmlPreferenceElement = xmlDocument->NewElement("preferences");
xmlPreferenceElement->SetAttribute("name", preferences->Name().c_str());
for (const auto& [name, value] : preferences->GetProperties())
{
auto* xmlPropertyElement = xmlDocument->NewElement("property");
xmlPropertyElement->SetAttribute("name", name.c_str());
xmlPropertyElement->SetAttribute("value", value.c_str());
xmlPreferenceElement->InsertEndChild(xmlPropertyElement);
}
xmlParentNode->InsertEndChild(xmlPreferenceElement);
for (const auto& child : preferences->GetChildren())
Serialize(child.get(), xmlPreferenceElement);
}
}
mitk::XMLPreferencesStorage::XMLPreferencesStorage(const std::filesystem::path& filename)
: IPreferencesStorage(filename)
{
if (std::filesystem::exists(filename))
{
tinyxml2::XMLDocument xmlDocument;
if (xmlDocument.LoadFile(filename.string().c_str()) == tinyxml2::XML_SUCCESS)
{
m_Root.reset(Deserialize(xmlDocument.RootElement(), nullptr, this));
return;
}
else
{
MITK_ERROR << "Could not load preferences from \"" << filename.string() << "\"!";
}
}
m_Root = std::make_unique<Preferences>(Preferences::Properties(), "", nullptr, this);
}
mitk::XMLPreferencesStorage::~XMLPreferencesStorage()
{
}
void mitk::XMLPreferencesStorage::Flush()
{
tinyxml2::XMLDocument xmlDocument;
xmlDocument.InsertEndChild(xmlDocument.NewDeclaration());
Serialize(static_cast<const mitk::Preferences*>(m_Root.get()), &xmlDocument);
if (xmlDocument.SaveFile(m_Filename.string().c_str()) != tinyxml2::XML_SUCCESS)
MITK_ERROR << "Could not save preferences to \"" << m_Filename.string() << "\"!";
}
diff --git a/Modules/Core/src/Interactions/mitkDisplayActionEventBroadcast.cpp b/Modules/Core/src/Interactions/mitkDisplayActionEventBroadcast.cpp
index fd3cf979ef..e7718b3a4a 100644
--- a/Modules/Core/src/Interactions/mitkDisplayActionEventBroadcast.cpp
+++ b/Modules/Core/src/Interactions/mitkDisplayActionEventBroadcast.cpp
@@ -1,807 +1,808 @@
/*============================================================================
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 "mitkDisplayActionEventBroadcast.h"
// us
#include "usGetModuleContext.h"
#include "usModuleContext.h"
// mitk core module
#include <mitkDisplayActionEvents.h>
#include <mitkImage.h>
#include <mitkInteractionConst.h>
#include <mitkInteractionPositionEvent.h>
#include <mitkLine.h>
#include <mitkRotationOperation.h>
+#include <mitkTimeNavigationController.h>
#include <rotate_cursor.xpm>
mitk::DisplayActionEventBroadcast::DisplayActionEventBroadcast()
: m_AlwaysReact(false)
, m_AutoRepeat(false)
, m_IndexToSliceModifier(4)
, m_InvertScrollDirection(false)
, m_InvertZoomDirection(false)
, m_ZoomFactor(2)
, m_InvertMoveDirection(false)
, m_InvertLevelWindowDirection(false)
, m_LinkPlanes(true)
{
m_StartCoordinateInMM.Fill(0);
m_LastDisplayCoordinate.Fill(0);
m_CurrentDisplayCoordinate.Fill(0);
// register the broadcast class (itself) as an interaction event observer via micro services
us::ServiceProperties props;
props["name"] = std::string("DisplayActionEventBroadcast");
m_ServiceRegistration = us::GetModuleContext()->RegisterService<InteractionEventObserver>(this, props);
}
mitk::DisplayActionEventBroadcast::~DisplayActionEventBroadcast()
{
m_ServiceRegistration.Unregister();
}
void mitk::DisplayActionEventBroadcast::Notify(InteractionEvent* interactionEvent, bool isHandled)
{
// the event is passed to the state machine interface to be handled
if (!isHandled || m_AlwaysReact)
{
HandleEvent(interactionEvent, nullptr);
}
}
void mitk::DisplayActionEventBroadcast::ConnectActionsAndFunctions()
{
CONNECT_CONDITION("check_position_event", CheckPositionEvent);
CONNECT_CONDITION("check_can_rotate", CheckRotationPossible);
CONNECT_CONDITION("check_can_swivel", CheckSwivelPossible);
CONNECT_FUNCTION("init", Init);
CONNECT_FUNCTION("move", Move);
CONNECT_FUNCTION("zoom", Zoom);
CONNECT_FUNCTION("scroll", Scroll);
CONNECT_FUNCTION("ScrollOneUp", ScrollOneUp);
CONNECT_FUNCTION("ScrollOneDown", ScrollOneDown);
CONNECT_FUNCTION("levelWindow", AdjustLevelWindow);
CONNECT_FUNCTION("setCrosshair", SetCrosshair);
CONNECT_FUNCTION("startRotation", StartRotation);
CONNECT_FUNCTION("endRotation", EndRotation);
CONNECT_FUNCTION("rotate", Rotate);
CONNECT_FUNCTION("swivel", Swivel);
CONNECT_FUNCTION("IncreaseTimeStep", IncreaseTimeStep);
CONNECT_FUNCTION("DecreaseTimeStep", DecreaseTimeStep);
}
void mitk::DisplayActionEventBroadcast::ConfigurationChanged()
{
PropertyList::Pointer properties = GetAttributes();
// alwaysReact
std::string strAlwaysReact = "";
m_AlwaysReact = false;
if (properties->GetStringProperty("alwaysReact", strAlwaysReact))
{
if (strAlwaysReact == "true")
{
m_AlwaysReact = true;
}
}
// auto repeat
std::string strAutoRepeat = "";
m_AutoRepeat = false;
if (properties->GetStringProperty("autoRepeat", strAutoRepeat))
{
if (strAutoRepeat == "true")
{
m_AutoRepeat = true;
}
}
// pixel movement for scrolling one slice
std::string strPixelPerSlice = "";
m_IndexToSliceModifier = 4;
if (properties->GetStringProperty("pixelPerSlice", strPixelPerSlice))
{
m_IndexToSliceModifier = atoi(strPixelPerSlice.c_str());
}
// scroll direction
if (!properties->GetStringProperty("scrollDirection", m_ScrollDirection))
{
m_ScrollDirection = "updown";
}
m_InvertScrollDirection = GetBoolProperty(properties, "invertScrollDirection", false);
// zoom direction
if (!properties->GetStringProperty("zoomDirection", m_ZoomDirection))
{
m_ZoomDirection = "updown";
}
m_InvertZoomDirection = GetBoolProperty(properties, "invertZoomDirection", false);
m_InvertMoveDirection = GetBoolProperty(properties, "invertMoveDirection", false);
if (!properties->GetStringProperty("levelWindowDirection", m_LevelDirection))
{
m_LevelDirection = "leftright";
}
m_InvertLevelWindowDirection = GetBoolProperty(properties, "invertLevelWindowDirection", false);
// coupled rotation
std::string strCoupled = "";
m_LinkPlanes = false;
if (properties->GetStringProperty("coupled", strCoupled))
{
if (strCoupled == "true")
{
m_LinkPlanes = true;
}
}
// zoom factor
std::string strZoomFactor = "";
properties->GetStringProperty("zoomFactor", strZoomFactor);
m_ZoomFactor = .05;
if (atoi(strZoomFactor.c_str()) > 0)
{
m_ZoomFactor = 1.0 + (atoi(strZoomFactor.c_str()) / 100.0);
}
}
bool mitk::DisplayActionEventBroadcast::FilterEvents(InteractionEvent* interactionEvent, DataNode * /*dataNode*/)
{
BaseRenderer* sendingRenderer = interactionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return false;
}
if (BaseRenderer::Standard3D == sendingRenderer->GetMapperID())
{
return false;
}
return true;
}
bool mitk::DisplayActionEventBroadcast::CheckPositionEvent(const InteractionEvent *interactionEvent)
{
const auto* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return false;
}
return true;
}
bool mitk::DisplayActionEventBroadcast::CheckRotationPossible(const InteractionEvent *interactionEvent)
{
// Decide between moving and rotation slices.
/*
Detailed logic:
1. Find the SliceNavigationController that has sent the event: this one defines our rendering plane and will NOT be
rotated. Needs not even be counted or checked.
2. Inspect every other SliceNavigationController
- calculate the line intersection of this SliceNavigationController's plane with our rendering plane
- if there is NO intersection, ignore and continue
- IF there is an intersection
- check the mouse cursor's distance from that line.
0. if the line is NOT near the cursor, remember the plane as "one of the other planes" (which can be rotated in
"locked" mode)
1. on first line near the cursor, just remember this intersection line as THE other plane that we want to rotate
2. on every consecutive line near the cursor, check if the line is geometrically identical to the line that we want to
rotate
- if yes, we just push this line to the "other" lines and rotate it along
- if no, then we have a situation where the mouse is near two other lines (e.g. crossing point) and don't want to
rotate
*/
const auto* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return false;
}
BaseRenderer* renderer = positionEvent->GetSender();
if (nullptr == renderer)
{
return false;
}
const PlaneGeometry* rendererWorldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry();
if (nullptr == rendererWorldPlaneGeometry)
{
return false;
}
Point3D position = positionEvent->GetPositionInWorld();
const auto spacing = rendererWorldPlaneGeometry->GetSpacing();
const PlaneGeometry *geometryToBeRotated = nullptr; // this one is under the mouse cursor
const PlaneGeometry *anyOtherGeometry = nullptr; // this is also visible (for calculation of intersection ONLY)
Line3D intersectionLineWithGeometryToBeRotated;
bool hitMultipleLines(false);
m_SNCsToBeRotated.clear();
const ScalarType threshholdDistancePixels = 12.0;
auto allRenderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows();
for (auto renderWindow : allRenderWindows)
{
SliceNavigationController* snc = BaseRenderer::GetInstance(renderWindow)->GetSliceNavigationController();
// If the mouse cursor is in 3D Renderwindow, do not check for intersecting planes.
if (BaseRenderer::Standard3D == BaseRenderer::GetInstance(renderWindow)->GetMapperID())
{
continue;
}
const PlaneGeometry* rendererPlaneGeometry = snc->GetCurrentPlaneGeometry();
if (nullptr == rendererPlaneGeometry)
{
continue; // ignore, we don't see a plane
}
// check if there is an intersection between rendered / clicked geometry and the one being analyzed
Line3D intersectionLine;
if (!rendererWorldPlaneGeometry->IntersectionLine(rendererPlaneGeometry, intersectionLine))
{
continue; // we ignore this plane, it's parallel to our plane
}
// check distance from intersection line
const double distanceFromIntersectionLine = intersectionLine.Distance(position) / spacing[static_cast<int>(snc->GetDefaultViewDirection())];
// far away line, only remember for linked rotation if necessary
if (distanceFromIntersectionLine > threshholdDistancePixels)
{
// we just take the last one, so overwrite each iteration (we just need some crossing point)
// TODO what about multiple crossings? NOW we have undefined behavior / random crossing point is used
anyOtherGeometry = rendererPlaneGeometry;
if (m_LinkPlanes)
{
// if planes are linked, apply rotation to all planes
m_SNCsToBeRotated.push_back(snc);
}
}
else // close to cursor
{
if (nullptr == geometryToBeRotated) // first one close to the cursor
{
geometryToBeRotated = rendererPlaneGeometry;
intersectionLineWithGeometryToBeRotated = intersectionLine;
m_SNCsToBeRotated.push_back(snc);
}
else
{
// compare to the line defined by geometryToBeRotated: if identical, just rotate this otherRenderersRenderPlane
// together with the primary one
// if different, DON'T rotate
if (intersectionLine.IsParallel(intersectionLineWithGeometryToBeRotated)
&& intersectionLine.Distance(intersectionLineWithGeometryToBeRotated.GetPoint1()) < eps)
{
m_SNCsToBeRotated.push_back(snc);
}
else
{
hitMultipleLines = true;
}
}
}
}
bool moveSlices(true);
if (geometryToBeRotated && anyOtherGeometry && rendererWorldPlaneGeometry && !hitMultipleLines)
{
// assure all three are valid, so calculation of center of rotation can be done
moveSlices = false;
}
// question in state machine is: "rotate?"
if (moveSlices) // i.e. NOT rotate
{
return false;
}
else
{
// we have enough information for rotation
// remember where the last cursor position ON THE LINE has been observed
m_LastCursorPosition = intersectionLineWithGeometryToBeRotated.Project(position);
// find center of rotation by intersection with any of the OTHER lines
if (anyOtherGeometry->IntersectionPoint(intersectionLineWithGeometryToBeRotated, m_CenterOfRotation))
{
return true;
}
else
{
return false;
}
}
return false;
}
bool mitk::DisplayActionEventBroadcast::CheckSwivelPossible(const InteractionEvent *interactionEvent)
{
// Decide between moving and rotation: if we're close to the crossing
// point of the planes, moving mode is entered, otherwise
// rotation/swivel mode
const auto* positionEvent = dynamic_cast<const InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return false;
}
BaseRenderer* renderer = positionEvent->GetSender();
if (nullptr == renderer)
{
return false;
}
const Point3D& position = positionEvent->GetPositionInWorld();
m_SNCsToBeRotated.clear();
const PlaneGeometry* clickedGeometry(nullptr);
const PlaneGeometry* otherGeometry1(nullptr);
const PlaneGeometry* otherGeometry2(nullptr);
const ScalarType threshholdDistancePixels = 6.0;
auto allRenderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows();
for (auto renderWindow : allRenderWindows)
{
SliceNavigationController* snc = BaseRenderer::GetInstance(renderWindow)->GetSliceNavigationController();
// If the mouse cursor is in 3D Renderwindow, do not check for intersecting planes.
if (BaseRenderer::Standard3D == BaseRenderer::GetInstance(renderWindow)->GetMapperID())
{
continue;
}
const PlaneGeometry* rendererPlaneGeometry = snc->GetCurrentPlaneGeometry();
if (nullptr == rendererPlaneGeometry)
{
continue; // ignore, we don't see a plane
}
if (snc == renderer->GetSliceNavigationController())
{
clickedGeometry = rendererPlaneGeometry;
m_SNCsToBeRotated.push_back(snc);
}
else
{
if (nullptr == otherGeometry1)
{
otherGeometry1 = rendererPlaneGeometry;
}
else
{
otherGeometry2 = rendererPlaneGeometry;
}
if (m_LinkPlanes)
{
// if planes are linked, apply rotation to all planes
m_SNCsToBeRotated.push_back(snc);
}
}
}
Line3D line;
Point3D point;
if ((nullptr != clickedGeometry) && (nullptr != otherGeometry1) && (nullptr != otherGeometry2)
&& clickedGeometry->IntersectionLine(otherGeometry1, line) && otherGeometry2->IntersectionPoint(line, point))
{
m_CenterOfRotation = point;
if (m_CenterOfRotation.EuclideanDistanceTo(position) < threshholdDistancePixels)
{
return false;
}
else
{
m_ReferenceCursor = positionEvent->GetPointerPositionOnScreen();
// Get main axes of rotation plane and store it for rotation step
m_RotationPlaneNormal = clickedGeometry->GetNormal();
ScalarType xVector[] = { 1.0, 0.0, 0.0 };
ScalarType yVector[] = { 0.0, 1.0, 0.0 };
clickedGeometry->BaseGeometry::IndexToWorld(Vector3D(xVector), m_RotationPlaneXVector);
clickedGeometry->BaseGeometry::IndexToWorld(Vector3D(yVector), m_RotationPlaneYVector);
m_RotationPlaneNormal.Normalize();
m_RotationPlaneXVector.Normalize();
m_RotationPlaneYVector.Normalize();
m_PreviousRotationAxis.Fill(0.0);
m_PreviousRotationAxis[2] = 1.0;
m_PreviousRotationAngle = 0.0;
return true;
}
}
else
{
return false;
}
return false;
}
void mitk::DisplayActionEventBroadcast::Init(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
m_CurrentDisplayCoordinate = m_LastDisplayCoordinate;
positionEvent->GetSender()->DisplayToPlane(m_LastDisplayCoordinate, m_StartCoordinateInMM);
}
void mitk::DisplayActionEventBroadcast::Move(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
BaseRenderer* sender = interactionEvent->GetSender();
Vector2D moveVector = m_LastDisplayCoordinate - positionEvent->GetPointerPositionOnScreen();
if (m_InvertMoveDirection)
{
moveVector *= -1.0;
}
moveVector *= sender->GetScaleFactorMMPerDisplayUnit(); // #TODO: put here?
// store new display coordinate
m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
// propagate move event with computed geometry values
InvokeEvent(DisplayMoveEvent(interactionEvent, moveVector));
}
void mitk::DisplayActionEventBroadcast::SetCrosshair(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
Point3D position = positionEvent->GetPositionInWorld();
// propagate set crosshair event with computed geometry values
InvokeEvent(DisplaySetCrosshairEvent(interactionEvent, position));
}
void mitk::DisplayActionEventBroadcast::Zoom(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
float factor = 1.0;
float distance = 0;
if (m_ZoomDirection == "updown")
{
distance = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
}
else
{
distance = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
}
if (m_InvertZoomDirection)
{
distance *= -1.0;
}
// set zooming speed
if (distance < 0.0)
{
factor = 1.0 / m_ZoomFactor;
}
else if (distance > 0.0)
{
factor = 1.0 * m_ZoomFactor;
}
// store new display coordinates
m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
// propagate zoom event with computed geometry values
InvokeEvent(DisplayZoomEvent(interactionEvent, factor, m_StartCoordinateInMM));
}
void mitk::DisplayActionEventBroadcast::Scroll(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
int sliceDelta = 0;
// scroll direction
if (m_ScrollDirection == "updown")
{
sliceDelta = static_cast<int>(m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1]);
}
else
{
sliceDelta = static_cast<int>(m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0]);
}
if (m_InvertScrollDirection)
{
sliceDelta *= -1;
}
// set how many pixels the mouse has to be moved to scroll one slice
// if the mouse has been moved less than 'm_IndexToSliceModifier', pixels slice ONE slice only
if (sliceDelta > 0 && sliceDelta < m_IndexToSliceModifier)
{
sliceDelta = m_IndexToSliceModifier;
}
else if (sliceDelta < 0 && sliceDelta > -m_IndexToSliceModifier)
{
sliceDelta = -m_IndexToSliceModifier;
}
sliceDelta /= m_IndexToSliceModifier;
// store new display coordinates
m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
// propagate scroll event with computed geometry values
InvokeEvent(DisplayScrollEvent(interactionEvent, sliceDelta, m_AutoRepeat));
}
void mitk::DisplayActionEventBroadcast::ScrollOneUp(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
int sliceDelta = 1;
if (m_InvertScrollDirection)
{
sliceDelta = -1;
}
// propagate scroll event with a single slice delta (increase)
InvokeEvent(DisplayScrollEvent(interactionEvent, sliceDelta, m_AutoRepeat));
}
void mitk::DisplayActionEventBroadcast::ScrollOneDown(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
int sliceDelta = -1;
if (m_InvertScrollDirection)
{
sliceDelta = 1;
}
// propagate scroll event with a single slice delta (decrease)
InvokeEvent(DisplayScrollEvent(interactionEvent, sliceDelta, m_AutoRepeat));
}
void mitk::DisplayActionEventBroadcast::AdjustLevelWindow(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
ScalarType level;
ScalarType window;
if (m_LevelDirection == "leftright")
{
level = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
window = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
}
else
{
level = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
window = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
}
if (m_InvertLevelWindowDirection)
{
level *= -1;
window *= -1;
}
level *= static_cast<ScalarType>(2);
window *= static_cast<ScalarType>(2);
// store new display coordinates
m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
// propagate set level window event with the level and window delta
InvokeEvent(DisplaySetLevelWindowEvent(interactionEvent, level, window));
}
void mitk::DisplayActionEventBroadcast::StartRotation(StateMachineAction* /*stateMachineAction*/, InteractionEvent* /*interactionEvent*/)
{
SetMouseCursor(rotate_cursor_xpm, 0, 0);
}
void mitk::DisplayActionEventBroadcast::EndRotation(StateMachineAction* /*stateMachineAction*/, InteractionEvent* /*interactionEvent*/)
{
ResetMouseCursor();
}
void mitk::DisplayActionEventBroadcast::Rotate(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
Point3D position = positionEvent->GetPositionInWorld();
Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation;
Vector3D toCursor = position - m_CenterOfRotation;
// cross product: | A x B | = |A| * |B| * sin(angle)
Vector3D axisOfRotation;
vnl_vector_fixed<ScalarType, 3> vnlDirection = vnl_cross_3d(toCursor.GetVnlVector(), toProjected.GetVnlVector());
axisOfRotation.SetVnlVector(vnlDirection.as_ref());
// scalar product: A * B = |A| * |B| * cos(angle)
// tan = sin / cos
ScalarType angle = -atan2((double)(axisOfRotation.GetNorm()), (double)(toCursor * toProjected));
angle *= 180.0 / vnl_math::pi;
m_LastCursorPosition = position;
// create RotationOperation and apply to all SNCs that should be rotated
RotationOperation rotationOperation(OpROTATE, m_CenterOfRotation, axisOfRotation, angle);
// iterate the OTHER slice navigation controllers
for (auto iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
{
TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (nullptr == timeGeometry)
{
continue;
}
timeGeometry->ExecuteOperation(&rotationOperation);
(*iter)->SendCreatedWorldGeometryUpdate();
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::DisplayActionEventBroadcast::Swivel(StateMachineAction* /*stateMachineAction*/, InteractionEvent* interactionEvent)
{
const auto* positionEvent = dynamic_cast<InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
{
return;
}
// Determine relative mouse movement projected onto world space
Point2D position = positionEvent->GetPointerPositionOnScreen();
Vector2D relativeCursor = position - m_ReferenceCursor;
Vector3D relativeCursorAxis = m_RotationPlaneXVector * relativeCursor[0] + m_RotationPlaneYVector * relativeCursor[1];
// Determine rotation axis (perpendicular to rotation plane and cursor movement)
Vector3D rotationAxis = itk::CrossProduct(m_RotationPlaneNormal, relativeCursorAxis);
ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0;
// Restore the initial plane pose by undoing the previous rotation operation
RotationOperation op(OpROTATE, m_CenterOfRotation, m_PreviousRotationAxis, -m_PreviousRotationAngle);
SNCVector::iterator iter;
for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
{
if (!(*iter)->GetSliceRotationLocked())
{
TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (nullptr == timeGeometry)
{
continue;
}
timeGeometry->ExecuteOperation(&op);
(*iter)->SendCreatedWorldGeometryUpdate();
}
}
// Apply new rotation operation to all relevant SNCs
RotationOperation op2(OpROTATE, m_CenterOfRotation, rotationAxis, rotationAngle);
for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
{
if (!(*iter)->GetSliceRotationLocked())
{
// Retrieve the TimeGeometry of this SliceNavigationController
TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
if (nullptr == timeGeometry)
{
continue;
}
// Execute the new rotation
timeGeometry->ExecuteOperation(&op2);
// Notify listeners
(*iter)->SendCreatedWorldGeometryUpdate();
}
}
m_PreviousRotationAxis = rotationAxis;
m_PreviousRotationAngle = rotationAngle;
RenderingManager::GetInstance()->RequestUpdateAll();
return;
}
void mitk::DisplayActionEventBroadcast::IncreaseTimeStep(StateMachineAction*, InteractionEvent*)
{
- auto sliceNaviController = RenderingManager::GetInstance()->GetTimeNavigationController();
- auto stepper = sliceNaviController->GetTime();
+ auto* timeNaviController = RenderingManager::GetInstance()->GetTimeNavigationController();
+ auto* stepper = timeNaviController->GetStepper();
stepper->SetAutoRepeat(true);
stepper->Next();
}
void mitk::DisplayActionEventBroadcast::DecreaseTimeStep(StateMachineAction*, InteractionEvent*)
{
- auto sliceNaviController = RenderingManager::GetInstance()->GetTimeNavigationController();
- auto stepper = sliceNaviController->GetTime();
+ auto* timeNaviController = RenderingManager::GetInstance()->GetTimeNavigationController();
+ auto* stepper = timeNaviController->GetStepper();
stepper->SetAutoRepeat(true);
stepper->Previous();
}
bool mitk::DisplayActionEventBroadcast::GetBoolProperty(PropertyList::Pointer propertyList, const char* propertyName, bool defaultValue)
{
std::string valueAsString;
if (!propertyList->GetStringProperty(propertyName, valueAsString))
{
return defaultValue;
}
else
{
if (valueAsString == "true")
{
return true;
}
else
{
return false;
}
}
}
diff --git a/Modules/Core/src/Interactions/mitkDisplayActionEventFunctions.cpp b/Modules/Core/src/Interactions/mitkDisplayActionEventFunctions.cpp
index d2ce34a462..d82e1c125c 100644
--- a/Modules/Core/src/Interactions/mitkDisplayActionEventFunctions.cpp
+++ b/Modules/Core/src/Interactions/mitkDisplayActionEventFunctions.cpp
@@ -1,320 +1,323 @@
/*============================================================================
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 "mitkDisplayActionEventFunctions.h"
// mitk core
-#include "mitkBaseRenderer.h"
-#include "mitkCameraController.h"
-#include "mitkDisplayActionEvents.h"
-#include "mitkInteractionPositionEvent.h"
-#include "mitkLevelWindow.h"
-#include "mitkLevelWindowProperty.h"
-#include "mitkNodePredicateDataType.h"
+#include <mitkBaseRenderer.h>
+#include <mitkCameraController.h>
+#include <mitkDisplayActionEvents.h>
+#include <mitkInteractionPositionEvent.h>
+#include <mitkLevelWindow.h>
+#include <mitkLevelWindowProperty.h>
+#include <mitkNodePredicateDataType.h>
+#include <mitkTimeNavigationController.h>
//////////////////////////////////////////////////////////////////////////
// STANDARD FUNCTIONS
//////////////////////////////////////////////////////////////////////////
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::MoveSenderCameraAction()
{
mitk::StdFunctionCommand::ActionFunction actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplayMoveEvent().CheckEvent(&displayInteractorEvent))
{
const DisplayMoveEvent* displayActionEvent = dynamic_cast<const DisplayMoveEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
sendingRenderer->GetCameraController()->MoveBy(displayActionEvent->GetMoveVector());
RenderingManager::GetInstance()->RequestUpdate(sendingRenderer->GetRenderWindow());
}
};
return actionFunction;
}
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::SetCrosshairAction()
{
auto actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplaySetCrosshairEvent().CheckEvent(&displayInteractorEvent))
{
const DisplaySetCrosshairEvent* displayActionEvent = dynamic_cast<const DisplaySetCrosshairEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
sendingRenderer->GetSliceNavigationController()->SelectSliceByPoint(displayActionEvent->GetPosition());
}
};
return actionFunction;
}
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::ZoomSenderCameraAction()
{
auto actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplayZoomEvent().CheckEvent(&displayInteractorEvent))
{
const DisplayZoomEvent* displayActionEvent = dynamic_cast<const DisplayZoomEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
if (1.0 != displayActionEvent->GetZoomFactor())
{
sendingRenderer->GetCameraController()->Zoom(displayActionEvent->GetZoomFactor(), displayActionEvent->GetStartCoordinate());
RenderingManager::GetInstance()->RequestUpdate(sendingRenderer->GetRenderWindow());
}
}
};
return actionFunction;
}
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::ScrollSliceStepperAction()
{
auto actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplayScrollEvent().CheckEvent(&displayInteractorEvent))
{
const DisplayScrollEvent* displayActionEvent = dynamic_cast<const DisplayScrollEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
mitk::SliceNavigationController* sliceNavigationController = sendingRenderer->GetSliceNavigationController();
if (nullptr == sliceNavigationController)
{
return;
}
if (sliceNavigationController->GetSliceLocked())
{
return;
}
- mitk::Stepper* sliceStepper = sliceNavigationController->GetSlice();
- if (nullptr == sliceStepper)
+ mitk::Stepper* stepper = sliceNavigationController->GetStepper();
+ if (nullptr == stepper)
{
return;
}
// if only a single slice image was loaded, scrolling will affect the time steps
- if (sliceStepper->GetSteps() <= 1)
+ if (stepper->GetSteps() <= 1)
{
- sliceStepper = sliceNavigationController->GetTime();
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ stepper = timeNavigationController->GetStepper();
}
- sliceStepper->SetAutoRepeat(displayActionEvent->GetAutoRepeat());
- sliceStepper->MoveSlice(displayActionEvent->GetSliceDelta());
+ stepper->SetAutoRepeat(displayActionEvent->GetAutoRepeat());
+ stepper->MoveSlice(displayActionEvent->GetSliceDelta());
}
};
return actionFunction;
}
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::SetLevelWindowAction()
{
auto actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplaySetLevelWindowEvent().CheckEvent(&displayInteractorEvent))
{
const DisplaySetLevelWindowEvent* displayActionEvent = dynamic_cast<const DisplaySetLevelWindowEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
// get the the topmost visible image of the sending renderer
DataStorage::Pointer storage = sendingRenderer->GetDataStorage();
DataStorage::SetOfObjects::ConstPointer allImageNodes = storage->GetSubset(NodePredicateDataType::New("Image"));
Point3D worldposition;
const auto* positionEvent = dynamic_cast<const InteractionPositionEvent*>(displayActionEvent->GetInteractionEvent());
sendingRenderer->DisplayToWorld(positionEvent->GetPointerPositionOnScreen(), worldposition);
auto globalCurrentTimePoint = sendingRenderer->GetTime();
DataNode::Pointer node = FindTopmostVisibleNode(allImageNodes, worldposition, globalCurrentTimePoint, sendingRenderer);
if (node.IsNull())
{
return;
}
LevelWindow levelWindow = LevelWindow();
node->GetLevelWindow(levelWindow);
ScalarType level = levelWindow.GetLevel();
ScalarType window = levelWindow.GetWindow();
level += displayActionEvent->GetLevel();
window += displayActionEvent->GetWindow();
levelWindow.SetLevelWindow(level, window);
auto* levelWindowProperty = dynamic_cast<LevelWindowProperty*>(node->GetProperty("levelwindow"));
if (nullptr != levelWindowProperty)
{
levelWindowProperty->SetLevelWindow(levelWindow);
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
};
return actionFunction;
}
//////////////////////////////////////////////////////////////////////////
// SYNCHRONIZED FUNCTIONS
//////////////////////////////////////////////////////////////////////////
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::MoveCameraSynchronizedAction()
{
mitk::StdFunctionCommand::ActionFunction actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplayMoveEvent().CheckEvent(&displayInteractorEvent))
{
const DisplayMoveEvent* displayActionEvent = dynamic_cast<const DisplayMoveEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
auto renderingManager = RenderingManager::GetInstance();
auto allRenderWindows = renderingManager->GetAllRegisteredRenderWindows();
for (auto renderWindow : allRenderWindows)
{
if (BaseRenderer::GetInstance(renderWindow)->GetMapperID() == BaseRenderer::Standard2D)
{
BaseRenderer::GetInstance(renderWindow)->GetCameraController()->MoveBy(displayActionEvent->GetMoveVector());
renderingManager->RequestUpdate(renderWindow);
}
}
}
};
return actionFunction;
}
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::SetCrosshairSynchronizedAction()
{
auto actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplaySetCrosshairEvent().CheckEvent(&displayInteractorEvent))
{
const DisplaySetCrosshairEvent* displayActionEvent = dynamic_cast<const DisplaySetCrosshairEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
auto allRenderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows();
for (auto renderWindow : allRenderWindows)
{
if (BaseRenderer::GetInstance(renderWindow)->GetMapperID() == BaseRenderer::Standard2D)
{
BaseRenderer::GetInstance(renderWindow)->GetSliceNavigationController()->SelectSliceByPoint(displayActionEvent->GetPosition());
}
}
}
};
return actionFunction;
}
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::ZoomCameraSynchronizedAction()
{
auto actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplayZoomEvent().CheckEvent(&displayInteractorEvent))
{
const DisplayZoomEvent* displayActionEvent = dynamic_cast<const DisplayZoomEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
if (1.0 != displayActionEvent->GetZoomFactor())
{
auto renderingManager = RenderingManager::GetInstance();
auto allRenderWindows = renderingManager->GetAllRegisteredRenderWindows();
for (auto renderWindow : allRenderWindows)
{
if (BaseRenderer::GetInstance(renderWindow)->GetMapperID() == BaseRenderer::Standard2D)
{
BaseRenderer* currentRenderer = BaseRenderer::GetInstance(renderWindow);
currentRenderer->GetCameraController()->Zoom(displayActionEvent->GetZoomFactor(), displayActionEvent->GetStartCoordinate());
renderingManager->RequestUpdate(currentRenderer->GetRenderWindow());
}
}
}
}
};
return actionFunction;
}
mitk::StdFunctionCommand::ActionFunction mitk::DisplayActionEventFunctions::ScrollSliceStepperSynchronizedAction()
{
auto actionFunction = [](const itk::EventObject& displayInteractorEvent)
{
if (DisplayScrollEvent().CheckEvent(&displayInteractorEvent))
{
const DisplayScrollEvent* displayActionEvent = dynamic_cast<const DisplayScrollEvent*>(&displayInteractorEvent);
const BaseRenderer::Pointer sendingRenderer = displayActionEvent->GetSender();
if (nullptr == sendingRenderer)
{
return;
}
auto allRenderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows();
for (auto renderWindow : allRenderWindows)
{
if (BaseRenderer::GetInstance(renderWindow)->GetMapperID() == BaseRenderer::Standard2D)
{
SliceNavigationController* sliceNavigationController = BaseRenderer::GetInstance(renderWindow)->GetSliceNavigationController();
if (nullptr == sliceNavigationController)
{
return;
}
if (sliceNavigationController->GetSliceLocked())
{
return;
}
- mitk::Stepper* sliceStepper = sliceNavigationController->GetSlice();
- if (nullptr == sliceStepper)
+ mitk::Stepper* stepper = sliceNavigationController->GetStepper();
+ if (nullptr == stepper)
{
return;
}
// if only a single slice image was loaded, scrolling will affect the time steps
- if (sliceStepper->GetSteps() <= 1)
+ if (stepper->GetSteps() <= 1)
{
- sliceStepper = sliceNavigationController->GetTime();
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ stepper = timeNavigationController->GetStepper();
}
- sliceStepper->SetAutoRepeat(displayActionEvent->GetAutoRepeat());
- sliceStepper->MoveSlice(displayActionEvent->GetSliceDelta());
+ stepper->SetAutoRepeat(displayActionEvent->GetAutoRepeat());
+ stepper->MoveSlice(displayActionEvent->GetSliceDelta());
}
}
}
};
return actionFunction;
}
diff --git a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp
index d0685e131f..f0c4d9b9d3 100644
--- a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp
+++ b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp
@@ -1,776 +1,780 @@
/*============================================================================
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 "mitkBaseRenderer.h"
#include "mitkBaseRendererHelper.h"
#include "mitkMapper.h"
#include "mitkResliceMethodProperty.h"
// Geometries
#include "mitkSlicedGeometry3D.h"
#include "mitkVtkLayerController.h"
#include "mitkInteractionConst.h"
#include "mitkProperties.h"
#include "mitkWeakPointerProperty.h"
// VTK
#include <vtkCamera.h>
#include <vtkLinearTransform.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
namespace mitk
{
itkEventMacroDefinition(RendererResetEvent, itk::AnyEvent);
}
mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::baseRendererMap;
mitk::BaseRenderer *mitk::BaseRenderer::GetInstance(vtkRenderWindow *renWin)
{
for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit)
{
if ((*mapit).first == renWin)
return (*mapit).second;
}
return nullptr;
}
void mitk::BaseRenderer::AddInstance(vtkRenderWindow *renWin, BaseRenderer *baseRenderer)
{
if (renWin == nullptr || baseRenderer == nullptr)
return;
// ensure that no BaseRenderer is managed twice
mitk::BaseRenderer::RemoveInstance(renWin);
baseRendererMap.insert(BaseRendererMapType::value_type(renWin, baseRenderer));
}
void mitk::BaseRenderer::RemoveInstance(vtkRenderWindow *renWin)
{
auto mapit = baseRendererMap.find(renWin);
if (mapit != baseRendererMap.end())
baseRendererMap.erase(mapit);
}
mitk::BaseRenderer *mitk::BaseRenderer::GetByName(const std::string &name)
{
for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit)
{
if ((*mapit).second->m_Name == name)
return (*mapit).second;
}
return nullptr;
}
vtkRenderWindow *mitk::BaseRenderer::GetRenderWindowByName(const std::string &name)
{
for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit)
{
if ((*mapit).second->m_Name == name)
return (*mapit).first;
}
return nullptr;
}
mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::GetSpecificRenderWindows(MapperSlotId mapper)
{
BaseRendererMapType allRenderWindows;
for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit)
{
if (mapper == mapit->second->GetMapperID())
{
allRenderWindows.insert(BaseRendererMapType::value_type(mapit->first, mapit->second));
}
}
return allRenderWindows;
}
mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::GetAll2DRenderWindows()
{
return GetSpecificRenderWindows(BaseRenderer::Standard2D);
}
mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::GetAll3DRenderWindows()
{
return GetSpecificRenderWindows(BaseRenderer::Standard3D);
}
mitk::BaseRenderer::BaseRenderer(const char *name,
vtkRenderWindow *renWin)
: m_RenderWindow(nullptr),
m_VtkRenderer(nullptr),
m_MapperID(StandardMapperSlot::Standard2D),
m_DataStorage(nullptr),
m_LastUpdateTime(0),
m_CameraController(nullptr),
m_CameraRotationController(nullptr),
m_SliceNavigationController(nullptr),
m_WorldTimeGeometry(nullptr),
m_InteractionReferenceGeometry(nullptr),
m_CurrentWorldGeometry(nullptr),
m_CurrentWorldPlaneGeometry(nullptr),
m_Slice(0),
m_TimeStep(),
m_CurrentWorldPlaneGeometryUpdateTime(),
m_TimeStepUpdateTime(),
m_KeepDisplayedRegion(true),
m_ReferenceGeometryAligned(true),
m_CurrentWorldPlaneGeometryData(nullptr),
m_CurrentWorldPlaneGeometryNode(nullptr),
m_CurrentWorldPlaneGeometryTransformTime(0),
m_Name(name),
m_EmptyWorldGeometry(true),
m_NumberOfVisibleLODEnabledMappers(0)
{
m_Bounds[0] = 0;
m_Bounds[1] = 0;
m_Bounds[2] = 0;
m_Bounds[3] = 0;
m_Bounds[4] = 0;
m_Bounds[5] = 0;
if (name != nullptr)
{
m_Name = name;
}
else
{
m_Name = "unnamed renderer";
itkWarningMacro(<< "Created unnamed renderer. Bad for serialization. Please choose a name.");
}
if (renWin != nullptr)
{
m_RenderWindow = renWin;
m_RenderWindow->Register(nullptr);
}
else
{
itkWarningMacro(<< "Created mitkBaseRenderer without vtkRenderWindow present.");
}
// instances.insert( this );
// adding this BaseRenderer to the List of all BaseRenderer
m_BindDispatcherInteractor = new mitk::BindDispatcherInteractor(GetName());
WeakPointerProperty::Pointer rendererProp = WeakPointerProperty::New((itk::Object *)this);
m_CurrentWorldPlaneGeometry = mitk::PlaneGeometry::New();
m_CurrentWorldPlaneGeometryData = mitk::PlaneGeometryData::New();
m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry);
m_CurrentWorldPlaneGeometryNode = mitk::DataNode::New();
m_CurrentWorldPlaneGeometryNode->SetData(m_CurrentWorldPlaneGeometryData);
m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp);
m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000));
m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New());
m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1));
m_CurrentWorldPlaneGeometryTransformTime = m_CurrentWorldPlaneGeometryNode->GetVtkTransform()->GetMTime();
m_SliceNavigationController = mitk::SliceNavigationController::New();
m_SliceNavigationController->SetRenderer(this);
m_SliceNavigationController->ConnectGeometrySendEvent(this);
m_SliceNavigationController->ConnectGeometryUpdateEvent(this);
m_SliceNavigationController->ConnectGeometrySliceEvent(this);
- m_SliceNavigationController->ConnectGeometryTimeEvent(this);
+
+ auto* timeNavigationController = RenderingManager::GetInstance()->GetTimeNavigationController();
+ timeNavigationController->ConnectTimeEvent(this);
m_CameraRotationController = mitk::CameraRotationController::New();
m_CameraRotationController->SetRenderWindow(m_RenderWindow);
m_CameraRotationController->AcquireCamera();
m_CameraController = mitk::CameraController::New();
m_CameraController->SetRenderer(this);
m_VtkRenderer = vtkRenderer::New();
m_VtkRenderer->SetMaximumNumberOfPeels(16);
if (AntiAliasing::FastApproximate == RenderingManager::GetInstance()->GetAntiAliasing())
m_VtkRenderer->UseFXAAOn();
if (nullptr == mitk::VtkLayerController::GetInstance(m_RenderWindow))
mitk::VtkLayerController::AddInstance(m_RenderWindow, m_VtkRenderer);
mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer);
}
mitk::BaseRenderer::~BaseRenderer()
{
if (m_VtkRenderer != nullptr)
{
m_VtkRenderer->Delete();
m_VtkRenderer = nullptr;
}
if (m_CameraController.IsNotNull())
m_CameraController->SetRenderer(nullptr);
mitk::VtkLayerController::RemoveInstance(m_RenderWindow);
RemoveAllLocalStorages();
m_DataStorage = nullptr;
if (m_BindDispatcherInteractor != nullptr)
{
delete m_BindDispatcherInteractor;
}
if (m_RenderWindow != nullptr)
{
m_RenderWindow->Delete();
m_RenderWindow = nullptr;
}
+
+ auto* timeNavigationController = RenderingManager::GetInstance()->GetTimeNavigationController();
+ timeNavigationController->Disconnect(this);
}
void mitk::BaseRenderer::RemoveAllLocalStorages()
{
this->InvokeEvent(RendererResetEvent());
std::list<mitk::BaseLocalStorageHandler *>::iterator it;
for (it = m_RegisteredLocalStorageHandlers.begin(); it != m_RegisteredLocalStorageHandlers.end(); ++it)
(*it)->ClearLocalStorage(this, false);
m_RegisteredLocalStorageHandlers.clear();
}
void mitk::BaseRenderer::RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh)
{
m_RegisteredLocalStorageHandlers.push_back(lsh);
}
void mitk::BaseRenderer::UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh)
{
m_RegisteredLocalStorageHandlers.remove(lsh);
}
void mitk::BaseRenderer::SetDataStorage(DataStorage *storage)
{
if (storage != m_DataStorage && storage != nullptr)
{
m_DataStorage = storage;
m_BindDispatcherInteractor->SetDataStorage(m_DataStorage);
this->Modified();
}
}
mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() const
{
return m_BindDispatcherInteractor->GetDispatcher();
}
void mitk::BaseRenderer::Resize(int w, int h)
{
m_RenderWindow->SetSize(w, h);
}
void mitk::BaseRenderer::InitRenderer(vtkRenderWindow *renderwindow)
{
if (m_RenderWindow != renderwindow)
{
if (m_RenderWindow != nullptr)
{
m_RenderWindow->Delete();
}
m_RenderWindow = renderwindow;
if (m_RenderWindow != nullptr)
{
m_RenderWindow->Register(nullptr);
}
}
RemoveAllLocalStorages();
if (m_CameraController.IsNotNull())
{
m_CameraController->SetRenderer(this);
}
}
void mitk::BaseRenderer::InitSize(int w, int h)
{
m_RenderWindow->SetSize(w, h);
}
void mitk::BaseRenderer::SetWorldTimeGeometry(const mitk::TimeGeometry* geometry)
{
if (m_WorldTimeGeometry == geometry)
{
return;
}
m_WorldTimeGeometry = geometry;
this->UpdateCurrentGeometries();
}
void mitk::BaseRenderer::SetInteractionReferenceGeometry(const TimeGeometry* geometry)
{
if (m_InteractionReferenceGeometry == geometry)
{
return;
}
m_InteractionReferenceGeometry = geometry;
this->UpdateCurrentGeometries();
}
void mitk::BaseRenderer::SetSlice(unsigned int slice)
{
if (m_Slice == slice)
{
return;
}
m_Slice = slice;
this->UpdateCurrentGeometries();
}
void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep)
{
if (m_TimeStep == timeStep)
{
return;
}
m_TimeStep = timeStep;
m_TimeStepUpdateTime.Modified();
this->UpdateCurrentGeometries();
}
mitk::TimeStepType mitk::BaseRenderer::GetTimeStep(const mitk::BaseData* data) const
{
if ((data == nullptr) || (data->IsInitialized() == false))
{
return -1;
}
return data->GetTimeGeometry()->TimePointToTimeStep(GetTime());
}
mitk::ScalarType mitk::BaseRenderer::GetTime() const
{
if (m_WorldTimeGeometry.IsNull())
{
return 0;
}
else
{
ScalarType timeInMS = m_WorldTimeGeometry->TimeStepToTimePoint(GetTimeStep());
if (timeInMS == itk::NumericTraits<mitk::ScalarType>::NonpositiveMin())
return 0;
else
return timeInMS;
}
}
void mitk::BaseRenderer::SetGeometry(const itk::EventObject& geometrySendEvent)
{
const auto* sendEvent = dynamic_cast<const SliceNavigationController::GeometrySendEvent*>(&geometrySendEvent);
if (nullptr == sendEvent)
{
return;
}
SetWorldTimeGeometry(sendEvent->GetTimeGeometry());
}
void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject& geometryUpdateEvent)
{
const auto* updateEvent = dynamic_cast<const SliceNavigationController::GeometryUpdateEvent*>(&geometryUpdateEvent);
if (nullptr == updateEvent)
{
return;
}
if (m_CurrentWorldGeometry.IsNull())
{
return;
}
const auto* slicedWorldGeometry = dynamic_cast<const SlicedGeometry3D*>(m_CurrentWorldGeometry.GetPointer());
if (slicedWorldGeometry)
{
PlaneGeometry* geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice);
SetCurrentWorldPlaneGeometry(geometry2D); // calls Modified()
}
}
void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject& geometrySliceEvent)
{
const auto* sliceEvent = dynamic_cast<const SliceNavigationController::GeometrySliceEvent*>(&geometrySliceEvent);
if (nullptr == sliceEvent)
{
return;
}
this->SetSlice(sliceEvent->GetPos());
}
void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject& geometryTimeEvent)
{
- const auto* timeEvent = dynamic_cast<const SliceNavigationController::GeometryTimeEvent *>(&geometryTimeEvent);
+ const auto* timeEvent = dynamic_cast<const TimeNavigationController::TimeEvent *>(&geometryTimeEvent);
if (nullptr == timeEvent)
{
return;
}
- this->SetTimeStep(timeEvent->GetPos());
+ this->SetTimeStep(timeEvent->GetTimeStep());
}
void mitk::BaseRenderer::SendUpdateSlice()
{
m_CurrentWorldPlaneGeometryUpdateTime.Modified();
}
void mitk::BaseRenderer::SetMapperID(MapperSlotId id)
{
if (m_MapperID != id)
{
bool useDepthPeeling = Standard3D == id;
m_VtkRenderer->SetUseDepthPeeling(useDepthPeeling);
m_VtkRenderer->SetUseDepthPeelingForVolumes(useDepthPeeling);
m_MapperID = id;
this->Modified();
}
}
int* mitk::BaseRenderer::GetSize() const
{
return m_RenderWindow->GetSize();
}
int* mitk::BaseRenderer::GetViewportSize() const
{
return m_VtkRenderer->GetSize();
}
const double* mitk::BaseRenderer::GetBounds() const
{
return m_Bounds;
}
void mitk::BaseRenderer::RequestUpdate()
{
SetConstrainZoomingAndPanning(true);
RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow);
}
void mitk::BaseRenderer::ForceImmediateUpdate()
{
RenderingManager::GetInstance()->ForceImmediateUpdate(m_RenderWindow);
}
unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const
{
return m_NumberOfVisibleLODEnabledMappers;
}
void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController)
{
if (SlicenavigationController == nullptr)
return;
// copy worldgeometry
SlicenavigationController->SetInputWorldTimeGeometry(SlicenavigationController->GetCreatedWorldGeometry());
SlicenavigationController->Update();
// set new
m_SliceNavigationController = SlicenavigationController;
m_SliceNavigationController->SetRenderer(this);
if (m_SliceNavigationController.IsNotNull())
{
m_SliceNavigationController->ConnectGeometrySendEvent(this);
m_SliceNavigationController->ConnectGeometryUpdateEvent(this);
m_SliceNavigationController->ConnectGeometrySliceEvent(this);
- m_SliceNavigationController->ConnectGeometryTimeEvent(this);
}
}
void mitk::BaseRenderer::DisplayToWorld(const Point2D& displayPoint, Point3D& worldIndex) const
{
if (m_MapperID == BaseRenderer::Standard2D)
{
double display[3], * world;
// For the right z-position in display coordinates, take the focal point, convert it to display and use it for
// correct depth.
double* displayCoord;
double cameraFP[4];
// Get camera focal point and position. Convert to display (screen)
// coordinates. We need a depth value for z-buffer.
this->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint(cameraFP);
cameraFP[3] = 0.0;
this->GetVtkRenderer()->SetWorldPoint(cameraFP[0], cameraFP[1], cameraFP[2], cameraFP[3]);
this->GetVtkRenderer()->WorldToDisplay();
displayCoord = this->GetVtkRenderer()->GetDisplayPoint();
// now convert the display point to world coordinates
display[0] = displayPoint[0];
display[1] = displayPoint[1];
display[2] = displayCoord[2];
this->GetVtkRenderer()->SetDisplayPoint(display);
this->GetVtkRenderer()->DisplayToWorld();
world = this->GetVtkRenderer()->GetWorldPoint();
for (int i = 0; i < 3; i++)
{
worldIndex[i] = world[i] / world[3];
}
}
else if (m_MapperID == BaseRenderer::Standard3D)
{
// Seems to be the same code as above, but subclasses may contain different implementations.
PickWorldPoint(displayPoint, worldIndex);
}
return;
}
void mitk::BaseRenderer::DisplayToPlane(const Point2D &displayPoint, Point2D &planePointInMM) const
{
if (m_MapperID == BaseRenderer::Standard2D)
{
Point3D worldPoint;
this->DisplayToWorld(displayPoint, worldPoint);
m_CurrentWorldPlaneGeometry->Map(worldPoint, planePointInMM);
}
else if (m_MapperID == BaseRenderer::Standard3D)
{
MITK_WARN << "No conversion possible with 3D mapper.";
return;
}
return;
}
void mitk::BaseRenderer::WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const
{
double world[4], *display;
world[0] = worldIndex[0];
world[1] = worldIndex[1];
world[2] = worldIndex[2];
world[3] = 1.0;
this->GetVtkRenderer()->SetWorldPoint(world);
this->GetVtkRenderer()->WorldToDisplay();
display = this->GetVtkRenderer()->GetDisplayPoint();
displayPoint[0] = display[0];
displayPoint[1] = display[1];
return;
}
void mitk::BaseRenderer::WorldToView(const mitk::Point3D &worldIndex, mitk::Point2D &viewPoint) const
{
double world[4], *view;
world[0] = worldIndex[0];
world[1] = worldIndex[1];
world[2] = worldIndex[2];
world[3] = 1.0;
this->GetVtkRenderer()->SetWorldPoint(world);
this->GetVtkRenderer()->WorldToView();
view = this->GetVtkRenderer()->GetViewPoint();
this->GetVtkRenderer()->ViewToNormalizedViewport(view[0], view[1], view[2]);
viewPoint[0] = view[0] * this->GetViewportSize()[0];
viewPoint[1] = view[1] * this->GetViewportSize()[1];
return;
}
void mitk::BaseRenderer::PlaneToDisplay(const Point2D &planePointInMM, Point2D &displayPoint) const
{
Point3D worldPoint;
m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint);
this->WorldToDisplay(worldPoint, displayPoint);
return;
}
void mitk::BaseRenderer::PlaneToView(const Point2D &planePointInMM, Point2D &viewPoint) const
{
Point3D worldPoint;
m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint);
this->WorldToView(worldPoint,viewPoint);
return;
}
double mitk::BaseRenderer::GetScaleFactorMMPerDisplayUnit() const
{
if (this->GetMapperID() == BaseRenderer::Standard2D)
{
// GetParallelScale returns half of the height of the render window in mm.
// Divided by the half size of the Display size in pixel givest the mm per pixel.
return this->GetVtkRenderer()->GetActiveCamera()->GetParallelScale() * 2.0 / GetViewportSize()[1];
}
else
return 1.0;
}
mitk::Point2D mitk::BaseRenderer::GetDisplaySizeInMM() const
{
Point2D dispSizeInMM;
dispSizeInMM[0] = GetSizeX() * GetScaleFactorMMPerDisplayUnit();
dispSizeInMM[1] = GetSizeY() * GetScaleFactorMMPerDisplayUnit();
return dispSizeInMM;
}
mitk::Point2D mitk::BaseRenderer::GetViewportSizeInMM() const
{
Point2D dispSizeInMM;
dispSizeInMM[0] = GetViewportSize()[0] * GetScaleFactorMMPerDisplayUnit();
dispSizeInMM[1] = GetViewportSize()[1] * GetScaleFactorMMPerDisplayUnit();
return dispSizeInMM;
}
mitk::Point2D mitk::BaseRenderer::GetOriginInMM() const
{
Point2D originPx;
originPx[0] = m_VtkRenderer->GetOrigin()[0];
originPx[1] = m_VtkRenderer->GetOrigin()[1];
Point2D displayGeometryOriginInMM;
DisplayToPlane(originPx, displayGeometryOriginInMM); // top left of the render window (Origin)
return displayGeometryOriginInMM;
}
void mitk::BaseRenderer::SetConstrainZoomingAndPanning(bool constrain)
{
m_ConstrainZoomingAndPanning = constrain;
if (m_ConstrainZoomingAndPanning)
{
this->GetCameraController()->AdjustCameraToPlane();
}
}
void mitk::BaseRenderer::UpdateCurrentGeometries()
{
m_ReferenceGeometryAligned = true;
if (m_WorldTimeGeometry.IsNull())
{
// simply mark the base renderer as modified
Modified();
return;
}
if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps())
{
m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1;
}
auto slicedWorldGeometry =
dynamic_cast<SlicedGeometry3D*>(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer());
if (slicedWorldGeometry != nullptr)
{
if (m_Slice >= slicedWorldGeometry->GetSlices())
{
m_Slice = slicedWorldGeometry->GetSlices() - 1;
}
SetCurrentWorldGeometry(slicedWorldGeometry);
SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice));
m_ReferenceGeometryAligned = BaseRendererHelper::IsRendererGeometryAlignedWithGeometry(this, m_InteractionReferenceGeometry);
}
}
void mitk::BaseRenderer::SetCurrentWorldPlaneGeometry(const mitk::PlaneGeometry* geometry2d)
{
if (m_CurrentWorldPlaneGeometry == geometry2d)
{
return;
}
m_CurrentWorldPlaneGeometry = geometry2d->Clone();
m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry);
m_CurrentWorldPlaneGeometryUpdateTime.Modified();
Modified();
}
void mitk::BaseRenderer::SetCurrentWorldGeometry(const mitk::BaseGeometry* geometry)
{
if (m_CurrentWorldGeometry == geometry)
{
return;
}
m_CurrentWorldGeometry = geometry;
if (geometry == nullptr)
{
m_Bounds[0] = 0;
m_Bounds[1] = 0;
m_Bounds[2] = 0;
m_Bounds[3] = 0;
m_Bounds[4] = 0;
m_Bounds[5] = 0;
m_EmptyWorldGeometry = true;
return;
}
BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(nullptr);
const BoundingBox::BoundsArrayType& worldBounds = boundingBox->GetBounds();
m_Bounds[0] = worldBounds[0];
m_Bounds[1] = worldBounds[1];
m_Bounds[2] = worldBounds[2];
m_Bounds[3] = worldBounds[3];
m_Bounds[4] = worldBounds[4];
m_Bounds[5] = worldBounds[5];
if (boundingBox->GetDiagonalLength2() <= mitk::eps)
{
m_EmptyWorldGeometry = true;
}
else
{
m_EmptyWorldGeometry = false;
}
}
void mitk::BaseRenderer::PrintSelf(std::ostream &os, itk::Indent indent) const
{
os << indent << " MapperID: " << m_MapperID << std::endl;
os << indent << " Slice: " << m_Slice << std::endl;
os << indent << " TimeStep: " << m_TimeStep << std::endl;
os << indent << " CurrentWorldPlaneGeometry: ";
if (m_CurrentWorldPlaneGeometry.IsNull())
os << "nullptr" << std::endl;
else
m_CurrentWorldPlaneGeometry->Print(os, indent);
os << indent << " CurrentWorldPlaneGeometryUpdateTime: " << m_CurrentWorldPlaneGeometryUpdateTime << std::endl;
os << indent << " CurrentWorldPlaneGeometryTransformTime: " << m_CurrentWorldPlaneGeometryTransformTime << std::endl;
Superclass::PrintSelf(os, indent);
}
diff --git a/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp b/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp
index 8c30df1c50..beafa5cc99 100644
--- a/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp
+++ b/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp
@@ -1,614 +1,594 @@
/*============================================================================
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 "mitkPointSetVtkMapper3D.h"
#include "mitkColorProperty.h"
#include "mitkDataNode.h"
#include "mitkPointSet.h"
#include "mitkProperties.h"
#include "mitkVtkPropRenderer.h"
#include <vtkActor.h>
#include <vtkAppendPolyData.h>
#include <vtkCellArray.h>
#include <vtkConeSource.h>
#include <vtkCubeSource.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataAlgorithm.h>
#include <vtkPolyDataMapper.h>
#include <vtkPropAssembly.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkTubeFilter.h>
#include <vtkVectorText.h>
#include <cstdlib>
#include <mitkPropertyObserver.h>
#include <vtk_glew.h>
const mitk::PointSet *mitk::PointSetVtkMapper3D::GetInput()
{
return static_cast<const mitk::PointSet *>(GetDataNode()->GetData());
}
mitk::PointSetVtkMapper3D::PointSetVtkMapper3D()
: m_vtkSelectedPointList(nullptr),
m_vtkUnselectedPointList(nullptr),
m_VtkSelectedPolyDataMapper(nullptr),
m_VtkUnselectedPolyDataMapper(nullptr),
m_vtkTextList(nullptr),
m_NumberOfSelectedAdded(0),
m_NumberOfUnselectedAdded(0),
m_PointSize(1.0),
m_ContourRadius(0.5)
{
// propassembly
m_PointsAssembly = vtkSmartPointer<vtkPropAssembly>::New();
// creating actors to be able to set transform
m_SelectedActor = vtkSmartPointer<vtkActor>::New();
m_UnselectedActor = vtkSmartPointer<vtkActor>::New();
m_ContourActor = vtkSmartPointer<vtkActor>::New();
}
mitk::PointSetVtkMapper3D::~PointSetVtkMapper3D()
{
}
void mitk::PointSetVtkMapper3D::ReleaseGraphicsResources(vtkWindow *renWin)
{
m_PointsAssembly->ReleaseGraphicsResources(renWin);
m_SelectedActor->ReleaseGraphicsResources(renWin);
m_UnselectedActor->ReleaseGraphicsResources(renWin);
m_ContourActor->ReleaseGraphicsResources(renWin);
}
void mitk::PointSetVtkMapper3D::ReleaseGraphicsResources(mitk::BaseRenderer *renderer)
{
m_PointsAssembly->ReleaseGraphicsResources(renderer->GetRenderWindow());
m_SelectedActor->ReleaseGraphicsResources(renderer->GetRenderWindow());
m_UnselectedActor->ReleaseGraphicsResources(renderer->GetRenderWindow());
m_ContourActor->ReleaseGraphicsResources(renderer->GetRenderWindow());
}
void mitk::PointSetVtkMapper3D::CreateVTKRenderObjects()
{
m_vtkSelectedPointList = vtkSmartPointer<vtkAppendPolyData>::New();
m_vtkUnselectedPointList = vtkSmartPointer<vtkAppendPolyData>::New();
m_PointsAssembly->VisibilityOn();
if (m_PointsAssembly->GetParts()->IsItemPresent(m_SelectedActor))
m_PointsAssembly->RemovePart(m_SelectedActor);
if (m_PointsAssembly->GetParts()->IsItemPresent(m_UnselectedActor))
m_PointsAssembly->RemovePart(m_UnselectedActor);
if (m_PointsAssembly->GetParts()->IsItemPresent(m_ContourActor))
m_PointsAssembly->RemovePart(m_ContourActor);
- // exceptional displaying for PositionTracker -> MouseOrientationTool
- int mapperID;
- bool isInputDevice = false;
- if (this->GetDataNode()->GetBoolProperty("inputdevice", isInputDevice) && isInputDevice)
- {
- if (this->GetDataNode()->GetIntProperty("BaseRendererMapperID", mapperID) && mapperID == BaseRenderer::Standard3D)
- return; // The event for the PositionTracker came from the 3d widget and not needs to be displayed
- }
-
// get and update the PointSet
mitk::PointSet::Pointer input = const_cast<mitk::PointSet *>(this->GetInput());
/* only update the input data, if the property tells us to */
bool update = true;
this->GetDataNode()->GetBoolProperty("updateDataOnRender", update);
if (update == true)
input->Update();
int timestep = this->GetTimestep();
mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet(timestep);
if (itkPointSet.GetPointer() == nullptr)
{
m_PointsAssembly->VisibilityOff();
return;
}
// now fill selected and unselected pointList
// get size of Points in Property
m_PointSize = 2;
mitk::FloatProperty::Pointer pointSizeProp =
dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetProperty("pointsize"));
if (pointSizeProp.IsNotNull())
m_PointSize = pointSizeProp->GetValue();
// get the property for creating a label onto every point only once
bool showLabel = true;
this->GetDataNode()->GetBoolProperty("show label", showLabel);
const char *pointLabel = nullptr;
if (showLabel)
{
if (dynamic_cast<mitk::StringProperty *>(this->GetDataNode()->GetPropertyList()->GetProperty("label")) != nullptr)
pointLabel =
dynamic_cast<mitk::StringProperty *>(this->GetDataNode()->GetPropertyList()->GetProperty("label"))->GetValue();
else
showLabel = false;
}
// whether or not to creat a "contour" - connecting lines between all the points
int nbPoints = itkPointSet->GetPointData()->Size();
bool makeContour = false;
this->GetDataNode()->GetBoolProperty("show contour", makeContour);
bool closeContour = false;
this->GetDataNode()->GetBoolProperty("close contour", closeContour);
int contourPointLimit = 0; // NO contour
if (makeContour)
{
if (closeContour)
contourPointLimit = nbPoints;
else
contourPointLimit = nbPoints - 1;
}
// build list of all positions for later transform in one go
mitk::PointSet::PointsContainer::Iterator pointsIter;
int ptIdx;
m_NumberOfSelectedAdded = 0;
m_NumberOfUnselectedAdded = 0;
vtkSmartPointer<vtkPoints> localPoints = vtkSmartPointer<vtkPoints>::New();
m_WorldPositions = vtkSmartPointer<vtkPoints>::New();
m_PointConnections = vtkSmartPointer<vtkCellArray>::New(); // m_PointConnections between points
for (ptIdx = 0, pointsIter = itkPointSet->GetPoints()->Begin(); pointsIter != itkPointSet->GetPoints()->End();
pointsIter++, ptIdx++)
{
itk::Point<float> currentPoint = pointsIter->Value();
localPoints->InsertPoint(ptIdx, currentPoint[0], currentPoint[1], currentPoint[2]);
if (makeContour && ptIdx < contourPointLimit)
{
vtkIdType cell[2] = {(ptIdx + 1) % nbPoints, ptIdx};
m_PointConnections->InsertNextCell(2, cell);
}
}
vtkSmartPointer<vtkLinearTransform> vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep());
vtktransform->TransformPoints(localPoints, m_WorldPositions);
// create contour
if (makeContour)
{
this->CreateContour(m_WorldPositions, m_PointConnections);
}
// check if the list for the PointDataContainer is the same size as the PointsContainer. Is not, then the points were
// inserted manually and can not be visualized according to the PointData (selected/unselected)
bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size());
// now add an object for each point in data
mitk::PointSet::PointDataContainer::Iterator pointDataIter = itkPointSet->GetPointData()->Begin();
for (ptIdx = 0; ptIdx < nbPoints; ++ptIdx) // pointDataIter moved at end of loop
{
double currentPoint[3];
m_WorldPositions->GetPoint(ptIdx, currentPoint);
vtkSmartPointer<vtkPolyDataAlgorithm> source;
// check for the pointtype in data and decide which geom-object to take and then add to the selected or unselected
// list
int pointType;
if (itkPointSet->GetPointData()->size() == 0 || pointDataBroken)
pointType = mitk::PTUNDEFINED;
else
pointType = pointDataIter.Value().pointSpec;
switch (pointType)
{
case mitk::PTUNDEFINED:
{
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetRadius(m_PointSize / 2.0f);
sphere->SetCenter(currentPoint);
- // sphere->SetCenter(pointsIter.Value()[0],pointsIter.Value()[1],pointsIter.Value()[2]);
-
- // MouseOrientation Tool (PositionTracker)
- if (isInputDevice)
- {
- sphere->SetThetaResolution(10);
- sphere->SetPhiResolution(10);
- }
- else
- {
- sphere->SetThetaResolution(20);
- sphere->SetPhiResolution(20);
- }
+ sphere->SetThetaResolution(20);
+ sphere->SetPhiResolution(20);
source = sphere;
}
break;
case mitk::PTSTART:
{
vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
cube->SetXLength(m_PointSize / 2);
cube->SetYLength(m_PointSize / 2);
cube->SetZLength(m_PointSize / 2);
cube->SetCenter(currentPoint);
source = cube;
}
break;
case mitk::PTCORNER:
{
vtkSmartPointer<vtkConeSource> cone = vtkSmartPointer<vtkConeSource>::New();
cone->SetRadius(m_PointSize / 2.0f);
cone->SetCenter(currentPoint);
cone->SetResolution(20);
source = cone;
}
break;
case mitk::PTEDGE:
{
vtkSmartPointer<vtkCylinderSource> cylinder = vtkSmartPointer<vtkCylinderSource>::New();
cylinder->SetRadius(m_PointSize / 2.0f);
cylinder->SetCenter(currentPoint);
cylinder->SetResolution(20);
source = cylinder;
}
break;
case mitk::PTEND:
{
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetRadius(m_PointSize / 2.0f);
// no SetCenter?? this functionality should be explained!
// otherwise: join with default block!
sphere->SetThetaResolution(20);
sphere->SetPhiResolution(20);
source = sphere;
}
break;
default:
{
vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetRadius(m_PointSize / 2.0f);
sphere->SetCenter(currentPoint);
sphere->SetThetaResolution(20);
sphere->SetPhiResolution(20);
source = sphere;
}
break;
}
if (pointDataIter.Value().selected && !pointDataBroken)
{
m_vtkSelectedPointList->AddInputConnection(source->GetOutputPort());
++m_NumberOfSelectedAdded;
}
else
{
m_vtkUnselectedPointList->AddInputConnection(source->GetOutputPort());
++m_NumberOfUnselectedAdded;
}
if (showLabel)
{
char buffer[20];
std::string l = pointLabel;
if (input->GetSize() > 1)
{
sprintf(buffer, "%d", ptIdx + 1);
l.append(buffer);
}
// Define the text for the label
vtkSmartPointer<vtkVectorText> label = vtkSmartPointer<vtkVectorText>::New();
label->SetText(l.c_str());
//# Set up a transform to move the label to a new position.
vtkSmartPointer<vtkTransform> aLabelTransform = vtkSmartPointer<vtkTransform>::New();
aLabelTransform->Identity();
aLabelTransform->Translate(currentPoint[0] + 2, currentPoint[1] + 2, currentPoint[2]);
aLabelTransform->Scale(5.7, 5.7, 5.7);
//# Move the label to a new position.
vtkSmartPointer<vtkTransformPolyDataFilter> labelTransform = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
labelTransform->SetTransform(aLabelTransform);
labelTransform->SetInputConnection(label->GetOutputPort());
// add it to the wright PointList
if (pointType)
{
m_vtkSelectedPointList->AddInputConnection(labelTransform->GetOutputPort());
++m_NumberOfSelectedAdded;
}
else
{
m_vtkUnselectedPointList->AddInputConnection(labelTransform->GetOutputPort());
++m_NumberOfUnselectedAdded;
}
}
if (pointDataIter != itkPointSet->GetPointData()->End())
pointDataIter++;
} // end FOR
// now according to number of elements added to selected or unselected, build up the rendering pipeline
if (m_NumberOfSelectedAdded > 0)
{
m_VtkSelectedPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_VtkSelectedPolyDataMapper->SetInputConnection(m_vtkSelectedPointList->GetOutputPort());
// create a new instance of the actor
m_SelectedActor = vtkSmartPointer<vtkActor>::New();
m_SelectedActor->SetMapper(m_VtkSelectedPolyDataMapper);
m_PointsAssembly->AddPart(m_SelectedActor);
}
if (m_NumberOfUnselectedAdded > 0)
{
m_VtkUnselectedPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_VtkUnselectedPolyDataMapper->SetInputConnection(m_vtkUnselectedPointList->GetOutputPort());
// create a new instance of the actor
m_UnselectedActor = vtkSmartPointer<vtkActor>::New();
m_UnselectedActor->SetMapper(m_VtkUnselectedPolyDataMapper);
m_PointsAssembly->AddPart(m_UnselectedActor);
}
}
void mitk::PointSetVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if (!visible)
{
m_UnselectedActor->VisibilityOff();
m_SelectedActor->VisibilityOff();
m_ContourActor->VisibilityOff();
return;
}
// create new vtk render objects (e.g. sphere for a point)
BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer);
bool needGenerateData = ls->IsGenerateDataRequired(renderer, this, GetDataNode());
if (!needGenerateData)
{
if (this->GetDataNode()->GetPropertyList()->GetMTime() > ls->GetLastGenerateDataTime() ||
this->GetDataNode()->GetPropertyList(renderer)->GetMTime() > ls->GetLastGenerateDataTime())
{
needGenerateData = true;
}
}
if (needGenerateData)
{
this->CreateVTKRenderObjects();
ls->UpdateGenerateDataTime();
}
this->ApplyAllProperties(renderer, m_ContourActor);
bool showPoints = true;
this->GetDataNode()->GetBoolProperty("show points", showPoints);
m_UnselectedActor->SetVisibility(showPoints);
m_SelectedActor->SetVisibility(showPoints);
if (false && dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetProperty("opacity")) != nullptr)
{
mitk::FloatProperty::Pointer pointOpacity =
dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetProperty("opacity"));
float opacity = pointOpacity->GetValue();
m_ContourActor->GetProperty()->SetOpacity(opacity);
m_UnselectedActor->GetProperty()->SetOpacity(opacity);
m_SelectedActor->GetProperty()->SetOpacity(opacity);
}
bool showContour = false;
this->GetDataNode()->GetBoolProperty("show contour", showContour);
m_ContourActor->SetVisibility(showContour);
}
void mitk::PointSetVtkMapper3D::ResetMapper(BaseRenderer * /*renderer*/)
{
m_PointsAssembly->VisibilityOff();
}
vtkProp *mitk::PointSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/)
{
return m_PointsAssembly;
}
void mitk::PointSetVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/)
{
}
void mitk::PointSetVtkMapper3D::ApplyAllProperties(mitk::BaseRenderer *renderer, vtkActor *actor)
{
Superclass::ApplyColorAndOpacityProperties(renderer, actor);
// check for color props and use it for rendering of selected/unselected points and contour
// due to different params in VTK (double/float) we have to convert!
// vars to convert to
double unselectedColor[4] = {1.0f, 1.0f, 0.0f, 1.0f}; // yellow
double selectedColor[4] = {1.0f, 0.0f, 0.0f, 1.0f}; // red
double contourColor[4] = {1.0f, 0.0f, 0.0f, 1.0f}; // red
// different types for color!!!
mitk::Color tmpColor;
double opacity = 1.0;
// check if there is an unselected property
if (dynamic_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor")) != nullptr)
{
tmpColor = dynamic_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor"))
->GetValue();
unselectedColor[0] = tmpColor[0];
unselectedColor[1] = tmpColor[1];
unselectedColor[2] = tmpColor[2];
unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value
}
else if (dynamic_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("unselectedcolor")) != nullptr)
{
tmpColor =
dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("unselectedcolor"))
->GetValue();
unselectedColor[0] = tmpColor[0];
unselectedColor[1] = tmpColor[1];
unselectedColor[2] = tmpColor[2];
unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value
}
else
{
// check if the node has a color
float unselectedColorTMP[4] = {1.0f, 1.0f, 0.0f, 1.0f}; // yellow
m_DataNode->GetColor(unselectedColorTMP, nullptr);
unselectedColor[0] = unselectedColorTMP[0];
unselectedColor[1] = unselectedColorTMP[1];
unselectedColor[2] = unselectedColorTMP[2];
// unselectedColor[3] stays 1.0f
}
// get selected property
if (dynamic_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) != nullptr)
{
tmpColor =
dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))
->GetValue();
selectedColor[0] = tmpColor[0];
selectedColor[1] = tmpColor[1];
selectedColor[2] = tmpColor[2];
selectedColor[3] = 1.0f;
}
else if (dynamic_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("selectedcolor")) != nullptr)
{
tmpColor =
dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("selectedcolor"))
->GetValue();
selectedColor[0] = tmpColor[0];
selectedColor[1] = tmpColor[1];
selectedColor[2] = tmpColor[2];
selectedColor[3] = 1.0f;
}
// get contour property
if (dynamic_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) != nullptr)
{
tmpColor =
dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))
->GetValue();
contourColor[0] = tmpColor[0];
contourColor[1] = tmpColor[1];
contourColor[2] = tmpColor[2];
contourColor[3] = 1.0f;
}
else if (dynamic_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("contourcolor")) != nullptr)
{
tmpColor =
dynamic_cast<mitk::ColorProperty *>(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("contourcolor"))
->GetValue();
contourColor[0] = tmpColor[0];
contourColor[1] = tmpColor[1];
contourColor[2] = tmpColor[2];
contourColor[3] = 1.0f;
}
if (dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity")) !=
nullptr)
{
mitk::FloatProperty::Pointer pointOpacity =
dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity"));
opacity = pointOpacity->GetValue();
}
else if (dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("opacity")) !=
nullptr)
{
mitk::FloatProperty::Pointer pointOpacity =
dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("opacity"));
opacity = pointOpacity->GetValue();
}
// finished color / opacity fishing!
// check if a contour shall be drawn
bool showContour = false;
this->GetDataNode()->GetBoolProperty("show contour", showContour, renderer);
if (showContour && (m_ContourActor != nullptr))
{
this->CreateContour(m_WorldPositions, m_PointConnections);
m_ContourActor->GetProperty()->SetColor(contourColor);
m_ContourActor->GetProperty()->SetOpacity(opacity);
}
m_SelectedActor->GetProperty()->SetColor(selectedColor);
m_SelectedActor->GetProperty()->SetOpacity(opacity);
m_UnselectedActor->GetProperty()->SetColor(unselectedColor);
m_UnselectedActor->GetProperty()->SetOpacity(opacity);
}
void mitk::PointSetVtkMapper3D::CreateContour(vtkPoints *points, vtkCellArray *m_PointConnections)
{
vtkSmartPointer<vtkAppendPolyData> vtkContourPolyData = vtkSmartPointer<vtkAppendPolyData>::New();
vtkSmartPointer<vtkPolyDataMapper> vtkContourPolyDataMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkPolyData> contour = vtkSmartPointer<vtkPolyData>::New();
contour->SetPoints(points);
contour->SetLines(m_PointConnections);
vtkSmartPointer<vtkTubeFilter> tubeFilter = vtkSmartPointer<vtkTubeFilter>::New();
tubeFilter->SetNumberOfSides(12);
tubeFilter->SetInputData(contour);
// check for property contoursize.
m_ContourRadius = 0.5;
mitk::FloatProperty::Pointer contourSizeProp =
dynamic_cast<mitk::FloatProperty *>(this->GetDataNode()->GetProperty("contoursize"));
if (contourSizeProp.IsNotNull())
m_ContourRadius = contourSizeProp->GetValue();
tubeFilter->SetRadius(m_ContourRadius);
tubeFilter->Update();
// add to pipeline
vtkContourPolyData->AddInputConnection(tubeFilter->GetOutputPort());
vtkContourPolyDataMapper->SetInputConnection(vtkContourPolyData->GetOutputPort());
m_ContourActor->SetMapper(vtkContourPolyDataMapper);
m_PointsAssembly->AddPart(m_ContourActor);
}
void mitk::PointSetVtkMapper3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite)
{
node->AddProperty("line width", mitk::IntProperty::New(2), renderer, overwrite);
node->AddProperty("pointsize", mitk::FloatProperty::New(1.0), renderer, overwrite);
node->AddProperty("selectedcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); // red
node->AddProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite); // yellow
node->AddProperty("opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite);
node->AddProperty("show contour", mitk::BoolProperty::New(false), renderer, overwrite);
node->AddProperty("close contour", mitk::BoolProperty::New(false), renderer, overwrite);
node->AddProperty("contourcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite);
node->AddProperty("contoursize", mitk::FloatProperty::New(0.5), renderer, overwrite);
node->AddProperty("show points", mitk::BoolProperty::New(true), renderer, overwrite);
node->AddProperty("updateDataOnRender", mitk::BoolProperty::New(true), renderer, overwrite);
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
diff --git a/Modules/Core/src/Rendering/mitkVideoRecorder.cpp b/Modules/Core/src/Rendering/mitkVideoRecorder.cpp
index 117946b90f..1de3fcfb9a 100644
--- a/Modules/Core/src/Rendering/mitkVideoRecorder.cpp
+++ b/Modules/Core/src/Rendering/mitkVideoRecorder.cpp
@@ -1,391 +1,409 @@
/*============================================================================
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 <mitkVideoRecorder.h>
#include <mitkBaseRenderer.h>
#include <mitkCoreServices.h>
#include <mitkExceptionMacro.h>
#include <mitkIOUtil.h>
#include <mitkIPreferences.h>
#include <mitkIPreferencesService.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <vtkImageResize.h>
#include <vtkNew.h>
#include <vtkPNGWriter.h>
#include <vtkRenderWindow.h>
#include <vtkWindowToImageFilter.h>
#include <itksys/Process.h>
#include <iomanip>
#include <optional>
#include <sstream>
std::string mitk::VideoRecorder::GetFileExtension(OutputFormat format)
{
switch (format)
{
case OutputFormat::WebM_VP9:
return ".webm";
case OutputFormat::MP4_H264:
return ".mp4";
default:
break;
}
mitkThrow() << "Unknown output format for video recording.";
}
namespace
{
mitk::IPreferences* GetPreferences()
{
auto* preferencesService = mitk::CoreServices::GetPreferencesService();
return preferencesService->GetSystemPreferences()->Node("org.mitk.views.moviemaker");
}
class RecordingSession
{
public:
RecordingSession(vtkRenderWindow* renderWindow, mitk::VideoRecorder::OutputFormat format)
: m_FrameDir(mitk::IOUtil::CreateTemporaryDirectory("MITK_RecordingSession_XXXXXX")),
m_NumberOfFrames(0)
{
m_WindowToImageFilter->SetInput(renderWindow);
if (mitk::VideoRecorder::OutputFormat::MP4_H264 == format)
{
// H.264 only supports image dimensions that are a multiple of 2. Resize if necessary.
auto* size = renderWindow->GetActualSize();
if (size[0] & 1 || size[1] & 1)
{
m_ImageResize->SetInputConnection(m_WindowToImageFilter->GetOutputPort());
m_ImageResize->SetOutputDimensions(size[0] & ~1, size[1] & ~1, -1);
m_ImageResize->SetInterpolate(0);
m_ImageResize->BorderOn();
m_ImageWriter->SetInputConnection(m_ImageResize->GetOutputPort());
return;
}
}
m_ImageWriter->SetInputConnection(m_WindowToImageFilter->GetOutputPort());
}
~RecordingSession()
{
std::error_code errorCode;
std::filesystem::remove_all(m_FrameDir, errorCode);
}
RecordingSession(const RecordingSession&) = delete;
RecordingSession& operator=(const RecordingSession&) = delete;
std::filesystem::path GetFrameDir() const
{
return m_FrameDir;
}
void RecordFrame()
{
m_WindowToImageFilter->Modified();
std::stringstream frameFilename;
frameFilename << std::setw(6) << std::setfill('0') << m_NumberOfFrames << ".png";
const auto framePath = m_FrameDir / frameFilename.str();
m_ImageWriter->SetFileName(framePath.string().c_str());
m_ImageWriter->Write();
++m_NumberOfFrames;
}
private:
std::filesystem::path m_FrameDir;
unsigned int m_NumberOfFrames;
vtkNew<vtkWindowToImageFilter> m_WindowToImageFilter;
vtkNew<vtkImageResize> m_ImageResize;
vtkNew<vtkPNGWriter> m_ImageWriter;
};
}
namespace mitk
{
class VideoRecorder::Impl
{
public:
Impl()
: m_FrameRate(30)
{
}
~Impl() = default;
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
std::filesystem::path GetFFmpegPath() const
{
if (m_FFmpegPath)
return m_FFmpegPath.value();
auto* preferences = GetPreferences();
if (nullptr != preferences)
{
auto ffmpegPath = preferences->Get("ffmpeg", "");
if (!ffmpegPath.empty())
return ffmpegPath;
}
return std::filesystem::path();
}
void SetFFmpegPath(const std::filesystem::path& path)
{
m_FFmpegPath = path;
}
std::filesystem::path GetOutputPath() const
{
return m_OutputPath;
}
void SetOutputPath(const std::filesystem::path& path)
{
m_OutputPath = path;
}
mitk::VideoRecorder::OutputFormat GetOutputFormat() const
{
if (m_OutputFormat)
return m_OutputFormat.value();
auto* preferences = GetPreferences();
if (nullptr != preferences)
return static_cast<OutputFormat>(preferences->GetInt("format", 0));
return OutputFormat::WebM_VP9;
}
void SetOutputFormat(OutputFormat format)
{
m_OutputFormat = format;
}
std::string GetRenderWindowName() const
{
return m_RenderWindowName;
}
void SetRenderWindowName(const std::string& renderWindowName)
{
m_RenderWindowName = renderWindowName;
}
int GetFrameRate() const
{
return m_FrameRate;
}
void SetFrameRate(unsigned int fps)
{
m_FrameRate = fps;
}
bool OnAir() const
{
return nullptr != m_RecordingSession.get();
}
void StartRecording()
{
if (this->OnAir())
mitkThrow() << "Recording session already running.";
auto renderWindowName = this->GetRenderWindowName();
if (renderWindowName.empty())
mitkThrow() << "No render window specified for recording.";
auto* renderWindow = BaseRenderer::GetRenderWindowByName(renderWindowName);
if (nullptr == renderWindow)
mitkThrow() << "\"" << renderWindowName << "\" references unknown render window for recording.";
m_RecordingSession = std::make_unique<RecordingSession>(renderWindow, this->GetOutputFormat());
}
void RecordFrame()
{
if (!this->OnAir())
mitkThrow() << "Cannot record frame. No recording session running.";
m_RecordingSession->RecordFrame();
}
std::string GetFFmpegCommandLine() const
{
bool vp9 = OutputFormat::WebM_VP9 == this->GetOutputFormat();
std::stringstream stream;
- stream << this->GetFFmpegPath()
+ stream << this->GetFFmpegPath() << ' '
<< "-y" << ' '
<< "-r " << std::to_string(this->GetFrameRate()) << ' '
<< "-i %6d.png" << ' '
<< "-c:v " << (vp9 ? "libvpx-vp9" : "libx264") << ' '
<< "-crf " << (vp9 ? "31" : "23") << ' '
<< "-pix_fmt yuv420p" << ' '
<< "-b:v 0" << ' '
<< this->GetOutputPath();
return stream.str();
}
int ExecuteFFmpeg() const
{
auto commandLine = this->GetFFmpegCommandLine();
auto commandLineCStr = commandLine.c_str();
auto workingDirectory = m_RecordingSession->GetFrameDir().string();
auto* ffmpeg = itksysProcess_New();
itksysProcess_SetOption(ffmpeg, itksysProcess_Option_Verbatim, 1);
itksysProcess_SetCommand(ffmpeg, &commandLineCStr);
itksysProcess_SetWorkingDirectory(ffmpeg, workingDirectory.c_str());
itksysProcess_Execute(ffmpeg);
itksysProcess_WaitForExit(ffmpeg, nullptr);
- if (itksysProcess_State_Exited != itksysProcess_GetState(ffmpeg))
+ auto state = itksysProcess_GetState(ffmpeg);
+
+ if (itksysProcess_State_Exited != state)
{
+ std::stringstream message;
+ message << "FFmpeg process did not exit as expected: ";
+
+ if (itksysProcess_State_Error == state)
+ {
+ message << itksysProcess_GetErrorString(ffmpeg);
+ }
+ else if (itksysProcess_State_Exception == state)
+ {
+ message << itksysProcess_GetExceptionString(ffmpeg);
+ }
+
+ message << "\n Command: " << commandLineCStr;
+ message << "\n Working directory: " << workingDirectory.c_str();
+
itksysProcess_Delete(ffmpeg);
- mitkThrow() << "FFmpeg process did not exit as expected.";
+
+ mitkThrow() << message.str();
}
auto exitCode = itksysProcess_GetExitValue(ffmpeg);
itksysProcess_Delete(ffmpeg);
return exitCode;
}
int StopRecording()
{
if (!this->OnAir())
mitkThrow() << "No recording session running.";
if (this->GetFFmpegPath().empty())
mitkThrow() << "Path to FFmpeg not set.";
if (this->GetOutputPath().empty())
mitkThrow() << "Path to output video file not set.";
auto exitCode = this->ExecuteFFmpeg();
m_RecordingSession = nullptr;
return exitCode;
}
private:
std::optional<std::filesystem::path> m_FFmpegPath;
std::filesystem::path m_OutputPath;
std::optional<OutputFormat> m_OutputFormat;
std::string m_RenderWindowName;
unsigned int m_FrameRate;
std::unique_ptr<RecordingSession> m_RecordingSession;
};
}
mitk::VideoRecorder::VideoRecorder()
: m_Impl(std::make_unique<Impl>())
{
}
mitk::VideoRecorder::~VideoRecorder()
{
}
std::filesystem::path mitk::VideoRecorder::GetFFmpegPath() const
{
return m_Impl->GetFFmpegPath();
}
void mitk::VideoRecorder::SetFFmpegPath(const std::filesystem::path& path)
{
m_Impl->SetFFmpegPath(path);
}
std::filesystem::path mitk::VideoRecorder::GetOutputPath() const
{
return m_Impl->GetOutputPath();
}
void mitk::VideoRecorder::SetOutputPath(const std::filesystem::path& path)
{
m_Impl->SetOutputPath(path);
}
mitk::VideoRecorder::OutputFormat mitk::VideoRecorder::GetOutputFormat() const
{
return m_Impl->GetOutputFormat();
}
void mitk::VideoRecorder::SetOutputFormat(OutputFormat format)
{
m_Impl->SetOutputFormat(format);
}
std::string mitk::VideoRecorder::GetRenderWindowName() const
{
return m_Impl->GetRenderWindowName();
}
void mitk::VideoRecorder::SetRenderWindowName(const std::string& renderWindowName)
{
m_Impl->SetRenderWindowName(renderWindowName);
}
int mitk::VideoRecorder::GetFrameRate() const
{
return m_Impl->GetFrameRate();
}
void mitk::VideoRecorder::SetFrameRate(unsigned int fps)
{
m_Impl->SetFrameRate(fps);
}
void mitk::VideoRecorder::StartRecording()
{
m_Impl->StartRecording();
}
void mitk::VideoRecorder::RecordFrame() const
{
m_Impl->RecordFrame();
}
int mitk::VideoRecorder::StopRecording()
{
return m_Impl->StopRecording();
}
diff --git a/Modules/Core/src/Rendering/mitkVtkEventProvider.cpp b/Modules/Core/src/Rendering/mitkVtkEventProvider.cpp
index e75c406175..0ee80799e2 100644
--- a/Modules/Core/src/Rendering/mitkVtkEventProvider.cpp
+++ b/Modules/Core/src/Rendering/mitkVtkEventProvider.cpp
@@ -1,240 +1,240 @@
/*============================================================================
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 "mitkVtkEventProvider.h"
#include "mitkVtkEventAdapter.h"
-#include <mbilog.h>
+#include <mitkLog.h>
#include <vtkCallbackCommand.h>
#include <vtkInteractorStyle.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindowInteractor.h>
#include "mitkInteractionEvent.h"
-#define VTKEVENTPROVIDER_INFO MBI_INFO("mitk.core.vtkeventprovider")
-#define VTKEVENTPROVIDER_WARN MBI_WARN("mitk.core.vtkeventprovider")
-#define VTKEVENTPROVIDER_ERROR MBI_ERROR("mitk.core.vtkeventprovider")
-#define VTKEVENTPROVIDER_DEBUG MBI_DEBUG("mitk.core.vtkeventprovider")
+#define VTKEVENTPROVIDER_INFO MITK_INFO("mitk.core.vtkeventprovider")
+#define VTKEVENTPROVIDER_WARN MITK_WARN("mitk.core.vtkeventprovider")
+#define VTKEVENTPROVIDER_ERROR MITK_ERROR("mitk.core.vtkeventprovider")
+#define VTKEVENTPROVIDER_DEBUG MITK_DEBUG("mitk.core.vtkeventprovider")
namespace mitk
{
vtkStandardNewMacro(vtkEventProvider);
}
//----------------------------------------------------------------------------
mitk::vtkEventProvider::vtkEventProvider()
{
// priority of the observer/command; we want MITK events processed in the very beginning
this->Priority = 99999.99;
// take over the processing of delete and keypress events from the superclass
this->EventCallbackCommand->SetCallback(vtkEventProvider::ProcessEvents);
// Set/Get the passive observer flag. If this is set to true, this
// indicates that this command does not change the state of the
// system in any way. Passive observers are processed first, and
// are not called even when another command has focus.
this->EventCallbackCommand->SetPassiveObserver(1); // get events first
// mouse move
AddInteractionEvent(vtkCommand::MouseMoveEvent);
// mouse press
AddInteractionEvent(vtkCommand::LeftButtonPressEvent);
AddInteractionEvent(vtkCommand::MiddleButtonPressEvent);
AddInteractionEvent(vtkCommand::RightButtonPressEvent);
// mouse release
AddInteractionEvent(vtkCommand::LeftButtonReleaseEvent);
AddInteractionEvent(vtkCommand::MiddleButtonReleaseEvent);
AddInteractionEvent(vtkCommand::RightButtonReleaseEvent);
// wheel event
AddInteractionEvent(vtkCommand::MouseWheelBackwardEvent);
AddInteractionEvent(vtkCommand::MouseWheelForwardEvent);
// key press event
AddInteractionEvent(vtkCommand::KeyPressEvent);
}
mitk::vtkEventProvider::~vtkEventProvider()
{
this->SetInteractor(nullptr);
}
void mitk::vtkEventProvider::SetMitkRenderWindow(mitk::RenderWindow *renWin)
{
m_RenderWindow = renWin;
}
mitk::RenderWindow *mitk::vtkEventProvider::GetRenderWindow()
{
return m_RenderWindow;
}
void mitk::vtkEventProvider::SetEnabled(int enabling)
{
if (!this->Interactor)
{
VTKEVENTPROVIDER_ERROR << "The interactor must be set prior to enabling/disabling widget";
return;
}
if (enabling) //----------------------------------------------------------
{
VTKEVENTPROVIDER_DEBUG << "Enabling widget";
if (this->Enabled) // already enabled, just return
{
return;
}
this->Enabled = 1;
// listen to all event types specified in m_InteractionEventsVector
vtkRenderWindowInteractor *i = this->Interactor;
InteractionEventsVectorType::iterator it;
for (it = m_InteractionEventsVector.begin(); it != m_InteractionEventsVector.end(); ++it)
{
// add observer to interactorStyle
i->GetInteractorStyle()->AddObserver((vtkCommand::EventIds)(*it), this->EventCallbackCommand, this->Priority);
}
this->InvokeEvent(vtkCommand::EnableEvent, nullptr);
}
else // disabling-----------------------------------------------------------
{
VTKEVENTPROVIDER_DEBUG << "Disabling widget";
if (!this->Enabled) // already disabled, just return
{
return;
}
this->Enabled = 0;
// don't listen for events any more
this->Interactor->RemoveObserver(this->EventCallbackCommand);
// this->Interactor->HandleEventLoop = 0;
this->InvokeEvent(vtkCommand::DisableEvent, nullptr);
}
}
//----------------------------------------------------------------------------
// This adds the keypress event observer and the delete event observer
void mitk::vtkEventProvider::SetInteractor(vtkRenderWindowInteractor *i)
{
if (i == this->Interactor)
{
return;
}
// if we already have an Interactor then stop observing it
if (this->Interactor)
this->SetEnabled(0); // disable the old interactor
this->Interactor = i;
this->Modified();
}
//----------------------------------------------------------------------------
void mitk::vtkEventProvider::ProcessEvents(vtkObject *object,
unsigned long event,
void *clientData,
void *vtkNotUsed(callData))
{
auto *self = reinterpret_cast<vtkEventProvider *>(clientData);
vtkRenderWindowInteractor *rwi = static_cast<vtkInteractorStyle *>(object)->GetInteractor();
// base renderer
mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance(self->GetRenderWindow()->GetVtkRenderWindow());
switch (event)
{
// key press
case vtkCommand::KeyPressEvent:
{
VTKEVENTPROVIDER_DEBUG << "key press event";
InteractionEvent::Pointer adaptedEvent =
VtkEventAdapter::AdaptInteractionKeyEvent(baseRenderer, event, rwi).GetPointer();
self->GetRenderWindow()->HandleEvent(adaptedEvent.GetPointer());
break;
}
// mouse events
case vtkCommand::MouseMoveEvent:
{
VTKEVENTPROVIDER_DEBUG << "mouse move event";
InteractionEvent::Pointer adaptedEvent =
VtkEventAdapter::AdaptMouseMoveEvent(baseRenderer, event, rwi).GetPointer();
self->GetRenderWindow()->HandleEvent(adaptedEvent.GetPointer());
break;
}
case vtkCommand::LeftButtonPressEvent:
case vtkCommand::MiddleButtonPressEvent:
case vtkCommand::RightButtonPressEvent:
{
VTKEVENTPROVIDER_DEBUG << "mouse press event";
InteractionEvent::Pointer adaptedEvent =
VtkEventAdapter::AdaptMousePressEvent(baseRenderer, event, rwi).GetPointer();
self->GetRenderWindow()->HandleEvent(adaptedEvent.GetPointer());
break;
}
case vtkCommand::LeftButtonReleaseEvent:
case vtkCommand::MiddleButtonReleaseEvent:
case vtkCommand::RightButtonReleaseEvent:
{
VTKEVENTPROVIDER_DEBUG << "mouse release event";
InteractionEvent::Pointer adaptedEvent =
VtkEventAdapter::AdaptMouseReleaseEvent(baseRenderer, event, rwi).GetPointer();
self->GetRenderWindow()->HandleEvent(adaptedEvent.GetPointer());
break;
}
// mouse WHEEL
case vtkCommand::MouseWheelForwardEvent:
case vtkCommand::MouseWheelBackwardEvent:
{
VTKEVENTPROVIDER_DEBUG << "mouse wheel event";
InteractionEvent::Pointer adaptedEvent =
VtkEventAdapter::AdaptMouseWheelEvent(baseRenderer, event, rwi).GetPointer();
self->GetRenderWindow()->HandleEvent(adaptedEvent.GetPointer());
break;
}
default:
VTKEVENTPROVIDER_INFO << "VTK event not mapped properly.";
break;
}
}
void mitk::vtkEventProvider::RemoveInteractionEvent(unsigned long ievent)
{
InteractionEventsVectorType::iterator it;
if (m_InteractionEventsVector.size() > 0)
{
it = std::find(m_InteractionEventsVector.begin(), m_InteractionEventsVector.end(), ievent);
if (it != m_InteractionEventsVector.end())
{
m_InteractionEventsVector.erase(it);
return;
}
}
}
void mitk::vtkEventProvider::AddInteractionEvent(unsigned long ievent)
{
// Remove event if it already exists
RemoveInteractionEvent(ievent);
m_InteractionEventsVector.push_back(ievent);
}
diff --git a/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp b/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp
index 243003e4d3..deeefdbced 100644
--- a/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp
+++ b/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp
@@ -1,580 +1,580 @@
/*============================================================================
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 "vtkMitkLevelWindowFilter.h"
#include "vtkObjectFactory.h"
#include <vtkColorTransferFunction.h>
#include <vtkImageData.h>
#include <vtkImageIterator.h>
#include <vtkInformation.h>
#include <vtkInformationVector.h>
#include <vtkLookupTable.h>
#include <vtkPiecewiseFunction.h>
#include <vtkStreamingDemandDrivenPipeline.h>
// used for acos etc.
#include <cmath>
// used for PI
#include <itkMath.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
static const double PI = itk::Math::pi;
vtkStandardNewMacro(vtkMitkLevelWindowFilter);
vtkMitkLevelWindowFilter::vtkMitkLevelWindowFilter()
: m_LookupTable(nullptr), m_OpacityFunction(nullptr), m_MinOpacity(0.0), m_MaxOpacity(255.0)
{
// MITK_INFO << "mitk level/window filter uses " << GetNumberOfThreads() << " thread(s)";
}
vtkMitkLevelWindowFilter::~vtkMitkLevelWindowFilter()
{
}
vtkMTimeType vtkMitkLevelWindowFilter::GetMTime()
{
vtkMTimeType mTime = this->vtkObject::GetMTime();
vtkMTimeType time;
if (this->m_LookupTable != nullptr)
{
time = this->m_LookupTable->GetMTime();
mTime = (time > mTime ? time : mTime);
}
return mTime;
}
void vtkMitkLevelWindowFilter::SetLookupTable(vtkScalarsToColors *lookupTable)
{
if (m_LookupTable != lookupTable)
{
m_LookupTable = lookupTable;
this->Modified();
}
}
vtkScalarsToColors *vtkMitkLevelWindowFilter::GetLookupTable()
{
return m_LookupTable;
}
void vtkMitkLevelWindowFilter::SetOpacityPiecewiseFunction(vtkPiecewiseFunction *opacityFunction)
{
if (m_OpacityFunction != opacityFunction)
{
m_OpacityFunction = opacityFunction;
this->Modified();
}
}
// This code was copied from the iil. The template works only for float and double.
// Internal method which should never be used anywhere else and should not be in th header.
// Convert color pixels from (R,G,B) to (H,S,I).
// Reference: "Digital Image Processing, 2nd. edition", R. Gonzalez and R. Woods. Prentice Hall, 2002.
template <class T>
void RGBtoHSI(T *RGB, T *HSI)
{
T R = RGB[0], G = RGB[1], B = RGB[2], nR = (R < 0 ? 0 : (R > 255 ? 255 : R)) / 255,
nG = (G < 0 ? 0 : (G > 255 ? 255 : G)) / 255, nB = (B < 0 ? 0 : (B > 255 ? 255 : B)) / 255,
m = nR < nG ? (nR < nB ? nR : nB) : (nG < nB ? nG : nB),
theta = (T)(std::acos(0.5f * ((nR - nG) + (nR - nB)) / std::sqrt(std::pow(nR - nG, 2) + (nR - nB) * (nG - nB))) *
180 / PI),
sum = nR + nG + nB;
T H = 0, S = 0, I = 0;
if (theta > 0)
H = (nB <= nG) ? theta : 360 - theta;
if (sum > 0)
S = 1 - 3 / sum * m;
I = sum / 3;
HSI[0] = (T)H;
HSI[1] = (T)S;
HSI[2] = (T)I;
}
// This code was copied from the iil. The template works only for float and double.
// Internal method which should never be used anywhere else and should not be in th header.
// Convert color pixels from (H,S,I) to (R,G,B).
template <class T>
void HSItoRGB(T *HSI, T *RGB)
{
T H = (T)HSI[0], S = (T)HSI[1], I = (T)HSI[2], a = I * (1 - S), R = 0, G = 0, B = 0;
if (H < 120)
{
B = a;
R = (T)(I * (1 + S * std::cos(H * PI / 180) / std::cos((60 - H) * PI / 180)));
G = 3 * I - (R + B);
}
else if (H < 240)
{
H -= 120;
R = a;
G = (T)(I * (1 + S * std::cos(H * PI / 180) / std::cos((60 - H) * PI / 180)));
B = 3 * I - (R + G);
}
else
{
H -= 240;
G = a;
B = (T)(I * (1 + S * std::cos(H * PI / 180) / std::cos((60 - H) * PI / 180)));
R = 3 * I - (G + B);
}
R *= 255;
G *= 255;
B *= 255;
RGB[0] = (T)(R < 0 ? 0 : (R > 255 ? 255 : R));
RGB[1] = (T)(G < 0 ? 0 : (G > 255 ? 255 : G));
RGB[2] = (T)(B < 0 ? 0 : (B > 255 ? 255 : B));
}
// Internal method which should never be used anywhere else and should not be in th header.
//----------------------------------------------------------------------------
// This templated function executes the filter for any type of data.
template <class T>
void vtkApplyLookupTableOnRGBA(vtkMitkLevelWindowFilter *self,
vtkImageData *inData,
vtkImageData *outData,
int outExt[6],
double *clippingBounds,
T *)
{
vtkImageIterator<T> inputIt(inData, outExt);
vtkImageIterator<T> outputIt(outData, outExt);
vtkLookupTable *lookupTable;
const int maxC = inData->GetNumberOfScalarComponents();
double tableRange[2];
lookupTable = dynamic_cast<vtkLookupTable *>(self->GetLookupTable());
lookupTable->GetTableRange(tableRange);
// parameters for RGB level window
const double scale = (tableRange[1] - tableRange[0] > 0 ? 255.0 / (tableRange[1] - tableRange[0]) : 0.0);
const double bias = tableRange[0] * scale;
// parameters for opaque level window
const double scaleOpac =
(self->GetMaxOpacity() - self->GetMinOpacity() > 0 ? 255.0 / (self->GetMaxOpacity() - self->GetMinOpacity()) : 0.0);
const double biasOpac = self->GetMinOpacity() * scaleOpac;
int y = outExt[2];
// Loop through output pixels
while (!outputIt.IsAtEnd())
{
T *inputSI = inputIt.BeginSpan();
T *outputSI = outputIt.BeginSpan();
T *outputSIEnd = outputIt.EndSpan();
if (y >= clippingBounds[2] && y < clippingBounds[3])
{
int x = outExt[0];
while (outputSI != outputSIEnd)
{
if (x >= clippingBounds[0] && x < clippingBounds[1])
{
double rgb[3], alpha, hsi[3];
// level/window mechanism for intensity in HSI space
rgb[0] = static_cast<double>(*inputSI);
inputSI++;
rgb[1] = static_cast<double>(*inputSI);
inputSI++;
rgb[2] = static_cast<double>(*inputSI);
inputSI++;
RGBtoHSI<double>(rgb, hsi);
hsi[2] = hsi[2] * 255.0 * scale - bias;
hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2]));
hsi[2] /= 255.0;
HSItoRGB<double>(hsi, rgb);
*outputSI = static_cast<T>(rgb[0]);
outputSI++;
*outputSI = static_cast<T>(rgb[1]);
outputSI++;
*outputSI = static_cast<T>(rgb[2]);
outputSI++;
unsigned char finalAlpha = 255;
// RGBA case
if (maxC >= 4)
{
// level/window mechanism for opacity
alpha = static_cast<double>(*inputSI);
inputSI++;
alpha = alpha * scaleOpac - biasOpac;
if (alpha > 255.0)
{
alpha = 255.0;
}
else if (alpha < 0.0)
{
alpha = 0.0;
}
finalAlpha = static_cast<unsigned char>(alpha);
for (int c = 4; c < maxC; c++)
inputSI++;
}
*outputSI = static_cast<T>(finalAlpha);
outputSI++;
}
else
{
inputSI += maxC;
*outputSI = 0;
outputSI++;
*outputSI = 0;
outputSI++;
*outputSI = 0;
outputSI++;
*outputSI = 0;
outputSI++;
}
x++;
}
}
else
{
while (outputSI != outputSIEnd)
{
*outputSI = 0;
outputSI++;
*outputSI = 0;
outputSI++;
*outputSI = 0;
outputSI++;
*outputSI = 0;
outputSI++;
}
}
inputIt.NextSpan();
outputIt.NextSpan();
y++;
}
}
// Internal method which should never be used anywhere else and should not be in th header.
//----------------------------------------------------------------------------
// This templated function executes the filter for any type of data.
template <class T>
void vtkApplyLookupTableOnScalarsFast(
vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], T *)
{
vtkImageIterator<T> inputIt(inData, outExt);
vtkImageIterator<unsigned char> outputIt(outData, outExt);
double tableRange[2];
// access vtkLookupTable
auto *lookupTable = dynamic_cast<vtkLookupTable *>(self->GetLookupTable());
lookupTable->GetTableRange(tableRange);
// access elements of the vtkLookupTable
auto *realLookupTable = lookupTable->GetPointer(0);
size_t maxIndex = lookupTable->GetNumberOfColors() - 1;
const float scale = (tableRange[1] - tableRange[0] > 0 ? (maxIndex + 1) / (tableRange[1] - tableRange[0]) : 0.0);
// ensuring that starting point is zero
float bias = -tableRange[0] * scale;
// due to later conversion to int for rounding
bias += 0.5f;
// Loop through output pixels
while (!outputIt.IsAtEnd())
{
unsigned char *outputSI = outputIt.BeginSpan();
unsigned char *outputSIEnd = outputIt.EndSpan();
T *inputSI = inputIt.BeginSpan();
while (outputSI != outputSIEnd)
{
// map to an index
auto idx = std::min(static_cast<size_t>(std::max(0, static_cast<int>(*inputSI * scale + bias))), maxIndex) * 4;
memcpy(outputSI, &realLookupTable[idx], 4);
inputSI++;
outputSI += 4;
}
inputIt.NextSpan();
outputIt.NextSpan();
}
}
// Internal method which should never be used anywhere else and should not be in th header.
//----------------------------------------------------------------------------
// This templated function executes the filter for any type of data.
template <class T>
void vtkApplyLookupTableOnScalars(vtkMitkLevelWindowFilter *self,
vtkImageData *inData,
vtkImageData *outData,
int outExt[6],
double *clippingBounds,
T *)
{
vtkImageIterator<T> inputIt(inData, outExt);
vtkImageIterator<unsigned char> outputIt(outData, outExt);
vtkScalarsToColors *lookupTable = self->GetLookupTable();
int y = outExt[2];
// Loop through output pixels
while (!outputIt.IsAtEnd())
{
unsigned char *outputSI = outputIt.BeginSpan();
const unsigned char * const outputSIEnd = outputIt.EndSpan();
// do we iterate over the inner vertical clipping bounds
if (y >= clippingBounds[2] && y < clippingBounds[3])
{
T *inputSI = inputIt.BeginSpan();
int x = outExt[0];
while (outputSI != outputSIEnd)
{
// is this pixel within horizontal clipping bounds
if (x >= clippingBounds[0] && x < clippingBounds[1])
{
// fetching original value
auto grayValue = static_cast<double>(*inputSI);
// applying lookuptable
memcpy(outputSI, lookupTable->MapValue(grayValue), 4);
}
else
{
// outer horizontal clipping bounds - write a transparent RGBA pixel as a single int
memset(outputSI, 0, 4);
}
inputSI++;
outputSI += 4;
x++;
}
}
else
{
// outer vertical clipping bounds - write a transparent RGBA line as ints
while (outputSI != outputSIEnd)
{
*reinterpret_cast<int *>(outputSI) = 0;
outputSI += 4;
}
}
inputIt.NextSpan();
outputIt.NextSpan();
y++;
}
}
// Internal method which should never be used anywhere else and should not be in th header.
//----------------------------------------------------------------------------
// This templated function executes the filter for any type of data.
template <class T>
void vtkApplyLookupTableOnScalarsCTF(vtkMitkLevelWindowFilter *self,
vtkImageData *inData,
vtkImageData *outData,
int outExt[6],
double *clippingBounds,
T *)
{
vtkImageIterator<T> inputIt(inData, outExt);
vtkImageIterator<unsigned char> outputIt(outData, outExt);
auto *lookupTable = dynamic_cast<vtkColorTransferFunction *>(self->GetLookupTable());
vtkPiecewiseFunction *opacityFunction = self->GetOpacityPiecewiseFunction();
int y = outExt[2];
// Loop through output pixels
while (!outputIt.IsAtEnd())
{
unsigned char *outputSI = outputIt.BeginSpan();
unsigned char *outputSIEnd = outputIt.EndSpan();
// do we iterate over the inner vertical clipping bounds
if (y >= clippingBounds[2] && y < clippingBounds[3])
{
T *inputSI = inputIt.BeginSpan();
int x = outExt[0];
while (outputSI != outputSIEnd)
{
// is this pixel within horizontal clipping bounds
if (x >= clippingBounds[0] && x < clippingBounds[1])
{
// fetching original value
auto grayValue = static_cast<double>(*inputSI);
// applying directly colortransferfunction
// because vtkColorTransferFunction::MapValue is not threadsafe
double rgba[4];
lookupTable->GetColor(grayValue, rgba); // RGB mapping
rgba[3] = 1.0;
if (opacityFunction)
rgba[3] = opacityFunction->GetValue(grayValue); // Alpha mapping
for (int i = 0; i < 4; ++i)
{
outputSI[i] = static_cast<unsigned char>(255.0 * rgba[i] + 0.5);
}
}
else
{
// outer horizontal clipping bounds - write a transparent RGBA pixel as a single int
*reinterpret_cast<int *>(outputSI) = 0;
}
inputSI++;
outputSI += 4;
x++;
}
}
else
{
// outer vertical clipping bounds - write a transparent RGBA line as ints
while (outputSI != outputSIEnd)
{
*reinterpret_cast<int *>(outputSI) = 0;
outputSI += 4;
}
}
inputIt.NextSpan();
outputIt.NextSpan();
y++;
}
}
int vtkMitkLevelWindowFilter::RequestInformation(vtkInformation *request,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// do nothing except copy scalar type info
this->CopyInputArrayAttributesToOutput(request, inputVector, outputVector);
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 4);
return 1;
}
// Method to run the filter in different threads.
void vtkMitkLevelWindowFilter::ThreadedExecute(vtkImageData *inData, vtkImageData *outData, int extent[6], int /*id*/)
{
if (inData->GetNumberOfScalarComponents() > 2)
{
switch (inData->GetScalarType())
{
vtkTemplateMacro(
vtkApplyLookupTableOnRGBA(this, inData, outData, extent, m_ClippingBounds, static_cast<VTK_TT *>(nullptr)));
default:
vtkErrorMacro(<< "Execute: Unknown ScalarType");
return;
}
}
else
{
bool dontClip = extent[2] >= m_ClippingBounds[2] && extent[3] <= m_ClippingBounds[3] &&
extent[0] >= m_ClippingBounds[0] && extent[1] <= m_ClippingBounds[1];
if (this->GetLookupTable())
this->GetLookupTable()->Build();
auto *vlt = dynamic_cast<vtkLookupTable *>(this->GetLookupTable());
auto *ctf = dynamic_cast<vtkColorTransferFunction *>(this->GetLookupTable());
bool linearLookupTable = vlt && vlt->GetScale() == VTK_SCALE_LINEAR;
bool useFast = dontClip && linearLookupTable;
if (ctf)
{
switch (inData->GetScalarType())
{
vtkTemplateMacro(vtkApplyLookupTableOnScalarsCTF(
this, inData, outData, extent, m_ClippingBounds, static_cast<VTK_TT *>(nullptr)));
default:
vtkErrorMacro(<< "Execute: Unknown ScalarType");
return;
}
}
else if (useFast)
{
switch (inData->GetScalarType())
{
vtkTemplateMacro(
vtkApplyLookupTableOnScalarsFast(this, inData, outData, extent, static_cast<VTK_TT *>(nullptr)));
default:
vtkErrorMacro(<< "Execute: Unknown ScalarType");
return;
}
}
else
{
switch (inData->GetScalarType())
{
vtkTemplateMacro(vtkApplyLookupTableOnScalars(
this, inData, outData, extent, m_ClippingBounds, static_cast<VTK_TT *>(nullptr)));
default:
vtkErrorMacro(<< "Execute: Unknown ScalarType");
return;
}
}
}
}
// void vtkMitkLevelWindowFilter::ExecuteInformation(
// vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData))
//{
//}
void vtkMitkLevelWindowFilter::SetMinOpacity(double minOpacity)
{
m_MinOpacity = minOpacity;
}
inline double vtkMitkLevelWindowFilter::GetMinOpacity() const
{
return m_MinOpacity;
}
void vtkMitkLevelWindowFilter::SetMaxOpacity(double maxOpacity)
{
m_MaxOpacity = maxOpacity;
}
inline double vtkMitkLevelWindowFilter::GetMaxOpacity() const
{
return m_MaxOpacity;
}
void vtkMitkLevelWindowFilter::SetClippingBounds(double *bounds) // TODO does double[4] work??
{
for (unsigned int i = 0; i < 4; ++i)
m_ClippingBounds[i] = bounds[i];
}
diff --git a/Modules/Core/test/mitkBaseGeometryTest.cpp b/Modules/Core/test/mitkBaseGeometryTest.cpp
index dad9c06c3a..4818e69c58 100644
--- a/Modules/Core/test/mitkBaseGeometryTest.cpp
+++ b/Modules/Core/test/mitkBaseGeometryTest.cpp
@@ -1,1680 +1,1680 @@
/*============================================================================
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 <mitkTestingConfig.h>
#include <MitkCoreExports.h>
#include <mitkBaseGeometry.h>
#include <mitkCommon.h>
#include <mitkOperationActor.h>
#include <itkBoundingBox.h>
#include <itkIndex.h>
#include <itkQuaternionRigidTransform.h>
#include <itkScalableAffineTransform.h>
#include <mitkVector.h>
#include <vtkMatrix4x4.h>
#include <vtkMatrixToLinearTransform.h>
#include <mitkImageCast.h>
#include <mitkInteractionConst.h>
#include <mitkMatrixConvert.h>
#include <mitkRotationOperation.h>
#include <mitkScaleOperation.h>
#include <mitkNodePredicateGeometry.h>
class vtkMatrix4x4;
class vtkMatrixToLinearTransform;
class vtkLinearTransform;
typedef itk::BoundingBox<unsigned long, 3, mitk::ScalarType> BoundingBox;
typedef itk::BoundingBox<unsigned long, 3, mitk::ScalarType> BoundingBoxType;
typedef BoundingBoxType::BoundsArrayType BoundsArrayType;
typedef BoundingBoxType::Pointer BoundingBoxPointer;
// Dummy instance of abstract base class
class DummyTestClass : public mitk::BaseGeometry
{
public:
DummyTestClass(){};
DummyTestClass(const DummyTestClass &other) : BaseGeometry(other){};
~DummyTestClass() override{};
mitkClassMacro(DummyTestClass, mitk::BaseGeometry);
itkNewMacro(Self);
mitkNewMacro1Param(Self, const Self &);
itk::LightObject::Pointer InternalClone() const override
{
Self::Pointer newGeometry = new Self(*this);
newGeometry->UnRegister();
return newGeometry.GetPointer();
}
protected:
void PrintSelf(std::ostream & /*os*/, itk::Indent /*indent*/) const override{};
//##Documentation
//## @brief Pre- and Post-functions are empty in BaseGeometry
//##
//## These virtual functions allow for a different beahiour in subclasses.
//## Do implement them in every subclass of BaseGeometry. If not needed, use {}.
//## If this class is inherited from a subclass of BaseGeometry, call {Superclass::Pre...();};, example:
// SlicedGeometry3D class
void PreSetSpacing(const mitk::Vector3D &/*aSpacing*/) override{};
};
class mitkBaseGeometryTestSuite : public mitk::TestFixture
{
// List of Tests
CPPUNIT_TEST_SUITE(mitkBaseGeometryTestSuite);
// Constructor
MITK_TEST(TestConstructors);
MITK_TEST(TestInitialize);
// Set
MITK_TEST(TestSetOrigin);
MITK_TEST(TestSetBounds);
MITK_TEST(TestSetFloatBounds);
MITK_TEST(TestSetFloatBoundsDouble);
MITK_TEST(TestSetFrameOfReferenceID);
MITK_TEST(TestSetIndexToWorldTransform);
MITK_TEST(TestSetIndexToWorldTransformWithoutChangingSpacing);
MITK_TEST(TestSetIndexToWorldTransform_WithPointerToSameTransform);
MITK_TEST(TestSetSpacing);
MITK_TEST(TestTransferItkToVtkTransform);
MITK_TEST(TestSetIndexToWorldTransformByVtkMatrix);
MITK_TEST(TestSetIdentity);
MITK_TEST(TestSetImageGeometry);
// Equal
MITK_TEST(Equal_CloneAndOriginal_ReturnsTrue);
MITK_TEST(Equal_DifferentOrigin_ReturnsFalse);
MITK_TEST(Equal_DifferentIndexToWorldTransform_ReturnsFalse);
MITK_TEST(Equal_DifferentSpacing_ReturnsFalse);
MITK_TEST(Equal_InputIsNull_ReturnsFalse);
MITK_TEST(Equal_DifferentBoundingBox_ReturnsFalse);
MITK_TEST(Equal_Transforms_MinorDifferences_And_Eps);
// other Functions
MITK_TEST(TestComposeTransform);
MITK_TEST(TestComposeVtkMatrix);
MITK_TEST(TestTranslate);
MITK_TEST(TestIndexToWorld);
MITK_TEST(TestExecuteOperation);
MITK_TEST(TestCalculateBoundingBoxRelToTransform);
// MITK_TEST(TestSetTimeBounds);
MITK_TEST(TestIs2DConvertable);
MITK_TEST(TestGetCornerPoint);
MITK_TEST(TestExtentInMM);
MITK_TEST(TestGetAxisVector);
MITK_TEST(TestGetCenter);
MITK_TEST(TestGetDiagonalLength);
MITK_TEST(TestGetExtent);
MITK_TEST(TestIsInside);
MITK_TEST(TestGetMatrixColumn);
// test IsSubGeometry
MITK_TEST(IsSubGeometry_Spacing);
MITK_TEST(IsSubGeometry_TransformMatrix);
MITK_TEST(IsSubGeometry_Bounds_Image);
MITK_TEST(IsSubGeometry_Bounds_NoneImage);
MITK_TEST(IsSubGeometry_Grid_Image);
MITK_TEST(IsSubGeometry_Grid_NoneImage);
MITK_TEST(IsSubGeometry_Bounds_Oblique_Image);
MITK_TEST(IsSubGeometry_Bounds_Oblique_NoneImage);
MITK_TEST(IsSubGeometry_Grid_Oblique_Image);
MITK_TEST(IsSubGeometry_Grid_Oblique_NoneImage);
CPPUNIT_TEST_SUITE_END();
// Used Variables
private:
mitk::Point3D aPoint;
float aFloatSpacing[3];
mitk::Vector3D aSpacing;
mitk::AffineTransform3D::Pointer aTransform;
BoundingBoxPointer aBoundingBox;
mitk::AffineTransform3D::MatrixType aMatrix;
mitk::Point3D anotherPoint;
mitk::Vector3D anotherSpacing;
BoundingBoxPointer anotherBoundingBox;
BoundingBoxPointer aThirdBoundingBox;
mitk::AffineTransform3D::Pointer anotherTransform;
mitk::AffineTransform3D::Pointer aThirdTransform;
mitk::AffineTransform3D::MatrixType anotherMatrix;
mitk::AffineTransform3D::MatrixType aThirdMatrix;
DummyTestClass::Pointer aDummyGeometry;
DummyTestClass::Pointer anotherDummyGeometry;
DummyTestClass::Pointer aDummyGeometryOblique;
public:
// Set up for variables
void setUp() override
{
mitk::FillVector3D(aFloatSpacing, 1, 1, 1);
mitk::FillVector3D(aSpacing, 1, 1, 1);
mitk::FillVector3D(aPoint, 0, 0, 0);
// Transform
aTransform = mitk::AffineTransform3D::New();
aTransform->SetIdentity();
aMatrix.SetIdentity();
anotherTransform = mitk::AffineTransform3D::New();
anotherMatrix.SetIdentity();
anotherMatrix(1, 1) = 2;
anotherTransform->SetMatrix(anotherMatrix);
aThirdTransform = mitk::AffineTransform3D::New();
aThirdMatrix.SetIdentity();
aThirdMatrix(1, 1) = 7;
aThirdTransform->SetMatrix(aThirdMatrix);
// Bounding Box
float bounds[6] = { 0, 1, 0, 1, 0, 1 };
mitk::BoundingBox::BoundsArrayType b;
const float* input = bounds;
int j = 0;
for (mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); j < 6; ++j)
*it++ = (mitk::ScalarType) * input++;
aBoundingBox = BoundingBoxType::New();
BoundingBoxType::PointsContainer::Pointer pointscontainer = BoundingBoxType::PointsContainer::New();
BoundingBoxType::PointType p;
BoundingBoxType::PointIdentifier pointid;
for (pointid = 0; pointid < 2; ++pointid)
{
unsigned int i;
for (i = 0; i < 3; ++i)
{
p[i] = bounds[2 * i + pointid];
}
pointscontainer->InsertElement(pointid, p);
}
aBoundingBox->SetPoints(pointscontainer);
aBoundingBox->ComputeBoundingBox();
anotherBoundingBox = BoundingBoxType::New();
p[0] = 11;
p[1] = 12;
p[2] = 13;
pointscontainer->InsertElement(1, p);
anotherBoundingBox->SetPoints(pointscontainer);
anotherBoundingBox->ComputeBoundingBox();
aThirdBoundingBox = BoundingBoxType::New();
p[0] = 22;
p[1] = 23;
p[2] = 24;
pointscontainer->InsertElement(1, p);
aThirdBoundingBox->SetPoints(pointscontainer);
aThirdBoundingBox->ComputeBoundingBox();
mitk::FillVector3D(anotherPoint, 2, 3, 4);
mitk::FillVector3D(anotherSpacing, 5, 6.5, 7);
aDummyGeometry = DummyTestClass::New();
aDummyGeometry->Initialize();
anotherDummyGeometry = aDummyGeometry->Clone();
aDummyGeometryOblique = DummyTestClass::New();
aDummyGeometryOblique->Initialize();
auto newBounds = aDummyGeometryOblique->GetBounds();
newBounds[0] = 0;
newBounds[1] = 5;
newBounds[2] = 10;
newBounds[3] = 20;
newBounds[4] = 30;
newBounds[5] = 40;
aDummyGeometryOblique->SetBounds(newBounds);
aDummyGeometryOblique->GetMatrixColumn(0);
auto obliqueTransform = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::OutputVectorType rotationAxis(0.);
rotationAxis[1] = 1.;
obliqueTransform->Rotate3D(rotationAxis, 0.6);
mitk::AffineTransform3D::OutputVectorType translation;
translation[0] = 100.;
translation[1] = -50.;
translation[2] = -150.;
obliqueTransform->SetTranslation(translation);
aDummyGeometryOblique->SetIndexToWorldTransform(obliqueTransform);
}
void tearDown() override
{
aDummyGeometry = nullptr;
anotherDummyGeometry = nullptr;
}
// Test functions
void TestSetOrigin()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetOrigin(anotherPoint);
CPPUNIT_ASSERT(mitk::Equal(anotherPoint, dummy->GetOrigin()));
// undo changes, new and changed object need to be the same!
dummy->SetOrigin(aPoint);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "TestSetOrigin");
}
void TestSetImageGeometry()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetImageGeometry(true);
CPPUNIT_ASSERT(dummy->GetImageGeometry());
// undo changes, new and changed object need to be the same!
dummy->SetImageGeometry(false);
CPPUNIT_ASSERT(dummy->GetImageGeometry() == false);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "TestSetImageGeometry");
}
void TestSetFloatBounds()
{
float bounds[6] = {0, 11, 0, 12, 0, 13};
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetFloatBounds(bounds);
MITK_ASSERT_EQUAL(BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "BoundingBox equality");
// Wrong bounds, test needs to fail
bounds[1] = 7;
dummy->SetFloatBounds(bounds);
MITK_ASSERT_NOT_EQUAL(
BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "BoundingBox not equal");
// undo changes, new and changed object need to be the same!
float originalBounds[6] = {0, 1, 0, 1, 0, 1};
dummy->SetFloatBounds(originalBounds);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Undo and equal");
}
void TestSetBounds()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetBounds(anotherBoundingBox->GetBounds());
MITK_ASSERT_EQUAL(BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Setting bounds");
// Test needs to fail now
dummy->SetBounds(aThirdBoundingBox->GetBounds());
MITK_ASSERT_NOT_EQUAL(
BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Setting unequal bounds");
// undo changes, new and changed object need to be the same!
dummy->SetBounds(aBoundingBox->GetBounds());
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Undo set bounds");
}
void TestSetFloatBoundsDouble()
{
double bounds[6] = {0, 11, 0, 12, 0, 13};
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetFloatBounds(bounds);
MITK_ASSERT_EQUAL(BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Float bounds");
// Test needs to fail now
bounds[3] = 7;
dummy->SetFloatBounds(bounds);
MITK_ASSERT_NOT_EQUAL(
BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Float bounds unequal");
// undo changes, new and changed object need to be the same!
double originalBounds[6] = {0, 1, 0, 1, 0, 1};
dummy->SetFloatBounds(originalBounds);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Undo set float bounds");
}
void TestSetFrameOfReferenceID()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetFrameOfReferenceID(5);
CPPUNIT_ASSERT(dummy->GetFrameOfReferenceID() == 5);
// undo changes, new and changed object need to be the same!
dummy->SetFrameOfReferenceID(0);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Undo set frame of reference");
}
void TestSetIndexToWorldTransform()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(anotherTransform);
MITK_ASSERT_EQUAL(anotherTransform,
mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()),
"Compare IndexToWorldTransform 1");
// Test needs to fail now
dummy->SetIndexToWorldTransform(aThirdTransform);
MITK_ASSERT_NOT_EQUAL(anotherTransform,
mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()),
"Compare IndexToWorldTransform 2");
// undo changes, new and changed object need to be the same!
dummy->SetIndexToWorldTransform(aTransform);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Compare IndexToWorldTransform 3");
}
void TestSetIndexToWorldTransformWithoutChangingSpacing()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransformWithoutChangingSpacing(anotherTransform);
CPPUNIT_ASSERT(mitk::Equal(aSpacing, dummy->GetSpacing(), mitk::eps, true));
// calculate a new version of anotherTransform, so that the spacing should be the same as the original spacing of
// aTransform.
mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
vnlmatrix = anotherTransform->GetMatrix().GetVnlMatrix();
mitk::VnlVector col;
col = vnlmatrix.get_column(0).as_ref();
col.normalize();
col *= aSpacing[0];
vnlmatrix.set_column(0, col);
col = vnlmatrix.get_column(1).as_ref();
col.normalize();
col *= aSpacing[1];
vnlmatrix.set_column(1, col);
col = vnlmatrix.get_column(2).as_ref();
col.normalize();
col *= aSpacing[2];
vnlmatrix.set_column(2, col);
mitk::Matrix3D matrix;
matrix = vnlmatrix;
anotherTransform->SetMatrix(matrix);
CPPUNIT_ASSERT(mitk::Equal(*anotherTransform, *(dummy->GetIndexToWorldTransform()), mitk::eps, true));
}
void TestSetIndexToWorldTransform_WithPointerToSameTransform()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetOrigin(anotherPoint);
dummy->SetIndexToWorldTransform(anotherTransform);
dummy->SetSpacing(anotherSpacing);
mitk::AffineTransform3D::Pointer testTransfrom = dummy->GetIndexToWorldTransform();
mitk::Vector3D modifiedPoint = anotherPoint.GetVectorFromOrigin() * 2.;
testTransfrom->SetOffset(modifiedPoint);
dummy->SetIndexToWorldTransform(testTransfrom);
CPPUNIT_ASSERT(mitk::Equal(modifiedPoint, dummy->GetOrigin().GetVectorFromOrigin()));
}
void TestSetIndexToWorldTransformByVtkMatrix()
{
vtkMatrix4x4 *vtkmatrix;
vtkmatrix = vtkMatrix4x4::New();
vtkmatrix->Identity();
vtkmatrix->SetElement(1, 1, 2);
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
MITK_ASSERT_EQUAL(anotherTransform,
mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()),
"Compare IndexToWorldTransformByVtkMatrix 1");
// test needs to fail now
vtkmatrix->SetElement(1, 1, 7);
dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
MITK_ASSERT_NOT_EQUAL(anotherTransform,
mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()),
"Compare IndexToWorldTransformByVtkMatrix 2");
// undo changes, new and changed object need to be the same!
vtkmatrix->SetElement(1, 1, 1);
dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
vtkmatrix->Delete();
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Compare IndexToWorldTransformByVtkMatrix 3");
}
void TestSetIdentity()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
// Change IndextoWorldTransform and Origin
dummy->SetIndexToWorldTransform(anotherTransform);
dummy->SetOrigin(anotherPoint);
// Set Identity should reset ITWT and Origin
dummy->SetIdentity();
MITK_ASSERT_EQUAL(
aTransform, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Test set identity 1");
CPPUNIT_ASSERT(mitk::Equal(aPoint, dummy->GetOrigin()));
CPPUNIT_ASSERT(mitk::Equal(aSpacing, dummy->GetSpacing()));
// new and changed object need to be the same!
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Test set identity 2");
}
void TestSetSpacing()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetSpacing(anotherSpacing);
CPPUNIT_ASSERT(mitk::Equal(anotherSpacing, dummy->GetSpacing()));
// undo changes, new and changed object need to be the same!
dummy->SetSpacing(aSpacing);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy spacing");
}
void TestTransferItkToVtkTransform()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(anotherTransform); // calls TransferItkToVtkTransform
mitk::AffineTransform3D::Pointer dummyTransform = dummy->GetIndexToWorldTransform();
CPPUNIT_ASSERT(mitk::MatrixEqualElementWise(anotherMatrix, dummyTransform->GetMatrix()));
}
void TestConstructors()
{
// test standard constructor
DummyTestClass::Pointer dummy1 = DummyTestClass::New();
bool test = dummy1->IsValid();
CPPUNIT_ASSERT(test == true);
CPPUNIT_ASSERT(dummy1->GetFrameOfReferenceID() == 0);
CPPUNIT_ASSERT(dummy1->GetIndexToWorldTransformLastModified() == 0);
CPPUNIT_ASSERT(mitk::Equal(dummy1->GetSpacing(), aSpacing));
CPPUNIT_ASSERT(mitk::Equal(dummy1->GetOrigin(), aPoint));
CPPUNIT_ASSERT(dummy1->GetImageGeometry() == false);
MITK_ASSERT_EQUAL(
mitk::AffineTransform3D::Pointer(dummy1->GetIndexToWorldTransform()), aTransform, "Constructor test 1");
MITK_ASSERT_EQUAL(
mitk::BaseGeometry::BoundingBoxType::ConstPointer(dummy1->GetBoundingBox()), aBoundingBox, "Constructor test 2");
DummyTestClass::Pointer dummy2 = DummyTestClass::New();
dummy2->SetOrigin(anotherPoint);
float bounds[6] = {0, 11, 0, 12, 0, 13};
dummy2->SetFloatBounds(bounds);
dummy2->SetIndexToWorldTransform(anotherTransform);
dummy2->SetSpacing(anotherSpacing);
DummyTestClass::Pointer dummy3 = DummyTestClass::New(*dummy2);
MITK_ASSERT_EQUAL(dummy3, dummy2, "Dummy constructor");
}
// Equal Tests
void Equal_CloneAndOriginal_ReturnsTrue() { MITK_ASSERT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Clone test"); }
void Equal_DifferentOrigin_ReturnsFalse()
{
anotherDummyGeometry->SetOrigin(anotherPoint);
MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different origin test");
}
void Equal_DifferentIndexToWorldTransform_ReturnsFalse()
{
anotherDummyGeometry->SetIndexToWorldTransform(anotherTransform);
MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different index to world");
}
void Equal_DifferentSpacing_ReturnsFalse()
{
anotherDummyGeometry->SetSpacing(anotherSpacing);
MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different spacing");
}
void Equal_InputIsNull_ReturnsFalse()
{
DummyTestClass::Pointer geometryNull = nullptr;
CPPUNIT_ASSERT_THROW(MITK_ASSERT_EQUAL(geometryNull, anotherDummyGeometry, "Input is null"), mitk::Exception);
}
void Equal_DifferentBoundingBox_ReturnsFalse()
{
// create different bounds to make the comparison false
mitk::ScalarType bounds[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
anotherDummyGeometry->SetBounds(bounds);
MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different bounding box");
}
void Equal_Transforms_MinorDifferences_And_Eps()
{
// Verifies that the eps parameter is evaluated properly
// when comparing two mitk::BaseGeometry::TransformTypes
aMatrix.SetIdentity();
anotherMatrix.SetIdentity();
aMatrix(0, 1) = 0.0002;
aTransform->SetMatrix(aMatrix);
anotherMatrix(0, 1) = 0.0002;
anotherTransform->SetMatrix(anotherMatrix);
anotherTransform->SetMatrix(aMatrix);
CPPUNIT_ASSERT_MESSAGE("Exact same transforms are mitk::Equal() for eps=mitk::eps",
mitk::Equal(*aTransform, *anotherTransform, mitk::eps, true));
CPPUNIT_ASSERT_MESSAGE("Exact same transforms are mitk::Equal() for eps=vnl_math::eps",
mitk::Equal(*aTransform, *anotherTransform, vnl_math::eps, true));
anotherMatrix(0, 1) = 0.0002 + mitk::eps;
anotherTransform->SetMatrix(anotherMatrix);
CPPUNIT_ASSERT_MESSAGE("Transforms of diff mitk::eps are !mitk::Equal() for eps=vnl_math::eps",
!mitk::Equal(*aTransform, *anotherTransform, vnl_math::eps, true));
CPPUNIT_ASSERT_MESSAGE("Transforms of diff mitk::eps are !mitk::Equal() for eps=mitk::eps-1%",
!mitk::Equal(*aTransform, *anotherTransform, mitk::eps * 0.99, true));
CPPUNIT_ASSERT_MESSAGE("Transforms of diff mitk::eps _are_ mitk::Equal() for eps=mitk::eps+1%",
mitk::Equal(*aTransform, *anotherTransform, mitk::eps * 1.01, true));
}
void TestComposeTransform()
{
// Create Transformations to set and compare
mitk::AffineTransform3D::Pointer transform1;
transform1 = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType matrix1;
matrix1.SetIdentity();
matrix1(1, 1) = 2;
transform1->SetMatrix(matrix1); // Spacing = 2
mitk::AffineTransform3D::Pointer transform2;
transform2 = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType matrix2;
matrix2.SetIdentity();
matrix2(1, 1) = 2;
transform2->SetMatrix(matrix2); // Spacing = 2
mitk::AffineTransform3D::Pointer transform3;
transform3 = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType matrix3;
matrix3.SetIdentity();
matrix3(1, 1) = 4;
transform3->SetMatrix(matrix3); // Spacing = 4
mitk::AffineTransform3D::Pointer transform4;
transform4 = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType matrix4;
matrix4.SetIdentity();
matrix4(1, 1) = 0.25;
transform4->SetMatrix(matrix4); // Spacing = 0.25
// Vector to compare spacing
mitk::Vector3D expectedSpacing;
expectedSpacing.Fill(1.0);
expectedSpacing[1] = 4;
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(transform1); // Spacing = 2
dummy->Compose(transform2); // Spacing = 4
CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing));
MITK_ASSERT_EQUAL(
transform3, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compose transform 2"); // 4=4
// undo changes, new and changed object need to be the same!
dummy->Compose(transform4); // Spacing = 1
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Compose transform 3"); // 1=1
}
void TestComposeVtkMatrix()
{
// Create Transformations to set and compare
mitk::AffineTransform3D::Pointer transform1;
transform1 = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType matrix1;
matrix1.SetIdentity();
matrix1(1, 1) = 2;
transform1->SetMatrix(matrix1); // Spacing = 2
vtkMatrix4x4 *vtkmatrix2;
vtkmatrix2 = vtkMatrix4x4::New();
vtkmatrix2->Identity();
vtkmatrix2->SetElement(1, 1, 2); // Spacing = 2
mitk::AffineTransform3D::Pointer transform3;
transform3 = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType matrix3;
matrix3.SetIdentity();
matrix3(1, 1) = 4;
transform3->SetMatrix(matrix3); // Spacing = 4
vtkMatrix4x4 *vtkmatrix4;
vtkmatrix4 = vtkMatrix4x4::New();
vtkmatrix4->Identity();
vtkmatrix4->SetElement(1, 1, 0.25); // Spacing = 0.25
// Vector to compare spacing
mitk::Vector3D expectedSpacing;
expectedSpacing.Fill(1.0);
expectedSpacing[1] = 4;
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(transform1); // Spacing = 2
dummy->Compose(vtkmatrix2); // Spacing = 4
vtkmatrix2->Delete();
MITK_ASSERT_EQUAL(
transform3, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compose vtk matrix"); // 4=4
CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing));
// undo changes, new and changed object need to be the same!
dummy->Compose(vtkmatrix4); // Spacing = 1
vtkmatrix4->Delete();
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Compose vtk"); // 1=1
}
void TestTranslate()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetOrigin(anotherPoint);
CPPUNIT_ASSERT(mitk::Equal(anotherPoint, dummy->GetOrigin()));
// use some random values for translation
mitk::Vector3D translationVector;
translationVector.SetElement(0, 17.5f);
translationVector.SetElement(1, -32.3f);
translationVector.SetElement(2, 4.0f);
// compute ground truth
mitk::Point3D tmpResult = anotherPoint + translationVector;
dummy->Translate(translationVector);
CPPUNIT_ASSERT(mitk::Equal(dummy->GetOrigin(), tmpResult));
// undo changes
translationVector *= -1;
dummy->Translate(translationVector);
CPPUNIT_ASSERT(mitk::Equal(dummy->GetOrigin(), anotherPoint));
// undo changes, new and changed object need to be the same!
translationVector.SetElement(0, -1 * anotherPoint[0]);
translationVector.SetElement(1, -1 * anotherPoint[1]);
translationVector.SetElement(2, -1 * anotherPoint[2]);
dummy->Translate(translationVector);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Translate test");
}
// a part of the test requires axis-parallel coordinates
int testIndexAndWorldConsistency(DummyTestClass::Pointer dummyGeometry)
{
// Testing consistency of index and world coordinate systems
mitk::Point3D origin = dummyGeometry->GetOrigin();
mitk::Point3D dummyPoint;
// Testing index->world->index conversion consistency
dummyGeometry->WorldToIndex(origin, dummyPoint);
dummyGeometry->IndexToWorld(dummyPoint, dummyPoint);
CPPUNIT_ASSERT(mitk::EqualArray(dummyPoint, origin, 3, mitk::eps, true));
// Testing WorldToIndex(origin, mitk::Point3D)==(0,0,0)
mitk::Point3D globalOrigin;
mitk::FillVector3D(globalOrigin, 0, 0, 0);
mitk::Point3D originContinuousIndex;
dummyGeometry->WorldToIndex(origin, originContinuousIndex);
CPPUNIT_ASSERT(mitk::EqualArray(originContinuousIndex, globalOrigin, 3, mitk::eps, true));
// Testing WorldToIndex(origin, itk::Index)==(0,0,0)
itk::Index<3> itkindex;
dummyGeometry->WorldToIndex(origin, itkindex);
itk::Index<3> globalOriginIndex;
mitk::vtk2itk(globalOrigin, globalOriginIndex);
CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true));
// Testing WorldToIndex(origin-0.5*spacing, itk::Index)==(0,0,0)
mitk::Vector3D halfSpacingStep = dummyGeometry->GetSpacing() * 0.5;
mitk::Matrix3D rotation;
mitk::Point3D originOffCenter = origin - halfSpacingStep;
dummyGeometry->WorldToIndex(originOffCenter, itkindex);
CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true));
// Testing WorldToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)
originOffCenter = origin + halfSpacingStep;
- originOffCenter -= 0.0001;
+ originOffCenter -= mitk::Vector(0.0001);
dummyGeometry->WorldToIndex(originOffCenter, itkindex);
CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true));
// Testing WorldToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
originOffCenter = origin + halfSpacingStep;
itk::Index<3> global111;
mitk::FillVector3D(global111, 1, 1, 1);
dummyGeometry->WorldToIndex(originOffCenter, itkindex);
CPPUNIT_ASSERT(mitk::EqualArray(itkindex, global111, 3, mitk::eps, true));
// Testing WorldToIndex(GetCenter())==BoundingBox.GetCenter
mitk::Point3D center = dummyGeometry->GetCenter();
mitk::Point3D centerContIndex;
dummyGeometry->WorldToIndex(center, centerContIndex);
mitk::BoundingBox::ConstPointer boundingBox = dummyGeometry->GetBoundingBox();
mitk::BoundingBox::PointType centerBounds = boundingBox->GetCenter();
CPPUNIT_ASSERT(mitk::Equal(centerContIndex, centerBounds));
// Testing GetCenter()==IndexToWorld(BoundingBox.GetCenter)
center = dummyGeometry->GetCenter();
mitk::Point3D centerBoundsInWorldCoords;
dummyGeometry->IndexToWorld(centerBounds, centerBoundsInWorldCoords);
CPPUNIT_ASSERT(mitk::Equal(center, centerBoundsInWorldCoords));
// Test using random point,
// Testing consistency of index and world coordinate systems
mitk::Point3D point;
mitk::FillVector3D(point, 3.5, -2, 4.6);
// Testing index->world->index conversion consistency
dummyGeometry->WorldToIndex(point, dummyPoint);
dummyGeometry->IndexToWorld(dummyPoint, dummyPoint);
CPPUNIT_ASSERT(mitk::EqualArray(dummyPoint, point, 3, mitk::eps, true));
return EXIT_SUCCESS;
}
int testIndexAndWorldConsistencyForVectors(DummyTestClass::Pointer dummyGeometry)
{
// Testing consistency of index and world coordinate systems for vectors
mitk::Vector3D xAxisMM = dummyGeometry->GetAxisVector(0);
mitk::Vector3D xAxisContinuousIndex;
mitk::Point3D p, pIndex, origin;
origin = dummyGeometry->GetOrigin();
p[0] = xAxisMM[0] + origin[0];
p[1] = xAxisMM[1] + origin[1];
p[2] = xAxisMM[2] + origin[2];
dummyGeometry->WorldToIndex(p, pIndex);
dummyGeometry->WorldToIndex(xAxisMM, xAxisContinuousIndex);
CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[0], pIndex[0]));
CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[1], pIndex[1]));
CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[2], pIndex[2]));
dummyGeometry->IndexToWorld(xAxisContinuousIndex, xAxisContinuousIndex);
dummyGeometry->IndexToWorld(pIndex, p);
CPPUNIT_ASSERT(xAxisContinuousIndex == xAxisMM);
CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[0], p[0] - origin[0]));
CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[1], p[1] - origin[1]));
CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[2], p[2] - origin[2]));
// Test consictency for random vector
mitk::Vector3D vector;
mitk::FillVector3D(vector, 2.5, -3.2, 8.1);
mitk::Vector3D vectorContinuousIndex;
p[0] = vector[0] + origin[0];
p[1] = vector[1] + origin[1];
p[2] = vector[2] + origin[2];
dummyGeometry->WorldToIndex(p, pIndex);
dummyGeometry->WorldToIndex(vector, vectorContinuousIndex);
CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[0], pIndex[0]));
CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[1], pIndex[1]));
CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[2], pIndex[2]));
dummyGeometry->IndexToWorld(vectorContinuousIndex, vectorContinuousIndex);
dummyGeometry->IndexToWorld(pIndex, p);
CPPUNIT_ASSERT(vectorContinuousIndex == vector);
CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[0], p[0] - origin[0]));
CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[1], p[1] - origin[1]));
CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[2], p[2] - origin[2]));
return EXIT_SUCCESS;
}
int testIndexAndWorldConsistencyForIndex(DummyTestClass::Pointer dummyGeometry)
{
// Testing consistency of index and world coordinate systems
// creating testing data
itk::Index<4> itkIndex4, itkIndex4b;
itk::Index<3> itkIndex3, itkIndex3b;
itk::Index<2> itkIndex2, itkIndex2b;
itk::Index<3> mitkIndex, mitkIndexb;
itkIndex4[0] = itkIndex4[1] = itkIndex4[2] = itkIndex4[3] = 4;
itkIndex3[0] = itkIndex3[1] = itkIndex3[2] = 6;
itkIndex2[0] = itkIndex2[1] = 2;
mitkIndex[0] = mitkIndex[1] = mitkIndex[2] = 13;
// check for consistency
mitk::Point3D point;
dummyGeometry->IndexToWorld(itkIndex2, point);
dummyGeometry->WorldToIndex(point, itkIndex2b);
CPPUNIT_ASSERT(((itkIndex2b[0] == itkIndex2[0]) && (itkIndex2b[1] == itkIndex2[1])));
// Testing itk::index<2> for IndexToWorld/WorldToIndex consistency
dummyGeometry->IndexToWorld(itkIndex3, point);
dummyGeometry->WorldToIndex(point, itkIndex3b);
CPPUNIT_ASSERT(
((itkIndex3b[0] == itkIndex3[0]) && (itkIndex3b[1] == itkIndex3[1]) && (itkIndex3b[2] == itkIndex3[2])));
// Testing itk::index<3> for IndexToWorld/WorldToIndex consistency
dummyGeometry->IndexToWorld(itkIndex4, point);
dummyGeometry->WorldToIndex(point, itkIndex4b);
CPPUNIT_ASSERT(((itkIndex4b[0] == itkIndex4[0]) && (itkIndex4b[1] == itkIndex4[1]) &&
(itkIndex4b[2] == itkIndex4[2]) && (itkIndex4b[3] == 0)));
// Testing itk::index<3> for IndexToWorld/WorldToIndex consistency
dummyGeometry->IndexToWorld(mitkIndex, point);
dummyGeometry->WorldToIndex(point, mitkIndexb);
CPPUNIT_ASSERT(
((mitkIndexb[0] == mitkIndex[0]) && (mitkIndexb[1] == mitkIndex[1]) && (mitkIndexb[2] == mitkIndex[2])));
// Testing mitk::Index for IndexToWorld/WorldToIndex consistency
return EXIT_SUCCESS;
}
void TestIndexToWorld()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
testIndexAndWorldConsistency(dummy);
testIndexAndWorldConsistencyForVectors(dummy);
testIndexAndWorldConsistencyForIndex(dummy);
// Geometry must not have changed
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy index to world");
// Test with other geometries
dummy->SetOrigin(anotherPoint);
testIndexAndWorldConsistency(dummy);
testIndexAndWorldConsistencyForVectors(dummy);
testIndexAndWorldConsistencyForIndex(dummy);
dummy->SetIndexToWorldTransform(anotherTransform);
testIndexAndWorldConsistency(dummy);
testIndexAndWorldConsistencyForVectors(dummy);
testIndexAndWorldConsistencyForIndex(dummy);
dummy->SetOrigin(anotherPoint);
testIndexAndWorldConsistency(dummy);
testIndexAndWorldConsistencyForVectors(dummy);
testIndexAndWorldConsistencyForIndex(dummy);
dummy->SetSpacing(anotherSpacing);
testIndexAndWorldConsistency(dummy);
testIndexAndWorldConsistencyForVectors(dummy);
testIndexAndWorldConsistencyForIndex(dummy);
}
void TestExecuteOperation()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
// Do same Operations with new Dummy and compare
DummyTestClass::Pointer newDummy = DummyTestClass::New();
// Test operation Nothing
auto opN = new mitk::Operation(mitk::OpNOTHING);
dummy->ExecuteOperation(opN);
MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy execute operation 1");
// Test operation Move
auto opP = new mitk::PointOperation(mitk::OpMOVE, anotherPoint);
dummy->ExecuteOperation(opP);
CPPUNIT_ASSERT(mitk::Equal(anotherPoint, dummy->GetOrigin()));
newDummy->SetOrigin(anotherPoint);
MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy execute operation 2");
// Test operation Scale, Scale sets spacing to scale+1
mitk::Point3D spacing;
spacing[0] = anotherSpacing[0] - 1.;
spacing[1] = anotherSpacing[1] - 1.;
spacing[2] = anotherSpacing[2] - 1.;
auto opS = new mitk::ScaleOperation(mitk::OpSCALE, spacing, anotherPoint);
dummy->ExecuteOperation(opS);
CPPUNIT_ASSERT(mitk::Equal(anotherSpacing, dummy->GetSpacing()));
newDummy->SetSpacing(anotherSpacing);
MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy execute operation 3");
// change Geometry to test more cases
dummy->SetIndexToWorldTransform(anotherTransform);
dummy->SetSpacing(anotherSpacing);
// Testing a rotation of the geometry
double angle = 35.0;
mitk::Vector3D rotationVector;
mitk::FillVector3D(rotationVector, 1, 0, 0);
mitk::Point3D center = dummy->GetCenter();
auto opR = new mitk::RotationOperation(mitk::OpROTATE, center, rotationVector, angle);
dummy->ExecuteOperation(opR);
mitk::Matrix3D rotation;
mitk::GetRotation(dummy, rotation);
mitk::Vector3D voxelStep = rotation * anotherSpacing;
mitk::Vector3D voxelStepIndex;
dummy->WorldToIndex(voxelStep, voxelStepIndex);
mitk::Vector3D expectedVoxelStepIndex;
expectedVoxelStepIndex.Fill(1);
CPPUNIT_ASSERT(mitk::Equal(voxelStepIndex, expectedVoxelStepIndex));
delete opR;
delete opN;
delete opS;
delete opP;
}
void TestCalculateBoundingBoxRelToTransform()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetExtentInMM(0, 15);
dummy->SetExtentInMM(1, 20);
dummy->SetExtentInMM(2, 8);
mitk::BoundingBox::Pointer dummyBoundingBox = dummy->CalculateBoundingBoxRelativeToTransform(anotherTransform);
mitk::BoundingBox::PointsContainer::Pointer pointscontainer = mitk::BoundingBox::PointsContainer::New();
mitk::BoundingBox::PointIdentifier pointid = 0;
unsigned char i;
mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
anotherTransform->GetInverse(inverse);
for (i = 0; i < 8; ++i)
pointscontainer->InsertElement(pointid++, inverse->TransformPoint(dummy->GetCornerPoint(i)));
mitk::BoundingBox::Pointer result = mitk::BoundingBox::New();
result->SetPoints(pointscontainer);
result->ComputeBoundingBox();
MITK_ASSERT_EQUAL(result, dummyBoundingBox, "BBox rel to transform");
// dummy still needs to be unchanged, except for extend
DummyTestClass::Pointer newDummy = DummyTestClass::New();
newDummy->SetExtentInMM(0, 15);
newDummy->SetExtentInMM(1, 20);
newDummy->SetExtentInMM(2, 8);
MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy BBox");
}
// void TestSetTimeBounds(){
// mitk::TimeBounds timeBounds;
// timeBounds[0] = 1;
// timeBounds[1] = 9;
// DummyTestClass::Pointer dummy = DummyTestClass::New();
// dummy->SetTimeBounds(timeBounds);
// mitk::TimeBounds timeBounds2 = dummy->GetTimeBounds();
// CPPUNIT_ASSERT(timeBounds[0]==timeBounds2[0]);
// CPPUNIT_ASSERT(timeBounds[1]==timeBounds2[1]);
// //undo changes, new and changed object need to be the same!
// timeBounds[0]=mitk::ScalarTypeNumericTraits::NonpositiveMin();
// timeBounds[1]=mitk::ScalarTypeNumericTraits::max();
// DummyTestClass::Pointer newDummy = DummyTestClass::New();
// CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true));
//}
void TestIs2DConvertable()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
// new initialized geometry is 2D convertable
CPPUNIT_ASSERT(dummy->Is2DConvertable());
// Wrong Spacing needs to fail
dummy->SetSpacing(anotherSpacing);
CPPUNIT_ASSERT(dummy->Is2DConvertable() == false);
// undo
dummy->SetSpacing(aSpacing);
CPPUNIT_ASSERT(dummy->Is2DConvertable());
// Wrong Origin needs to fail
dummy->SetOrigin(anotherPoint);
CPPUNIT_ASSERT(dummy->Is2DConvertable() == false);
// undo
dummy->SetOrigin(aPoint);
CPPUNIT_ASSERT(dummy->Is2DConvertable());
// third dimension must not be transformed
mitk::AffineTransform3D::Pointer dummyTransform = mitk::AffineTransform3D::New();
mitk::AffineTransform3D::MatrixType dummyMatrix;
dummyMatrix.SetIdentity();
dummyTransform->SetMatrix(dummyMatrix);
dummy->SetIndexToWorldTransform(dummyTransform);
// identity matrix is 2DConvertable
CPPUNIT_ASSERT(dummy->Is2DConvertable());
dummyMatrix(0, 2) = 3;
dummyTransform->SetMatrix(dummyMatrix);
CPPUNIT_ASSERT(dummy->Is2DConvertable() == false);
dummyMatrix.SetIdentity();
dummyMatrix(1, 2) = 0.4;
dummyTransform->SetMatrix(dummyMatrix);
CPPUNIT_ASSERT(dummy->Is2DConvertable() == false);
dummyMatrix.SetIdentity();
dummyMatrix(2, 2) = 3;
dummyTransform->SetMatrix(dummyMatrix);
CPPUNIT_ASSERT(dummy->Is2DConvertable() == false);
dummyMatrix.SetIdentity();
dummyMatrix(2, 1) = 3;
dummyTransform->SetMatrix(dummyMatrix);
CPPUNIT_ASSERT(dummy->Is2DConvertable() == false);
dummyMatrix.SetIdentity();
dummyMatrix(2, 0) = 3;
dummyTransform->SetMatrix(dummyMatrix);
CPPUNIT_ASSERT(dummy->Is2DConvertable() == false);
// undo changes, new and changed object need to be the same!
dummyMatrix.SetIdentity();
dummyTransform->SetMatrix(dummyMatrix);
DummyTestClass::Pointer newDummy = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy, newDummy, "Is 2D convertable");
}
void TestGetCornerPoint()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(anotherTransform);
double bounds[6] = {0, 11, 0, 12, 0, 13};
dummy->SetFloatBounds(bounds);
mitk::Point3D corner, refCorner;
// Corner 0
mitk::FillVector3D(refCorner, bounds[0], bounds[2], bounds[4]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(0);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(true, true, true);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Corner 1
mitk::FillVector3D(refCorner, bounds[0], bounds[2], bounds[5]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(1);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(true, true, false);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Corner 2
mitk::FillVector3D(refCorner, bounds[0], bounds[3], bounds[4]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(2);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(true, false, true);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Corner 3
mitk::FillVector3D(refCorner, bounds[0], bounds[3], bounds[5]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(3);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(true, false, false);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Corner 4
mitk::FillVector3D(refCorner, bounds[1], bounds[2], bounds[4]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(4);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(false, true, true);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Corner 5
mitk::FillVector3D(refCorner, bounds[1], bounds[2], bounds[5]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(5);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(false, true, false);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Corner 6
mitk::FillVector3D(refCorner, bounds[1], bounds[3], bounds[4]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(6);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(false, false, true);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Corner 7
mitk::FillVector3D(refCorner, bounds[1], bounds[3], bounds[5]);
refCorner = anotherTransform->TransformPoint(refCorner);
corner = dummy->GetCornerPoint(7);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
corner = dummy->GetCornerPoint(false, false, false);
CPPUNIT_ASSERT(mitk::Equal(refCorner, corner));
// Wrong Corner needs to fail
CPPUNIT_ASSERT_THROW(dummy->GetCornerPoint(20), itk::ExceptionObject);
// dummy geometry must not have changed!
DummyTestClass::Pointer newDummy = DummyTestClass::New();
newDummy->SetIndexToWorldTransform(anotherTransform);
newDummy->SetFloatBounds(bounds);
MITK_ASSERT_EQUAL(dummy, newDummy, "Corner point");
}
void TestExtentInMM()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetExtentInMM(0, 50);
CPPUNIT_ASSERT(mitk::Equal(50., dummy->GetExtentInMM(0)));
// Vnl Matrix has changed. The next line only works because the spacing is 1!
CPPUNIT_ASSERT(
mitk::Equal(50., dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude()));
// Smaller extent than original
dummy->SetExtentInMM(0, 5);
CPPUNIT_ASSERT(mitk::Equal(5., dummy->GetExtentInMM(0)));
CPPUNIT_ASSERT(
mitk::Equal(5., dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude()));
dummy->SetExtentInMM(1, 4);
CPPUNIT_ASSERT(mitk::Equal(4., dummy->GetExtentInMM(1)));
CPPUNIT_ASSERT(
mitk::Equal(4., dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1).magnitude()));
dummy->SetExtentInMM(2, 2.5);
CPPUNIT_ASSERT(mitk::Equal(2.5, dummy->GetExtentInMM(2)));
CPPUNIT_ASSERT(
mitk::Equal(2.5, dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2).magnitude()));
}
void TestGetAxisVector()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(anotherTransform);
double bounds[6] = {0, 11, 0, 12, 0, 13};
dummy->SetFloatBounds(bounds);
mitk::Vector3D vector;
mitk::FillVector3D(vector, bounds[1], 0, 0);
dummy->IndexToWorld(vector, vector);
CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(0), vector));
mitk::FillVector3D(vector, 0, bounds[3], 0);
dummy->IndexToWorld(vector, vector);
CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(1), vector));
mitk::FillVector3D(vector, 0, 0, bounds[5]);
dummy->IndexToWorld(vector, vector);
CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(2), vector));
}
void TestGetCenter()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(anotherTransform);
double bounds[6] = {0, 11, 2, 12, 1, 13};
dummy->SetFloatBounds(bounds);
mitk::Point3D refCenter;
for (int i = 0; i < 3; i++)
refCenter.SetElement(i, (bounds[2 * i] + bounds[2 * i + 1]) / 2.0);
dummy->IndexToWorld(refCenter, refCenter);
CPPUNIT_ASSERT(mitk::Equal(dummy->GetCenter(), refCenter));
}
void TestGetDiagonalLength()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
double bounds[6] = {1, 3, 5, 8, 7.5, 11.5};
dummy->SetFloatBounds(bounds);
// 3-1=2, 8-5=3, 11.5-7.5=4; 2^2+3^2+4^2 = 29
double expectedLength = sqrt(29.);
CPPUNIT_ASSERT(mitk::Equal(expectedLength, dummy->GetDiagonalLength(), mitk::eps, true));
CPPUNIT_ASSERT(mitk::Equal(29., dummy->GetDiagonalLength2(), mitk::eps, true));
// dummy must not have changed
DummyTestClass::Pointer newDummy = DummyTestClass::New();
newDummy->SetFloatBounds(bounds);
MITK_ASSERT_EQUAL(dummy, newDummy, "Diagonal length");
}
void TestGetExtent()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
double bounds[6] = {1, 3, 5, 8, 7.5, 11.5};
dummy->SetFloatBounds(bounds);
CPPUNIT_ASSERT(mitk::Equal(2., dummy->GetExtent(0)));
CPPUNIT_ASSERT(mitk::Equal(3., dummy->GetExtent(1)));
CPPUNIT_ASSERT(mitk::Equal(4., dummy->GetExtent(2)));
// dummy must not have changed
DummyTestClass::Pointer newDummy = DummyTestClass::New();
newDummy->SetFloatBounds(bounds);
MITK_ASSERT_EQUAL(dummy, newDummy, "Extend");
}
void TestIsInside()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
double bounds[6] = {1, 3, 5, 8, 7.5, 11.5};
dummy->SetFloatBounds(bounds);
mitk::Point3D insidePoint;
mitk::Point3D outsidePoint;
mitk::FillVector3D(insidePoint, 2, 6, 7.6);
mitk::FillVector3D(outsidePoint, 0, 9, 8.2);
CPPUNIT_ASSERT(dummy->IsIndexInside(insidePoint));
CPPUNIT_ASSERT(false == dummy->IsIndexInside(outsidePoint));
dummy->IndexToWorld(insidePoint, insidePoint);
dummy->IndexToWorld(outsidePoint, outsidePoint);
CPPUNIT_ASSERT(dummy->IsInside(insidePoint));
CPPUNIT_ASSERT(false == dummy->IsInside(outsidePoint));
// dummy must not have changed
DummyTestClass::Pointer newDummy = DummyTestClass::New();
newDummy->SetFloatBounds(bounds);
MITK_ASSERT_EQUAL(dummy, newDummy, "Is inside");
}
void TestInitialize()
{
// test standard constructor
DummyTestClass::Pointer dummy1 = DummyTestClass::New();
DummyTestClass::Pointer dummy2 = DummyTestClass::New();
dummy2->SetOrigin(anotherPoint);
dummy2->SetBounds(anotherBoundingBox->GetBounds());
// mitk::TimeBounds timeBounds;
// timeBounds[0] = 1;
// timeBounds[1] = 9;
// dummy2->SetTimeBounds(timeBounds);
dummy2->SetIndexToWorldTransform(anotherTransform);
dummy2->SetSpacing(anotherSpacing);
dummy1->InitializeGeometry(dummy2);
MITK_ASSERT_EQUAL(dummy1, dummy2, "Initialize 1");
dummy1->Initialize();
DummyTestClass::Pointer dummy3 = DummyTestClass::New();
MITK_ASSERT_EQUAL(dummy3, dummy1, "Initialize 2");
}
void TestGetMatrixColumn()
{
DummyTestClass::Pointer dummy = DummyTestClass::New();
dummy->SetIndexToWorldTransform(anotherTransform);
mitk::Vector3D testVector, refVector;
testVector.SetVnlVector(dummy->GetMatrixColumn(0));
mitk::FillVector3D(refVector, 1, 0, 0);
CPPUNIT_ASSERT(testVector == refVector);
testVector.SetVnlVector(dummy->GetMatrixColumn(1));
mitk::FillVector3D(refVector, 0, 2, 0);
CPPUNIT_ASSERT(testVector == refVector);
testVector.SetVnlVector(dummy->GetMatrixColumn(2));
mitk::FillVector3D(refVector, 0, 0, 1);
CPPUNIT_ASSERT(testVector == refVector);
// dummy must not have changed
DummyTestClass::Pointer newDummy = DummyTestClass::New();
newDummy->SetIndexToWorldTransform(anotherTransform);
MITK_ASSERT_EQUAL(dummy, newDummy, "GetMatrixColumn");
}
void IsSubGeometry_Spacing()
{
CPPUNIT_ASSERT(mitk::IsSubGeometry(*aDummyGeometry, *aDummyGeometry, mitk::eps, true));
for (unsigned int i = 0; i < 3; ++i)
{
mitk::Vector3D wrongSpacing = aDummyGeometry->GetSpacing();
wrongSpacing[i] += mitk::eps * 2;
auto wrongGeometry = aDummyGeometry->Clone();
wrongGeometry->SetSpacing(wrongSpacing);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometry, mitk::eps, true));
}
for (unsigned int i = 0; i < 3; ++i)
{
mitk::Vector3D wrongSpacing = aDummyGeometry->GetSpacing();
wrongSpacing[i] -= mitk::eps * 2;
auto wrongGeometry = aDummyGeometry->Clone();
wrongGeometry->SetSpacing(wrongSpacing);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometry, mitk::eps, true));
}
}
void IsSubGeometry_TransformMatrix()
{
CPPUNIT_ASSERT(mitk::IsSubGeometry(*aDummyGeometry, *aDummyGeometry, mitk::eps, true));
for (unsigned int i = 0; i < 3; ++i)
{
for (unsigned int j = 0; j < 3; ++j)
{
itk::Matrix<mitk::ScalarType, 3, 3> wrongMatrix = aDummyGeometry->GetIndexToWorldTransform()->GetMatrix();
wrongMatrix[i][j] += mitk::eps * 2;
auto wrongGeometry = aDummyGeometry->Clone();
wrongGeometry->GetIndexToWorldTransform()->SetMatrix(wrongMatrix);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometry, mitk::eps, true));
}
}
}
void IsSubGeometry_Bounds_NoneImage()
{
IsSubGeometry_Bounds_internal(false);
}
void IsSubGeometry_Bounds_Image()
{
IsSubGeometry_Bounds_internal(true);
}
void IsSubGeometry_Bounds_internal(bool isImage)
{
auto newBounds = aDummyGeometry->GetBounds();
newBounds[0] = 10;
newBounds[1] = 20;
newBounds[2] = 10;
newBounds[3] = 20;
newBounds[4] = 10;
newBounds[5] = 20;
aDummyGeometry->SetBounds(newBounds);
aDummyGeometry->SetImageGeometry(isImage);
CPPUNIT_ASSERT(mitk::IsSubGeometry(*aDummyGeometry, *aDummyGeometry, mitk::eps, true));
for (unsigned int i = 0; i < 6; ++i)
{
auto legalBounds = newBounds;
if (i % 2 == 0)
{
legalBounds[i] += 1;
}
else
{
legalBounds[i] -= 1;
}
auto legalGeometry = aDummyGeometry->Clone();
legalGeometry->SetBounds(legalBounds);
CPPUNIT_ASSERT(mitk::IsSubGeometry(*legalGeometry, *aDummyGeometry, mitk::eps, true));
}
for (unsigned int i = 0; i < 6; ++i)
{
auto wrongBounds = aDummyGeometry->GetBounds();
if (i % 2 == 0)
{
wrongBounds[i] -= 1;
}
else
{
wrongBounds[i] += 1;
}
auto wrongGeometry = aDummyGeometry->Clone();
wrongGeometry->SetBounds(wrongBounds);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometry, mitk::eps, true));
}
}
void IsSubGeometry_Grid_Image()
{
IsSubGeometry_Grid_internal(true);
}
void IsSubGeometry_Grid_NoneImage()
{
IsSubGeometry_Grid_internal(false);
}
void IsSubGeometry_Grid_internal(bool isImage)
{
auto newBounds = aDummyGeometry->GetBounds();
newBounds[0] = 0;
newBounds[1] = 20;
newBounds[2] = 0;
newBounds[3] = 20;
newBounds[4] = 0;
newBounds[5] = 20;
aDummyGeometry->SetBounds(newBounds);
aDummyGeometry->SetImageGeometry(isImage);
auto smallerGeometry = aDummyGeometry->Clone();
newBounds[0] = 5;
newBounds[1] = 10;
newBounds[2] = 5;
newBounds[3] = 10;
newBounds[4] = 5;
newBounds[5] = 10;
smallerGeometry->SetBounds(newBounds);
//legal negative shift
for (unsigned int i = 0; i < 3; ++i)
{
auto legalOrigin = smallerGeometry->GetOrigin();
legalOrigin[i] -= smallerGeometry->GetSpacing()[i];
auto legalGeometry = smallerGeometry->Clone();
legalGeometry->SetOrigin(legalOrigin);
CPPUNIT_ASSERT(mitk::IsSubGeometry(*legalGeometry, *aDummyGeometry, mitk::eps, true));
}
//legal positive shift
for (unsigned int i = 0; i < 3; ++i)
{
auto legalOrigin = smallerGeometry->GetOrigin();
legalOrigin[i] += smallerGeometry->GetSpacing()[i];
auto legalGeometry = smallerGeometry->Clone();
legalGeometry->SetOrigin(legalOrigin);
CPPUNIT_ASSERT(mitk::IsSubGeometry(*legalGeometry, *aDummyGeometry, mitk::eps, true));
}
//wrong negative shift
for (unsigned int i = 0; i < 3; ++i)
{
auto wrongOrigin = smallerGeometry->GetOrigin();
wrongOrigin[i] -= 2 * mitk::eps;
auto wrongGeometry = smallerGeometry->Clone();
wrongGeometry->SetOrigin(wrongOrigin);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometry, mitk::eps, true));
}
//wrong positive shift
for (unsigned int i = 0; i < 3; ++i)
{
auto wrongOrigin = smallerGeometry->GetOrigin();
wrongOrigin[i] += 2 * mitk::eps;
auto wrongGeometry = smallerGeometry->Clone();
wrongGeometry->SetOrigin(wrongOrigin);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometry, mitk::eps, true));
}
}
void IsSubGeometry_Bounds_Oblique_NoneImage()
{
IsSubGeometry_Bounds_Oblique_internal(false);
}
void IsSubGeometry_Bounds_Oblique_Image()
{
IsSubGeometry_Bounds_Oblique_internal(true);
}
void IsSubGeometry_Bounds_Oblique_internal(bool isImage)
{
auto newBounds = aDummyGeometryOblique->GetBounds();
aDummyGeometryOblique->SetImageGeometry(isImage);
//REMARK: used NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION to compensate rounding errors that
//are interoduced when transforming points/indeces due to the oblique geometry.
CPPUNIT_ASSERT(mitk::IsSubGeometry(*aDummyGeometryOblique, *aDummyGeometryOblique, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, true));
for (unsigned int i = 0; i < 6; ++i)
{
auto legalBounds = newBounds;
if (i % 2 == 0)
{
legalBounds[i] += 1;
}
else
{
legalBounds[i] -= 1;
}
auto legalGeometry = aDummyGeometryOblique->Clone();
legalGeometry->SetBounds(legalBounds);
CPPUNIT_ASSERT(mitk::IsSubGeometry(*legalGeometry, *aDummyGeometryOblique, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, true));
}
for (unsigned int i = 0; i < 6; ++i)
{
auto wrongBounds = newBounds;
if (i % 2 == 0)
{
wrongBounds[i] -= 1;
}
else
{
wrongBounds[i] += 1;
}
auto wrongGeometry = aDummyGeometryOblique->Clone();
wrongGeometry->SetBounds(wrongBounds);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometryOblique, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, true));
}
}
void IsSubGeometry_Grid_Oblique_NoneImage()
{
IsSubGeometry_Grid_Oblique_internal(false);
}
void IsSubGeometry_Grid_Oblique_Image()
{
IsSubGeometry_Grid_Oblique_internal(true);
}
void IsSubGeometry_Grid_Oblique_internal(bool isImage)
{
auto newBounds = aDummyGeometryOblique->GetBounds();
newBounds[0] = 0;
newBounds[1] = 20;
newBounds[2] = 0;
newBounds[3] = 20;
newBounds[4] = 0;
newBounds[5] = 20;
aDummyGeometryOblique->SetBounds(newBounds);
aDummyGeometryOblique->SetImageGeometry(isImage);
auto smallerGeometry = aDummyGeometryOblique->Clone();
newBounds[0] = 5;
newBounds[1] = 10;
newBounds[2] = 5;
newBounds[3] = 10;
newBounds[4] = 5;
newBounds[5] = 10;
smallerGeometry->SetBounds(newBounds);
//REMARK: used NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION in the following checks
//to compensate rounding errors that are interoduced when transforming points/indeces
//due to the oblique geometry.
//legal negative shift
for (unsigned int i = 0; i < 3; ++i)
{
auto legalOrigin = smallerGeometry->GetOrigin();
mitk::Point3D index;
smallerGeometry->WorldToIndex(legalOrigin, index);
index[i] -= 1;
smallerGeometry->IndexToWorld(index, legalOrigin);
auto legalGeometry = smallerGeometry->Clone();
legalGeometry->SetOrigin(legalOrigin);
CPPUNIT_ASSERT(mitk::IsSubGeometry(*legalGeometry, *aDummyGeometryOblique, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, true));
}
//legal positive shift
for (unsigned int i = 0; i < 3; ++i)
{
auto legalOrigin = smallerGeometry->GetOrigin();
mitk::Point3D index;
smallerGeometry->WorldToIndex(legalOrigin, index);
index[i] += 1;
smallerGeometry->IndexToWorld(index, legalOrigin);
auto legalGeometry = smallerGeometry->Clone();
legalGeometry->SetOrigin(legalOrigin);
CPPUNIT_ASSERT(mitk::IsSubGeometry(*legalGeometry, *aDummyGeometryOblique, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, true));
}
//wrong negative shift
for (unsigned int i = 0; i < 3; ++i)
{
auto wrongOrigin = smallerGeometry->GetOrigin();
wrongOrigin[i] -= 2 * mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION;
auto wrongGeometry = smallerGeometry->Clone();
wrongGeometry->SetOrigin(wrongOrigin);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometryOblique, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, true));
}
//wrong positive shift
for (unsigned int i = 0; i < 3; ++i)
{
auto wrongOrigin = smallerGeometry->GetOrigin();
wrongOrigin[i] += 2 * mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION;
auto wrongGeometry = smallerGeometry->Clone();
wrongGeometry->SetOrigin(wrongOrigin);
CPPUNIT_ASSERT(!mitk::IsSubGeometry(*wrongGeometry, *aDummyGeometryOblique, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, true));
}
}
}; // end class mitkBaseGeometryTestSuite
MITK_TEST_SUITE_REGISTRATION(mitkBaseGeometry)
diff --git a/Modules/Core/test/mitkExtractSliceFilterTest.cpp b/Modules/Core/test/mitkExtractSliceFilterTest.cpp
index 96916a6240..afe25f5d1f 100644
--- a/Modules/Core/test/mitkExtractSliceFilterTest.cpp
+++ b/Modules/Core/test/mitkExtractSliceFilterTest.cpp
@@ -1,1069 +1,1069 @@
/*============================================================================
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 <itkImage.h>
#include <itkImageRegionIterator.h>
#include <mitkExtractSliceFilter.h>
#include <mitkIOUtil.h>
#include <mitkITKImageImport.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkInteractionConst.h>
#include <mitkNumericTypes.h>
#include <mitkRotationOperation.h>
#include <mitkStandardFileLocations.h>
#include <mitkTestingMacros.h>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <mitkGeometry3D.h>
#include <vtkActor.h>
#include <vtkImageActor.h>
#include <vtkImageData.h>
#include <vtkImageMapToColors.h>
#include <vtkImageMapper.h>
#include <vtkImageReslice.h>
#include <vtkInteractorStyleImage.h>
#include <vtkLookupTable.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkTexture.h>
// use this to create the test volume on the fly
#define CREATE_VOLUME
// use this to save the created volume
//#define SAVE_VOLUME
// use this to calculate the error from the sphere mathematical model to our pixel based one
//#define CALC_TESTFAILURE_DEVIATION
// use this to render an oblique slice through a specified image
//#define SHOW_SLICE_IN_RENDER_WINDOW
-// use this to have infos printed in mbilog
+// use this to have infos printed in mitkLog
//#define EXTRACTOR_DEBUG
/*these are the deviations calculated by the function CalcTestFailureDeviation (see for details)*/
#define Testfailure_Deviation_Mean_128 0.853842
#define Testfailure_Deviation_Volume_128 0.145184
#define Testfailure_Deviation_Diameter_128 1.5625
#define Testfailure_Deviation_Mean_256 0.397693
#define Testfailure_Deviation_Volume_256 0.0141357
#define Testfailure_Deviation_Diameter_256 0.78125
#define Testfailure_Deviation_Mean_512 0.205277
#define Testfailure_Deviation_Volume_512 0.01993
#define Testfailure_Deviation_Diameter_512 0.390625
class mitkExtractSliceFilterTestClass
{
public:
static void TestSlice(mitk::PlaneGeometry *planeGeometry, std::string testname)
{
TestPlane = planeGeometry;
TestName = testname;
mitk::ScalarType centerCoordValue = TestvolumeSize / 2.0;
mitk::ScalarType center[3] = {centerCoordValue, centerCoordValue, centerCoordValue};
mitk::Point3D centerIndex(center);
double radius = TestvolumeSize / 4.0;
if (TestPlane->Distance(centerIndex) >= radius)
return; // outside sphere
// feed ExtractSliceFilter
mitk::ExtractSliceFilter::Pointer slicer = mitk::ExtractSliceFilter::New();
slicer->SetInput(TestVolume);
slicer->SetWorldGeometry(TestPlane);
slicer->Update();
MITK_TEST_CONDITION_REQUIRED(slicer->GetOutput() != nullptr, "Extractor returned a slice");
mitk::Image::Pointer reslicedImage = slicer->GetOutput();
AccessFixedDimensionByItk(reslicedImage, TestSphereRadiusByItk, 2);
AccessFixedDimensionByItk(reslicedImage, TestSphereAreaByItk, 2);
/*
double devArea, devDiameter;
if(TestvolumeSize == 128.0){ devArea = Testfailure_Deviation_Volume_128; devDiameter =
Testfailure_Deviation_Diameter_128; }
else if(TestvolumeSize == 256.0){devArea = Testfailure_Deviation_Volume_256; devDiameter =
Testfailure_Deviation_Diameter_256;}
else if (TestvolumeSize == 512.0){devArea = Testfailure_Deviation_Volume_512; devDiameter =
Testfailure_Deviation_Diameter_512;}
else{devArea = Testfailure_Deviation_Volume_128; devDiameter = Testfailure_Deviation_Diameter_128;}
*/
std::string areatestName = TestName.append(" area");
std::string diametertestName = TestName.append(" testing diameter");
// TODO think about the deviation, 1% makes no sense at all
MITK_TEST_CONDITION(std::abs(100 - testResults.percentageAreaCalcToPixel) < 1, areatestName);
MITK_TEST_CONDITION(std::abs(100 - testResults.percentageRadiusToPixel) < 1, diametertestName);
#ifdef EXTRACTOR_DEBUG
MITK_INFO << TestName << " >>> "
<< "planeDistanceToSphereCenter: " << testResults.planeDistanceToSphereCenter;
MITK_INFO << "area in pixels: " << testResults.areaInPixel << " <-> area in mm: " << testResults.areaCalculated
<< " = " << testResults.percentageAreaCalcToPixel << "%";
MITK_INFO << "calculated diameter: " << testResults.diameterCalculated
<< " <-> diameter in mm: " << testResults.diameterInMM
<< " <-> diameter in pixel: " << testResults.diameterInPixel << " = "
<< testResults.percentageRadiusToPixel << "%";
#endif
}
/*
* get the radius of the slice of a sphere based on pixel distance from edge to edge of the circle.
*/
template <typename TPixel, unsigned int VImageDimension>
static void TestSphereRadiusByItk(itk::Image<TPixel, VImageDimension> *inputImage)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
// set the index to the middle of the image's edge at x and y axis
typename InputImageType::IndexType currentIndexX;
currentIndexX[0] = (int)(TestvolumeSize / 2.0);
currentIndexX[1] = 0;
typename InputImageType::IndexType currentIndexY;
currentIndexY[0] = 0;
currentIndexY[1] = (int)(TestvolumeSize / 2.0);
// remember the last pixel value
double lastValueX = inputImage->GetPixel(currentIndexX);
double lastValueY = inputImage->GetPixel(currentIndexY);
// storage for the index marks
std::vector<typename InputImageType::IndexType> indicesX;
std::vector<typename InputImageType::IndexType> indicesY;
/*Get four indices on the edge of the circle*/
while (currentIndexX[1] < TestvolumeSize && currentIndexX[0] < TestvolumeSize)
{
// move x direction
currentIndexX[1] += 1;
// move y direction
currentIndexY[0] += 1;
if (inputImage->GetPixel(currentIndexX) > lastValueX)
{
// mark the current index
typename InputImageType::IndexType markIndex;
markIndex[0] = currentIndexX[0];
markIndex[1] = currentIndexX[1];
indicesX.push_back(markIndex);
}
else if (inputImage->GetPixel(currentIndexX) < lastValueX)
{
// mark the current index
typename InputImageType::IndexType markIndex;
markIndex[0] = currentIndexX[0];
markIndex[1] = currentIndexX[1] - 1; // value inside the sphere
indicesX.push_back(markIndex);
}
if (inputImage->GetPixel(currentIndexY) > lastValueY)
{
// mark the current index
typename InputImageType::IndexType markIndex;
markIndex[0] = currentIndexY[0];
markIndex[1] = currentIndexY[1];
indicesY.push_back(markIndex);
}
else if (inputImage->GetPixel(currentIndexY) < lastValueY)
{
// mark the current index
typename InputImageType::IndexType markIndex;
markIndex[0] = currentIndexY[0];
markIndex[1] = currentIndexY[1] - 1; // value inside the sphere
indicesY.push_back(markIndex);
}
// found both marks?
if (indicesX.size() == 2 && indicesY.size() == 2)
break;
// the new 'last' values
lastValueX = inputImage->GetPixel(currentIndexX);
lastValueY = inputImage->GetPixel(currentIndexY);
}
/*
*If we are here we found the four marks on the edge of the circle.
*For the case our plane is rotated and shifted, we have to calculate the center of the circle,
*else the center is the intersection of both straight lines between the marks.
*When we have the center, the diameter of the circle will be checked to the reference value(math!).
*/
// each distance from the first mark of each direction to the center of the straight line between the marks
double distanceToCenterX = std::abs(indicesX[0][1] - indicesX[1][1]) / 2.0;
// double distanceToCenterY = std::abs(indicesY[0][0] - indicesY[1][0]) / 2.0;
// the center of the straight lines
typename InputImageType::IndexType centerX;
// typename InputImageType::IndexType centerY;
centerX[0] = indicesX[0][0];
centerX[1] = indicesX[0][1] + distanceToCenterX;
// TODO think about implicit cast to int. this is not the real center of the image, which could be between two
// pixels
// centerY[0] = indicesY[0][0] + distanceToCenterY;
// centerY[1] = inidcesY[0][1];
typename InputImageType::IndexType currentIndex(centerX);
lastValueX = inputImage->GetPixel(currentIndex);
long sumpixels = 0;
std::vector<typename InputImageType::IndexType> diameterIndices;
// move up
while (currentIndex[1] < TestvolumeSize)
{
currentIndex[1] += 1;
if (inputImage->GetPixel(currentIndex) != lastValueX)
{
typename InputImageType::IndexType markIndex;
markIndex[0] = currentIndex[0];
markIndex[1] = currentIndex[1] - 1;
diameterIndices.push_back(markIndex);
break;
}
sumpixels++;
lastValueX = inputImage->GetPixel(currentIndex);
}
currentIndex[1] -= sumpixels; // move back to center to go in the other direction
lastValueX = inputImage->GetPixel(currentIndex);
// move down
while (currentIndex[1] >= 0)
{
currentIndex[1] -= 1;
if (inputImage->GetPixel(currentIndex) != lastValueX)
{
typename InputImageType::IndexType markIndex;
markIndex[0] = currentIndex[0];
markIndex[1] = currentIndex[1]; // outside sphere because we want to calculate the distance from edge to edge
diameterIndices.push_back(markIndex);
break;
}
sumpixels++;
lastValueX = inputImage->GetPixel(currentIndex);
}
/*
*Now sumpixels should be the apromximate diameter of the circle. This is checked with the calculated diameter from
*the plane transformation(math).
*/
mitk::Point3D volumeCenter;
volumeCenter[0] = volumeCenter[1] = volumeCenter[2] = TestvolumeSize / 2.0;
double planeDistanceToSphereCenter = TestPlane->Distance(volumeCenter);
double sphereRadius = TestvolumeSize / 4.0;
// calculate the radius of the circle cut from the sphere by the plane
double diameter = 2.0 * std::sqrt(std::pow(sphereRadius, 2) - std::pow(planeDistanceToSphereCenter, 2));
double percentageRadiusToPixel = 100 / diameter * sumpixels;
/*
*calculate the radius in mm by the both marks of the center line by using the world coordinates
*/
// get the points as 3D coordinates
mitk::Vector3D diameterPointRight, diameterPointLeft;
diameterPointRight[2] = diameterPointLeft[2] = 0.0;
diameterPointLeft[0] = diameterIndices[0][0];
diameterPointLeft[1] = diameterIndices[0][1];
diameterPointRight[0] = diameterIndices[1][0];
diameterPointRight[1] = diameterIndices[1][1];
// transform to worldcoordinates
TestVolume->GetGeometry()->IndexToWorld(diameterPointLeft, diameterPointLeft);
TestVolume->GetGeometry()->IndexToWorld(diameterPointRight, diameterPointRight);
// euklidian distance
double diameterInMM = ((diameterPointLeft * -1.0) + diameterPointRight).GetNorm();
testResults.diameterInMM = diameterInMM;
testResults.diameterCalculated = diameter;
testResults.diameterInPixel = sumpixels;
testResults.percentageRadiusToPixel = percentageRadiusToPixel;
testResults.planeDistanceToSphereCenter = planeDistanceToSphereCenter;
}
/*brute force the area pixel by pixel*/
template <typename TPixel, unsigned int VImageDimension>
static void TestSphereAreaByItk(itk::Image<TPixel, VImageDimension> *inputImage)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef itk::ImageRegionConstIterator<InputImageType> ImageIterator;
ImageIterator imageIterator(inputImage, inputImage->GetLargestPossibleRegion());
imageIterator.GoToBegin();
int sumPixelsInArea = 0;
while (!imageIterator.IsAtEnd())
{
if (inputImage->GetPixel(imageIterator.GetIndex()) == pixelValueSet)
sumPixelsInArea++;
++imageIterator;
}
mitk::Point3D volumeCenter;
volumeCenter[0] = volumeCenter[1] = volumeCenter[2] = TestvolumeSize / 2.0;
double planeDistanceToSphereCenter = TestPlane->Distance(volumeCenter);
double sphereRadius = TestvolumeSize / 4.0;
// calculate the radius of the circle cut from the sphere by the plane
double radius = std::sqrt(std::pow(sphereRadius, 2) - std::pow(planeDistanceToSphereCenter, 2));
double areaInMM = 3.14159265358979 * std::pow(radius, 2);
testResults.areaCalculated = areaInMM;
testResults.areaInPixel = sumPixelsInArea;
testResults.percentageAreaCalcToPixel = 100 / areaInMM * sumPixelsInArea;
}
/*
* random a voxel. define plane through this voxel. reslice at the plane. compare the pixel vaues of the voxel
* in the volume with the pixel value in the resliced image.
* there are some indice shifting problems which causes the test to fail for oblique planes. seems like the chosen
* worldcoordinate is not corresponding to the index in the 2D image. and so the pixel values are not the same as
* expected.
*/
static void PixelvalueBasedTest()
{
/* setup itk image */
typedef itk::Image<unsigned short, 3> ImageType;
typedef itk::ImageRegionConstIterator<ImageType> ImageIterator;
ImageType::Pointer image = ImageType::New();
ImageType::IndexType start;
start[0] = start[1] = start[2] = 0;
ImageType::SizeType size;
size[0] = size[1] = size[2] = 32;
ImageType::RegionType imgRegion;
imgRegion.SetSize(size);
imgRegion.SetIndex(start);
image->SetRegions(imgRegion);
- image->SetSpacing(1.0);
+ image->SetSpacing(mitk::Vector(1.0));
image->Allocate();
ImageIterator imageIterator(image, image->GetLargestPossibleRegion());
imageIterator.GoToBegin();
unsigned short pixelValue = 0;
// fill the image with distinct values
while (!imageIterator.IsAtEnd())
{
image->SetPixel(imageIterator.GetIndex(), pixelValue);
++imageIterator;
++pixelValue;
}
/* end setup itk image */
mitk::Image::Pointer imageInMitk;
CastToMitkImage(image, imageInMitk);
/*mitk::ImageWriter::Pointer writer = mitk::ImageWriter::New();
writer->SetInput(imageInMitk);
std::string file = "C:\\Users\\schroedt\\Desktop\\cube.nrrd";
writer->SetFileName(file);
writer->Update();*/
PixelvalueBasedTestByPlane(imageInMitk, mitk::AnatomicalPlane::Coronal);
PixelvalueBasedTestByPlane(imageInMitk, mitk::AnatomicalPlane::Sagittal);
PixelvalueBasedTestByPlane(imageInMitk, mitk::AnatomicalPlane::Axial);
}
static void PixelvalueBasedTestByPlane(mitk::Image *imageInMitk, mitk::AnatomicalPlane orientation)
{
typedef itk::Image<unsigned short, 3> ImageType;
// set the seed of the rand function
srand((unsigned)time(nullptr));
/* setup a random orthogonal plane */
int sliceindex = 17; // rand() % 32;
bool isFrontside = true;
bool isRotated = false;
if (orientation == mitk::AnatomicalPlane::Axial)
{
/*isFrontside = false;
isRotated = true;*/
}
mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New();
plane->InitializeStandardPlane(imageInMitk->GetGeometry(), orientation, sliceindex, isFrontside, isRotated);
mitk::Point3D origin = plane->GetOrigin();
mitk::Vector3D normal;
normal = plane->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
plane->SetOrigin(origin);
// we dont need this any more, because we are only testing orthogonal planes
/*mitk::Vector3D rotationVector;
rotationVector[0] = randFloat();
rotationVector[1] = randFloat();
rotationVector[2] = randFloat();
float degree = randFloat() * 180.0;
mitk::RotationOperation* op = new mitk::RotationOperation(mitk::OpROTATE, plane->GetCenter(), rotationVector,
degree);
plane->ExecuteOperation(op);
delete op;*/
/* end setup plane */
/* define a point in the 3D volume.
* add the two axis vectors of the plane (each multiplied with a
* random number) to the origin. now the two random numbers
* become our index coordinates in the 2D image, because the
* length of the axis vectors is 1.
*/
mitk::Point3D planeOrigin = plane->GetOrigin();
mitk::Vector3D axis0, axis1;
axis0 = plane->GetAxisVector(0);
axis1 = plane->GetAxisVector(1);
axis0.Normalize();
axis1.Normalize();
unsigned char n1 = 7; // rand() % 32;
unsigned char n2 = 13; // rand() % 32;
mitk::Point3D testPoint3DInWorld;
testPoint3DInWorld = planeOrigin + (axis0 * n1) + (axis1 * n2);
// get the index of the point in the 3D volume
ImageType::IndexType testPoint3DInIndex;
imageInMitk->GetGeometry()->WorldToIndex(testPoint3DInWorld, testPoint3DInIndex);
itk::Index<3> testPoint2DInIndex;
/* end define a point in the 3D volume.*/
// do reslicing at the plane
mitk::ExtractSliceFilter::Pointer slicer = mitk::ExtractSliceFilter::New();
slicer->SetInput(imageInMitk);
slicer->SetWorldGeometry(plane);
slicer->Update();
mitk::Image::Pointer slice = slicer->GetOutput();
// Get TestPoiont3D as Index in Slice
slice->GetGeometry()->WorldToIndex(testPoint3DInWorld, testPoint2DInIndex);
mitk::Point3D p, sliceIndexToWorld, imageIndexToWorld;
p[0] = testPoint2DInIndex[0];
p[1] = testPoint2DInIndex[1];
p[2] = testPoint2DInIndex[2];
slice->GetGeometry()->IndexToWorld(p, sliceIndexToWorld);
p[0] = testPoint3DInIndex[0];
p[1] = testPoint3DInIndex[1];
p[2] = testPoint3DInIndex[2];
imageInMitk->GetGeometry()->IndexToWorld(p, imageIndexToWorld);
itk::Index<2> testPoint2DIn2DIndex;
testPoint2DIn2DIndex[0] = testPoint2DInIndex[0];
testPoint2DIn2DIndex[1] = testPoint2DInIndex[1];
typedef mitk::ImagePixelReadAccessor<unsigned short, 3> VolumeReadAccessorType;
typedef mitk::ImagePixelReadAccessor<unsigned short, 2> SliceReadAccessorType;
VolumeReadAccessorType VolumeReadAccessor(imageInMitk);
SliceReadAccessorType SliceReadAccessor(slice);
// compare the pixelvalues of the defined point in the 3D volume with the value of the resliced image
unsigned short valueAt3DVolume = VolumeReadAccessor.GetPixelByIndex(testPoint3DInIndex);
unsigned short valueAtSlice = SliceReadAccessor.GetPixelByIndex(testPoint2DIn2DIndex);
// valueAt3DVolume == valueAtSlice is not always working. because of rounding errors
// indices are shifted
MITK_TEST_CONDITION(valueAt3DVolume == valueAtSlice, "comparing pixelvalues for orthogonal plane");
vtkSmartPointer<vtkImageData> imageInVtk = imageInMitk->GetVtkImageData();
vtkSmartPointer<vtkImageData> sliceInVtk = slice->GetVtkImageData();
double PixelvalueByMitkOutput = sliceInVtk->GetScalarComponentAsDouble(n1, n2, 0, 0);
// double valueVTKinImage = imageInVtk->GetScalarComponentAsDouble(testPoint3DInIndex[0], testPoint3DInIndex[1],
// testPoint3DInIndex[2], 0);
/* Test that everything is working equally if vtkoutput is used instead of the default output
* from mitk ImageToImageFilter
*/
mitk::ExtractSliceFilter::Pointer slicerWithVtkOutput = mitk::ExtractSliceFilter::New();
slicerWithVtkOutput->SetInput(imageInMitk);
slicerWithVtkOutput->SetWorldGeometry(plane);
slicerWithVtkOutput->SetVtkOutputRequest(true);
slicerWithVtkOutput->Update();
vtkSmartPointer<vtkImageData> vtkImageByVtkOutput = slicerWithVtkOutput->GetVtkOutput();
double PixelvalueByVtkOutput = vtkImageByVtkOutput->GetScalarComponentAsDouble(n1, n2, 0, 0);
MITK_TEST_CONDITION(PixelvalueByMitkOutput == PixelvalueByVtkOutput,
"testing conversion of image output vtk->mitk by reslicer");
-/*================ mbilog outputs ===========================*/
+/*================ log outputs ===========================*/
#ifdef EXTRACTOR_DEBUG
MITK_INFO << "\n"
<< "TESTINFO index: " << sliceindex << " orientation: " << orientation << " frontside: " << isFrontside
<< " rotated: " << isRotated;
MITK_INFO << "\n"
<< "slice index to world: " << sliceIndexToWorld;
MITK_INFO << "\n"
<< "image index to world: " << imageIndexToWorld;
MITK_INFO << "\n"
<< "vtk: slice: " << PixelvalueByMitkOutput << ", image: " << valueVTKinImage;
MITK_INFO << "\n"
<< "testPoint3D InWorld" << testPoint3DInWorld << " is " << testPoint2DInIndex << " in 2D";
MITK_INFO << "\n"
<< "randoms: " << ((int)n1) << ", " << ((int)n2);
MITK_INFO << "\n"
<< "point is inside plane: " << plane->IsInside(testPoint3DInWorld)
<< " and volume: " << imageInMitk->GetGeometry()->IsInside(testPoint3DInWorld);
MITK_INFO << "\n"
<< "volume idx: " << testPoint3DInIndex << " = " << valueAt3DVolume;
MITK_INFO << "\n"
<< "volume world: " << testPoint3DInWorld << " = " << valueAt3DVolumeByWorld;
MITK_INFO << "\n"
<< "slice idx: " << testPoint2DInIndex << " = " << valueAtSlice;
itk::Index<3> curr;
curr[0] = curr[1] = curr[2] = 0;
for (int i = 0; i < 32; ++i)
{
for (int j = 0; j < 32; ++j)
{
++curr[1];
if (SliceReadAccessor.GetPixelByIndex(curr) == valueAt3DVolume)
{
MITK_INFO << "\n" << valueAt3DVolume << " MATCHED mitk " << curr;
}
}
curr[1] = 0;
++curr[0];
}
typedef itk::Image<unsigned short, 2> Image2DType;
Image2DType::Pointer img = Image2DType::New();
CastToItkImage(slice, img);
typedef itk::ImageRegionConstIterator<Image2DType> Iterator2D;
Iterator2D iter(img, img->GetLargestPossibleRegion());
iter.GoToBegin();
while (!iter.IsAtEnd())
{
if (img->GetPixel(iter.GetIndex()) == valueAt3DVolume)
MITK_INFO << "\n" << valueAt3DVolume << " MATCHED itk " << iter.GetIndex();
++iter;
}
#endif // EXTRACTOR_DEBUG
}
/* random a float value */
static float randFloat()
{
return (((float)rand() + 1.0) / ((float)RAND_MAX + 1.0)) +
(((float)rand() + 1.0) / ((float)RAND_MAX + 1.0)) / ((float)RAND_MAX + 1.0);
}
/* create a sphere with the size of the given testVolumeSize*/
static void InitializeTestVolume()
{
#ifdef CREATE_VOLUME
// do sphere creation
ItkVolumeGeneration();
#ifdef SAVE_VOLUME
// save in file
mitk::ImageWriter::Pointer writer = mitk::ImageWriter::New();
writer->SetInput(TestVolume);
std::string file;
std::ostringstream filename;
filename << "C:\\home\\schroedt\\MITK\\Modules\\ImageExtraction\\Testing\\Data\\sphere_";
filename << TestvolumeSize;
filename << ".nrrd";
file = filename.str();
writer->SetFileName(file);
writer->Update();
#endif // SAVE_VOLUME
#endif
#ifndef CREATE_VOLUME // read from file
mitk::StandardFileLocations::Pointer locator = mitk::StandardFileLocations::GetInstance();
std::string filename = locator->FindFile("sphere_512.nrrd.mhd", "Modules/ImageExtraction/Testing/Data");
TestVolume = mitk::IOUtil::Load<mitk::Image>(filename);
#endif
#ifdef CALC_TESTFAILURE_DEVIATION
// get the TestFailureDeviation in %
AccessFixedDimensionByItk(TestVolume, CalcTestFailureDeviation, 3);
#endif
}
// the test result of the sphere reslice
struct SliceProperties
{
double planeDistanceToSphereCenter;
double diameterInMM;
double diameterInPixel;
double diameterCalculated;
double percentageRadiusToPixel;
double areaCalculated;
double areaInPixel;
double percentageAreaCalcToPixel;
};
static mitk::Image::Pointer TestVolume;
static double TestvolumeSize;
static mitk::PlaneGeometry::Pointer TestPlane;
static std::string TestName;
static unsigned char pixelValueSet;
static SliceProperties testResults;
static double TestFailureDeviation;
private:
/*
* Generate a sphere with a radius of TestvolumeSize / 4.0
*/
static void ItkVolumeGeneration()
{
typedef itk::Image<unsigned char, 3> TestVolumeType;
typedef itk::ImageRegionConstIterator<TestVolumeType> ImageIterator;
TestVolumeType::Pointer sphereImage = TestVolumeType::New();
TestVolumeType::IndexType start;
start[0] = start[1] = start[2] = 0;
TestVolumeType::SizeType size;
size[0] = size[1] = size[2] = TestvolumeSize;
TestVolumeType::RegionType imgRegion;
imgRegion.SetSize(size);
imgRegion.SetIndex(start);
sphereImage->SetRegions(imgRegion);
- sphereImage->SetSpacing(1.0);
+ sphereImage->SetSpacing(mitk::Vector(1.0));
sphereImage->Allocate();
sphereImage->FillBuffer(0);
mitk::Vector3D center;
center[0] = center[1] = center[2] = TestvolumeSize / 2.0;
double radius = TestvolumeSize / 4.0;
double pixelValue = pixelValueSet;
ImageIterator imageIterator(sphereImage, sphereImage->GetLargestPossibleRegion());
imageIterator.GoToBegin();
mitk::Vector3D currentVoxelInIndex;
while (!imageIterator.IsAtEnd())
{
currentVoxelInIndex[0] = imageIterator.GetIndex()[0];
currentVoxelInIndex[1] = imageIterator.GetIndex()[1];
currentVoxelInIndex[2] = imageIterator.GetIndex()[2];
double distanceToCenter = (center + (currentVoxelInIndex * -1.0)).GetNorm();
// if distance to center is smaller then the radius of the sphere
if (distanceToCenter < radius)
{
sphereImage->SetPixel(imageIterator.GetIndex(), pixelValue);
}
++imageIterator;
}
CastToMitkImage(sphereImage, TestVolume);
}
/* calculate the deviation of the voxel object to the mathematical sphere object.
* this is use to make a statement about the accuracy of the resliced image, eg. the circle's diameter or area.
*/
template <typename TPixel, unsigned int VImageDimension>
static void CalcTestFailureDeviation(itk::Image<TPixel, VImageDimension> *inputImage)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef itk::ImageRegionConstIterator<InputImageType> ImageIterator;
ImageIterator iterator(inputImage, inputImage->GetLargestPossibleRegion());
iterator.GoToBegin();
int volumeInPixel = 0;
while (!iterator.IsAtEnd())
{
if (inputImage->GetPixel(iterator.GetIndex()) == pixelValueSet)
volumeInPixel++;
++iterator;
}
double diameter = TestvolumeSize / 2.0;
double volumeCalculated = (1.0 / 6.0) * 3.14159265358979 * std::pow(diameter, 3);
double volumeDeviation = std::abs(100 - (100 / volumeCalculated * volumeInPixel));
typename InputImageType::IndexType index;
index[0] = index[1] = TestvolumeSize / 2.0;
index[2] = 0;
int sumpixels = 0;
while (index[2] < TestvolumeSize)
{
if (inputImage->GetPixel(index) == pixelValueSet)
sumpixels++;
index[2] += 1;
}
double diameterDeviation = std::abs(100 - (100 / diameter * sumpixels));
#ifdef DEBUG
MITK_INFO << "volume deviation: " << volumeDeviation << " diameter deviation:" << diameterDeviation;
#endif
mitkExtractSliceFilterTestClass::TestFailureDeviation = (volumeDeviation + diameterDeviation) / 2.0;
}
};
/*================ #END class ================*/
/*================#BEGIN Instantiation of members ================*/
mitk::Image::Pointer mitkExtractSliceFilterTestClass::TestVolume = mitk::Image::New();
double mitkExtractSliceFilterTestClass::TestvolumeSize = 256.0;
mitk::PlaneGeometry::Pointer mitkExtractSliceFilterTestClass::TestPlane = mitk::PlaneGeometry::New();
std::string mitkExtractSliceFilterTestClass::TestName = "";
unsigned char mitkExtractSliceFilterTestClass::pixelValueSet = 255;
mitkExtractSliceFilterTestClass::SliceProperties mitkExtractSliceFilterTestClass::testResults = {
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0};
double mitkExtractSliceFilterTestClass::TestFailureDeviation = 0.0;
/*================ #END Instantiation of members ================*/
/*================ #BEGIN test main ================*/
int mitkExtractSliceFilterTest(int /*argc*/, char * /*argv*/ [])
{
MITK_TEST_BEGIN("mitkExtractSliceFilterTest")
// pixelvalue based testing
mitkExtractSliceFilterTestClass::PixelvalueBasedTest();
// initialize sphere test volume
mitkExtractSliceFilterTestClass::InitializeTestVolume();
mitk::Vector3D spacing = mitkExtractSliceFilterTestClass::TestVolume->GetGeometry()->GetSpacing();
// the center of the sphere = center of image
double sphereCenter = mitkExtractSliceFilterTestClass::TestvolumeSize / 2.0;
double planeSize = mitkExtractSliceFilterTestClass::TestvolumeSize;
/* axial plane */
mitk::PlaneGeometry::Pointer geometryAxial = mitk::PlaneGeometry::New();
geometryAxial->InitializeStandardPlane(
planeSize, planeSize, spacing, mitk::AnatomicalPlane::Axial, sphereCenter, false, true);
geometryAxial->ChangeImageGeometryConsideringOriginOffset(true);
mitk::Point3D origin = geometryAxial->GetOrigin();
mitk::Vector3D normal;
normal = geometryAxial->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
// geometryAxial->SetOrigin(origin);
mitkExtractSliceFilterTestClass::TestSlice(geometryAxial, "Testing axial plane");
/* end axial plane */
/* sagittal plane */
mitk::PlaneGeometry::Pointer geometrySagittal = mitk::PlaneGeometry::New();
geometrySagittal->InitializeStandardPlane(
planeSize, planeSize, spacing, mitk::AnatomicalPlane::Sagittal, sphereCenter, true, false);
geometrySagittal->ChangeImageGeometryConsideringOriginOffset(true);
origin = geometrySagittal->GetOrigin();
normal = geometrySagittal->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
// geometrySagittal->SetOrigin(origin);
mitkExtractSliceFilterTestClass::TestSlice(geometrySagittal, "Testing sagittal plane");
/* sagittal plane */
/* sagittal shifted plane */
mitk::PlaneGeometry::Pointer geometrySagittalShifted = mitk::PlaneGeometry::New();
geometrySagittalShifted->InitializeStandardPlane(
planeSize, planeSize, spacing, mitk::AnatomicalPlane::Sagittal, (sphereCenter - 14), true, false);
geometrySagittalShifted->ChangeImageGeometryConsideringOriginOffset(true);
origin = geometrySagittalShifted->GetOrigin();
normal = geometrySagittalShifted->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
// geometrySagittalShifted->SetOrigin(origin);
mitkExtractSliceFilterTestClass::TestSlice(geometrySagittalShifted, "Testing sagittal plane shifted");
/* end sagittal shifted plane */
/* coronal plane */
mitk::PlaneGeometry::Pointer geometryCoronal = mitk::PlaneGeometry::New();
geometryCoronal->InitializeStandardPlane(
planeSize, planeSize, spacing, mitk::AnatomicalPlane::Coronal, sphereCenter, true, false);
geometryCoronal->ChangeImageGeometryConsideringOriginOffset(true);
origin = geometryCoronal->GetOrigin();
normal = geometryCoronal->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
// geometryCoronal->SetOrigin(origin);
mitkExtractSliceFilterTestClass::TestSlice(geometryCoronal, "Testing coronal plane");
/* end coronal plane */
/* oblique plane */
mitk::PlaneGeometry::Pointer obliquePlane = mitk::PlaneGeometry::New();
obliquePlane->InitializeStandardPlane(
planeSize, planeSize, spacing, mitk::AnatomicalPlane::Sagittal, sphereCenter, true, false);
obliquePlane->ChangeImageGeometryConsideringOriginOffset(true);
origin = obliquePlane->GetOrigin();
normal = obliquePlane->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
// obliquePlane->SetOrigin(origin);
mitk::Vector3D rotationVector;
rotationVector[0] = 0.2;
rotationVector[1] = 0.4;
rotationVector[2] = 0.62;
float degree = 37.0;
mitk::RotationOperation *op =
new mitk::RotationOperation(mitk::OpROTATE, obliquePlane->GetCenter(), rotationVector, degree);
obliquePlane->ExecuteOperation(op);
delete op;
mitkExtractSliceFilterTestClass::TestSlice(obliquePlane, "Testing oblique plane");
/* end oblique plane */
#ifdef SHOW_SLICE_IN_RENDER_WINDOW
/*================ #BEGIN vtk render code ================*/
// set reslicer for renderwindow
mitk::Image::Pointer pic = mitk::IOUtil::Load<mitk::Image>(filename);
vtkSmartPointer<vtkImageReslice> slicer = vtkSmartPointer<vtkImageReslice>::New();
slicer->SetInput(pic->GetVtkImageData());
mitk::PlaneGeometry::Pointer obliquePl = mitk::PlaneGeometry::New();
obliquePl->InitializeStandardPlane(
pic->GetGeometry(), mitk::AnatomicalPlane::Sagittal, pic->GetGeometry()->GetCenter()[0], true, false);
obliquePl->ChangeImageGeometryConsideringOriginOffset(true);
mitk::Point3D origin2 = obliquePl->GetOrigin();
mitk::Vector3D n;
n = obliquePl->GetNormal();
n.Normalize();
origin2 += n * 0.5; // pixelspacing is 1, so half the spacing is 0.5
obliquePl->SetOrigin(origin2);
mitk::Vector3D rotation;
rotation[0] = 0.534307;
rotation[1] = 0.000439605;
rotation[2] = 0.423017;
MITK_INFO << rotation;
mitk::RotationOperation *operation =
new mitk::RotationOperation(mitk::OpROTATE, obliquePl->GetCenter(), rotationVector, degree);
obliquePl->ExecuteOperation(operation);
delete operation;
double origin[3];
origin[0] = obliquePl->GetOrigin()[0];
origin[1] = obliquePl->GetOrigin()[1];
origin[2] = obliquePl->GetOrigin()[2];
slicer->SetResliceAxesOrigin(origin);
mitk::Vector3D right, bottom, normal;
right = obliquePl->GetAxisVector(0);
bottom = obliquePl->GetAxisVector(1);
normal = obliquePl->GetNormal();
right.Normalize();
bottom.Normalize();
normal.Normalize();
double cosines[9];
mitk::vnl2vtk(right.GetVnlVector(), cosines); // x
mitk::vnl2vtk(bottom.GetVnlVector(), cosines + 3); // y
mitk::vnl2vtk(normal.GetVnlVector(), cosines + 6); // n
slicer->SetResliceAxesDirectionCosines(cosines);
slicer->SetOutputDimensionality(2);
slicer->Update();
// set vtk renderwindow
vtkSmartPointer<vtkPlaneSource> vtkPlane = vtkSmartPointer<vtkPlaneSource>::New();
vtkPlane->SetOrigin(0.0, 0.0, 0.0);
// These two points define the axes of the plane in combination with the origin.
// Point 1 is the x-axis and point 2 the y-axis.
// Each plane is transformed according to the view (axial, coronal and sagittal) afterwards.
vtkPlane->SetPoint1(1.0, 0.0, 0.0); // P1: (xMax, yMin, depth)
vtkPlane->SetPoint2(0.0, 1.0, 0.0); // P2: (xMin, yMax, depth)
// these are not the correct values for all slices, only a square plane by now
vtkSmartPointer<vtkPolyDataMapper> imageMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
imageMapper->SetInputConnection(vtkPlane->GetOutputPort());
vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
// built a default lookuptable
lookupTable->SetRampToLinear();
lookupTable->SetSaturationRange(0.0, 0.0);
lookupTable->SetHueRange(0.0, 0.0);
lookupTable->SetValueRange(0.0, 1.0);
lookupTable->Build();
// map all black values to transparent
lookupTable->SetTableValue(0, 0.0, 0.0, 0.0, 0.0);
lookupTable->SetRange(-255.0, 255.0);
// lookupTable->SetRange(-1022.0, 1184.0);//pic3D range
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInput(slicer->GetOutput());
texture->SetLookupTable(lookupTable);
texture->SetMapColorScalarsThroughLookupTable(true);
vtkSmartPointer<vtkActor> imageActor = vtkSmartPointer<vtkActor>::New();
imageActor->SetMapper(imageMapper);
imageActor->SetTexture(texture);
// Setup renderers
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(imageActor);
// Setup render window
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
// Setup render window interactor
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
// Render and start interaction
renderWindowInteractor->SetRenderWindow(renderWindow);
// renderer->AddViewProp(imageActor);
renderWindow->Render();
renderWindowInteractor->Start();
// always end with this!
/*================ #END vtk render code ================*/
#endif // SHOW_SLICE_IN_RENDER_WINDOW
MITK_TEST_END()
}
diff --git a/Modules/Core/test/mitkGeometry3DTest.cpp b/Modules/Core/test/mitkGeometry3DTest.cpp
index caa5fc4d1a..c4395e1a28 100644
--- a/Modules/Core/test/mitkGeometry3DTest.cpp
+++ b/Modules/Core/test/mitkGeometry3DTest.cpp
@@ -1,622 +1,622 @@
/*============================================================================
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 "mitkGeometry3D.h"
#include <vnl/vnl_quaternion.h>
#include <vnl/vnl_quaternion.hxx>
#include "mitkInteractionConst.h"
#include "mitkRotationOperation.h"
#include <mitkImageCast.h>
#include <mitkMatrixConvert.h>
#include "mitkTestingMacros.h"
#include <fstream>
#include <mitkNumericTypes.h>
bool testGetAxisVectorVariants(mitk::Geometry3D *geometry)
{
int direction;
for (direction = 0; direction < 3; ++direction)
{
mitk::Vector3D frontToBack(0.);
switch (direction)
{
case 0:
frontToBack = geometry->GetCornerPoint(false, false, false) - geometry->GetCornerPoint(true, false, false);
break; // 7-3
case 1:
frontToBack = geometry->GetCornerPoint(false, false, false) - geometry->GetCornerPoint(false, true, false);
break; // 7-5
case 2:
frontToBack = geometry->GetCornerPoint(false, false, false) - geometry->GetCornerPoint(false, false, true);
break; // 7-2
}
std::cout << "Testing GetAxisVector(int) vs GetAxisVector(bool, bool, bool): ";
if (mitk::Equal(geometry->GetAxisVector(direction), frontToBack) == false)
{
std::cout << "[FAILED]" << std::endl;
return false;
}
std::cout << "[PASSED]" << std::endl;
}
return true;
}
bool testGetAxisVectorExtent(mitk::Geometry3D *geometry)
{
int direction;
for (direction = 0; direction < 3; ++direction)
{
if (mitk::Equal(geometry->GetAxisVector(direction).GetNorm(), geometry->GetExtentInMM(direction)) == false)
{
std::cout << "[FAILED]" << std::endl;
return false;
}
std::cout << "[PASSED]" << std::endl;
}
return true;
}
// a part of the test requires axis-parallel coordinates
int testIndexAndWorldConsistency(mitk::Geometry3D *geometry3d)
{
MITK_TEST_OUTPUT(<< "Testing consistency of index and world coordinate systems: ");
mitk::Point3D origin = geometry3d->GetOrigin();
mitk::Point3D dummy;
MITK_TEST_OUTPUT(<< " Testing index->world->index conversion consistency");
geometry3d->WorldToIndex(origin, dummy);
geometry3d->IndexToWorld(dummy, dummy);
MITK_TEST_CONDITION_REQUIRED(dummy == origin, "");
MITK_TEST_OUTPUT(<< " Testing WorldToIndex(origin, mitk::Point3D)==(0,0,0)");
mitk::Point3D globalOrigin;
mitk::FillVector3D(globalOrigin, 0, 0, 0);
mitk::Point3D originContinuousIndex;
geometry3d->WorldToIndex(origin, originContinuousIndex);
MITK_TEST_CONDITION_REQUIRED(originContinuousIndex == globalOrigin, "");
MITK_TEST_OUTPUT(<< " Testing WorldToIndex(origin, itk::Index)==(0,0,0)");
itk::Index<3> itkindex;
geometry3d->WorldToIndex(origin, itkindex);
itk::Index<3> globalOriginIndex;
mitk::vtk2itk(globalOrigin, globalOriginIndex);
MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
MITK_TEST_OUTPUT(<< " Testing WorldToIndex(origin-0.5*spacing, itk::Index)==(0,0,0)");
mitk::Vector3D halfSpacingStep = geometry3d->GetSpacing() * 0.5;
mitk::Matrix3D rotation;
mitk::Point3D originOffCenter = origin - halfSpacingStep;
geometry3d->WorldToIndex(originOffCenter, itkindex);
MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
MITK_TEST_OUTPUT(<< " Testing WorldToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)");
originOffCenter = origin + halfSpacingStep;
- originOffCenter -= 0.0001;
+ originOffCenter -= mitk::Vector(0.0001);
geometry3d->WorldToIndex(originOffCenter, itkindex);
MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
MITK_TEST_OUTPUT(<< " Testing WorldToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
originOffCenter = origin + halfSpacingStep;
itk::Index<3> global111;
mitk::FillVector3D(global111, 1, 1, 1);
geometry3d->WorldToIndex(originOffCenter, itkindex);
MITK_TEST_CONDITION_REQUIRED(itkindex == global111, "");
MITK_TEST_OUTPUT(<< " Testing WorldToIndex(GetCenter())==BoundingBox.GetCenter: ");
mitk::Point3D center = geometry3d->GetCenter();
mitk::Point3D centerContIndex;
geometry3d->WorldToIndex(center, centerContIndex);
mitk::BoundingBox::ConstPointer boundingBox = geometry3d->GetBoundingBox();
mitk::BoundingBox::PointType centerBounds = boundingBox->GetCenter();
// itk assumes corner based geometry. If our geometry is center based (imageGoe == true), everything needs to be
// shifted
if (geometry3d->GetImageGeometry())
{
centerBounds[0] -= 0.5;
centerBounds[1] -= 0.5;
centerBounds[2] -= 0.5;
}
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(centerContIndex, centerBounds), "");
MITK_TEST_OUTPUT(<< " Testing GetCenter()==IndexToWorld(BoundingBox.GetCenter): ");
center = geometry3d->GetCenter();
mitk::Point3D centerBoundsInWorldCoords;
geometry3d->IndexToWorld(centerBounds, centerBoundsInWorldCoords);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(center, centerBoundsInWorldCoords), "");
return EXIT_SUCCESS;
}
int testIndexAndWorldConsistencyForVectors(mitk::Geometry3D *geometry3d)
{
MITK_TEST_OUTPUT(<< "Testing consistency of index and world coordinate systems for vectors: ");
mitk::Vector3D xAxisMM = geometry3d->GetAxisVector(0);
mitk::Vector3D xAxisContinuousIndex;
mitk::Vector3D xAxisContinuousIndexDeprecated;
mitk::Point3D p, pIndex, origin;
origin = geometry3d->GetOrigin();
p[0] = xAxisMM[0];
p[1] = xAxisMM[1];
p[2] = xAxisMM[2];
geometry3d->WorldToIndex(p, pIndex);
geometry3d->WorldToIndex(xAxisMM, xAxisContinuousIndexDeprecated);
geometry3d->WorldToIndex(xAxisMM, xAxisContinuousIndex);
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == pIndex[0], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == pIndex[1], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == pIndex[2], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == xAxisContinuousIndexDeprecated[0], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == xAxisContinuousIndexDeprecated[1], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == xAxisContinuousIndexDeprecated[2], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[0] == pIndex[0], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[1] == pIndex[1], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[2] == pIndex[2], "");
geometry3d->IndexToWorld(xAxisContinuousIndex, xAxisContinuousIndex);
geometry3d->IndexToWorld(xAxisContinuousIndexDeprecated, xAxisContinuousIndexDeprecated);
geometry3d->IndexToWorld(pIndex, p);
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex == xAxisMM, "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[0] == p[0], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[1] == p[1], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndex[2] == p[2], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated == xAxisMM, "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[0] == p[0], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[1] == p[1], "");
MITK_TEST_CONDITION_REQUIRED(xAxisContinuousIndexDeprecated[2] == p[2], "");
return EXIT_SUCCESS;
}
int testIndexAndWorldConsistencyForIndex(mitk::Geometry3D *geometry3d)
{
MITK_TEST_OUTPUT(<< "Testing consistency of index and world coordinate systems: ");
// creating testing data
itk::Index<4> itkIndex4, itkIndex4b;
itk::Index<3> itkIndex3, itkIndex3b;
itk::Index<2> itkIndex2, itkIndex2b;
itk::Index<3> mitkIndex, mitkIndexb;
itkIndex4[0] = itkIndex4[1] = itkIndex4[2] = itkIndex4[3] = 4;
itkIndex3[0] = itkIndex3[1] = itkIndex3[2] = 6;
itkIndex2[0] = itkIndex2[1] = 2;
mitkIndex[0] = mitkIndex[1] = mitkIndex[2] = 13;
// check for consistency
mitk::Point3D point;
geometry3d->IndexToWorld(itkIndex2, point);
geometry3d->WorldToIndex(point, itkIndex2b);
MITK_TEST_CONDITION_REQUIRED(((itkIndex2b[0] == itkIndex2[0]) && (itkIndex2b[1] == itkIndex2[1])),
"Testing itk::index<2> for IndexToWorld/WorldToIndex consistency");
geometry3d->IndexToWorld(itkIndex3, point);
geometry3d->WorldToIndex(point, itkIndex3b);
MITK_TEST_CONDITION_REQUIRED(
((itkIndex3b[0] == itkIndex3[0]) && (itkIndex3b[1] == itkIndex3[1]) && (itkIndex3b[2] == itkIndex3[2])),
"Testing itk::index<3> for IndexToWorld/WorldToIndex consistency");
geometry3d->IndexToWorld(itkIndex4, point);
geometry3d->WorldToIndex(point, itkIndex4b);
MITK_TEST_CONDITION_REQUIRED(((itkIndex4b[0] == itkIndex4[0]) && (itkIndex4b[1] == itkIndex4[1]) &&
(itkIndex4b[2] == itkIndex4[2]) && (itkIndex4b[3] == 0)),
"Testing itk::index<3> for IndexToWorld/WorldToIndex consistency");
geometry3d->IndexToWorld(mitkIndex, point);
geometry3d->WorldToIndex(point, mitkIndexb);
MITK_TEST_CONDITION_REQUIRED(
((mitkIndexb[0] == mitkIndex[0]) && (mitkIndexb[1] == mitkIndex[1]) && (mitkIndexb[2] == mitkIndex[2])),
"Testing mitk::Index for IndexToWorld/WorldToIndex consistency");
return EXIT_SUCCESS;
}
#include <itkImage.h>
int testItkImageIsCenterBased()
{
MITK_TEST_OUTPUT(<< "Testing whether itk::Image coordinates are center-based.");
typedef itk::Image<int, 3> ItkIntImage3D;
ItkIntImage3D::Pointer itkintimage = ItkIntImage3D::New();
ItkIntImage3D::SizeType size;
size.Fill(10);
mitk::Point3D origin;
mitk::FillVector3D(origin, 2, 3, 7);
itkintimage->Initialize();
itkintimage->SetRegions(size);
itkintimage->SetOrigin(origin);
std::cout << "[PASSED]" << std::endl;
MITK_TEST_OUTPUT(<< " Testing itk::Image::TransformPhysicalPointToContinuousIndex(origin)==(0,0,0)");
mitk::Point3D globalOrigin;
mitk::FillVector3D(globalOrigin, 0, 0, 0);
itk::ContinuousIndex<mitk::ScalarType, 3> originContinuousIndex;
itkintimage->TransformPhysicalPointToContinuousIndex(origin, originContinuousIndex);
MITK_TEST_CONDITION_REQUIRED(originContinuousIndex == globalOrigin, "");
MITK_TEST_OUTPUT(<< " Testing itk::Image::TransformPhysicalPointToIndex(origin)==(0,0,0)");
itk::Index<3> itkindex;
itkintimage->TransformPhysicalPointToIndex(origin, itkindex);
itk::Index<3> globalOriginIndex;
mitk::vtk2itk(globalOrigin, globalOriginIndex);
MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
MITK_TEST_OUTPUT(<< " Testing itk::Image::TransformPhysicalPointToIndex(origin-0.5*spacing)==(0,0,0)");
mitk::Vector3D halfSpacingStep = itkintimage->GetSpacing() * 0.5;
mitk::Matrix3D rotation;
mitk::Point3D originOffCenter = origin - halfSpacingStep;
itkintimage->TransformPhysicalPointToIndex(originOffCenter, itkindex);
MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
MITK_TEST_OUTPUT(
<< " Testing itk::Image::TransformPhysicalPointToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0)");
originOffCenter = origin + halfSpacingStep;
- originOffCenter -= 0.0001;
+ originOffCenter -= mitk::Vector(0.0001);
itkintimage->TransformPhysicalPointToIndex(originOffCenter, itkindex);
MITK_TEST_CONDITION_REQUIRED(itkindex == globalOriginIndex, "");
MITK_TEST_OUTPUT(<< " Testing itk::Image::TransformPhysicalPointToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)");
originOffCenter = origin + halfSpacingStep;
itk::Index<3> global111;
mitk::FillVector3D(global111, 1, 1, 1);
itkintimage->TransformPhysicalPointToIndex(originOffCenter, itkindex);
MITK_TEST_CONDITION_REQUIRED(itkindex == global111, "");
MITK_TEST_OUTPUT(<< "=> Yes, itk::Image coordinates are center-based.");
return EXIT_SUCCESS;
}
int testGeometry3D(bool imageGeometry)
{
// Build up a new image Geometry
mitk::Geometry3D::Pointer geometry3d = mitk::Geometry3D::New();
float bounds[] = {-10.0, 17.0, -12.0, 188.0, 13.0, 211.0};
MITK_TEST_OUTPUT(<< "Initializing");
geometry3d->Initialize();
MITK_TEST_OUTPUT(<< "Setting ImageGeometry to " << imageGeometry);
geometry3d->SetImageGeometry(imageGeometry);
MITK_TEST_OUTPUT(<< "Setting bounds by SetFloatBounds(): " << bounds);
geometry3d->SetFloatBounds(bounds);
MITK_TEST_OUTPUT(<< "Testing AxisVectors");
if (testGetAxisVectorVariants(geometry3d) == false)
return EXIT_FAILURE;
if (testGetAxisVectorExtent(geometry3d) == false)
return EXIT_FAILURE;
MITK_TEST_OUTPUT(<< "Creating an AffineTransform3D transform");
mitk::AffineTransform3D::MatrixType matrix;
matrix.SetIdentity();
matrix(1, 1) = 2;
mitk::AffineTransform3D::Pointer transform;
transform = mitk::AffineTransform3D::New();
transform->SetMatrix(matrix);
MITK_TEST_OUTPUT(<< "Testing a SetIndexToWorldTransform");
geometry3d->SetIndexToWorldTransform(transform);
MITK_TEST_OUTPUT(<< "Testing correctness of value returned by GetSpacing");
const mitk::Vector3D &spacing1 = geometry3d->GetSpacing();
mitk::Vector3D expectedSpacing;
expectedSpacing.Fill(1.0);
expectedSpacing[1] = 2;
if (mitk::Equal(spacing1, expectedSpacing) == false)
{
MITK_TEST_OUTPUT(<< " [FAILED]");
return EXIT_FAILURE;
}
MITK_TEST_OUTPUT(<< "Testing a Compose(transform)");
geometry3d->Compose(transform);
MITK_TEST_OUTPUT(<< "Testing correctness of value returned by GetSpacing");
const mitk::Vector3D &spacing2 = geometry3d->GetSpacing();
expectedSpacing[1] = 4;
if (mitk::Equal(spacing2, expectedSpacing) == false)
{
MITK_TEST_OUTPUT(<< " [FAILED]");
return EXIT_FAILURE;
}
MITK_TEST_OUTPUT(<< "Testing correctness of SetSpacing");
mitk::Vector3D newspacing;
mitk::FillVector3D(newspacing, 1.5, 2.5, 3.5);
geometry3d->SetSpacing(newspacing);
const mitk::Vector3D &spacing3 = geometry3d->GetSpacing();
if (mitk::Equal(spacing3, newspacing) == false)
{
MITK_TEST_OUTPUT(<< " [FAILED]");
return EXIT_FAILURE;
}
// Separate Test function for Index and World consistency
testIndexAndWorldConsistency(geometry3d);
testIndexAndWorldConsistencyForVectors(geometry3d);
testIndexAndWorldConsistencyForIndex(geometry3d);
MITK_TEST_OUTPUT(<< "Testing a rotation of the geometry");
double angle = 35.0;
mitk::Vector3D rotationVector;
mitk::FillVector3D(rotationVector, 1, 0, 0);
mitk::Point3D center = geometry3d->GetCenter();
auto op = new mitk::RotationOperation(mitk::OpROTATE, center, rotationVector, angle);
geometry3d->ExecuteOperation(op);
MITK_TEST_OUTPUT(<< "Testing mitk::GetRotation() and success of rotation");
mitk::Matrix3D rotation;
mitk::GetRotation(geometry3d, rotation);
mitk::Vector3D voxelStep = rotation * newspacing;
mitk::Vector3D voxelStepIndex;
geometry3d->WorldToIndex(voxelStep, voxelStepIndex);
mitk::Vector3D expectedVoxelStepIndex;
expectedVoxelStepIndex.Fill(1);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(voxelStepIndex, expectedVoxelStepIndex), "");
delete op;
std::cout << "[PASSED]" << std::endl;
MITK_TEST_OUTPUT(<< "Testing that ImageGeometry is still " << imageGeometry);
MITK_TEST_CONDITION_REQUIRED(geometry3d->GetImageGeometry() == imageGeometry, "");
// Test if the translate function moves the origin correctly.
mitk::Point3D oldOrigin = geometry3d->GetOrigin();
// use some random values for translation
mitk::Vector3D translationVector;
translationVector.SetElement(0, 17.5f);
translationVector.SetElement(1, -32.3f);
translationVector.SetElement(2, 4.0f);
// compute ground truth
mitk::Point3D tmpResult = geometry3d->GetOrigin() + translationVector;
geometry3d->Translate(translationVector);
MITK_TEST_CONDITION(mitk::Equal(geometry3d->GetOrigin(), tmpResult), "Testing if origin was translated.");
translationVector *= -1; // vice versa
geometry3d->Translate(translationVector);
MITK_TEST_CONDITION(mitk::Equal(geometry3d->GetOrigin(), oldOrigin),
"Testing if the translation could be done vice versa.");
return EXIT_SUCCESS;
}
int testGeometryAfterCasting()
{
// Epsilon. Allowed difference for rotationvalue
float eps = 0.0001;
// Cast ITK and MITK images and see if geometry stays
typedef itk::Image<char, 2> Image2DType;
typedef itk::Image<char, 3> Image3DType;
// Create 3D ITK Image from Scratch, cast to 3D MITK image, compare Geometries
Image3DType::Pointer image3DItk = Image3DType::New();
Image3DType::RegionType myRegion;
Image3DType::SizeType mySize;
Image3DType::IndexType myIndex;
Image3DType::SpacingType mySpacing;
Image3DType::DirectionType myDirection, rotMatrixX, rotMatrixY, rotMatrixZ;
mySpacing[0] = 31;
mySpacing[1] = 0.1;
mySpacing[2] = 2.9;
myIndex[0] = -15;
myIndex[1] = 15;
myIndex[2] = 12;
mySize[0] = 10;
mySize[1] = 2;
mySize[2] = 5;
myRegion.SetSize(mySize);
myRegion.SetIndex(myIndex);
image3DItk->SetSpacing(mySpacing);
image3DItk->SetRegions(myRegion);
image3DItk->Allocate();
image3DItk->FillBuffer(0);
myDirection.SetIdentity();
rotMatrixX.SetIdentity();
rotMatrixY.SetIdentity();
rotMatrixZ.SetIdentity();
mitk::Image::Pointer mitkImage;
// direction [row] [column]
MITK_TEST_OUTPUT(<< "Casting a rotated 3D ITK Image to a MITK Image and check if Geometry is still same");
for (double rotX = 0; rotX < itk::Math::pi * 2; rotX += itk::Math::pi * 0.4)
{
// Set Rotation X
rotMatrixX[1][1] = cos(rotX);
rotMatrixX[1][2] = -sin(rotX);
rotMatrixX[2][1] = sin(rotX);
rotMatrixX[2][2] = cos(rotX);
for (double rotY = 0; rotY < itk::Math::pi * 2; rotY += itk::Math::pi * 0.3)
{
// Set Rotation Y
rotMatrixY[0][0] = cos(rotY);
rotMatrixY[0][2] = sin(rotY);
rotMatrixY[2][0] = -sin(rotY);
rotMatrixY[2][2] = cos(rotY);
for (double rotZ = 0; rotZ < itk::Math::pi * 2; rotZ += itk::Math::pi * 0.2)
{
// Set Rotation Z
rotMatrixZ[0][0] = cos(rotZ);
rotMatrixZ[0][1] = -sin(rotZ);
rotMatrixZ[1][0] = sin(rotZ);
rotMatrixZ[1][1] = cos(rotZ);
// Multiply matrizes
myDirection = myDirection * rotMatrixX * rotMatrixY * rotMatrixZ;
image3DItk->SetDirection(myDirection);
mitk::CastToMitkImage(image3DItk, mitkImage);
const mitk::AffineTransform3D::MatrixType &matrix =
mitkImage->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
double mitkValue = matrix[row][col] / mitkImage->GetGeometry()->GetSpacing()[col];
double itkValue = myDirection[row][col];
double diff = mitkValue - itkValue;
// if you decrease this value, you can see that there might be QUITE high inaccuracy!!!
if (diff > eps) // need to check, how exact it SHOULD be .. since it is NOT EXACT!
{
std::cout << "Had a difference of : " << diff;
std::cout << "Error: Casting altered Geometry!";
std::cout << "ITK Matrix:\n" << myDirection;
std::cout << "Mitk Matrix (With Spacing):\n" << matrix;
std::cout << "Mitk Spacing: " << mitkImage->GetGeometry()->GetSpacing();
MITK_TEST_CONDITION_REQUIRED(false == true, "");
return false;
}
}
}
}
}
}
// Create 2D ITK Image from Scratch, cast to 2D MITK image, compare Geometries
Image2DType::Pointer image2DItk = Image2DType::New();
Image2DType::RegionType myRegion2D;
Image2DType::SizeType mySize2D;
Image2DType::IndexType myIndex2D;
Image2DType::SpacingType mySpacing2D;
Image2DType::DirectionType myDirection2D, rotMatrix;
mySpacing2D[0] = 31;
mySpacing2D[1] = 0.1;
myIndex2D[0] = -15;
myIndex2D[1] = 15;
mySize2D[0] = 10;
mySize2D[1] = 2;
myRegion2D.SetSize(mySize2D);
myRegion2D.SetIndex(myIndex2D);
image2DItk->SetSpacing(mySpacing2D);
image2DItk->SetRegions(myRegion2D);
image2DItk->Allocate();
image2DItk->FillBuffer(0);
myDirection2D.SetIdentity();
rotMatrix.SetIdentity();
// direction [row] [column]
MITK_TEST_OUTPUT(<< "Casting a rotated 2D ITK Image to a MITK Image and check if Geometry is still same");
for (double rotTheta = 0; rotTheta < itk::Math::pi * 2; rotTheta += itk::Math::pi * 0.2)
{
// Set Rotation
rotMatrix[0][0] = cos(rotTheta);
rotMatrix[0][1] = -sin(rotTheta);
rotMatrix[1][0] = sin(rotTheta);
rotMatrix[1][1] = cos(rotTheta);
// Multiply matrizes
myDirection2D = myDirection2D * rotMatrix;
image2DItk->SetDirection(myDirection2D);
mitk::CastToMitkImage(image2DItk, mitkImage);
const mitk::AffineTransform3D::MatrixType &matrix =
mitkImage->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
// Compare MITK and ITK matrix
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
double mitkValue = matrix[row][col] / mitkImage->GetGeometry()->GetSpacing()[col];
if ((row == 2) && (col == row))
{
if (mitkValue != 1)
{
MITK_TEST_OUTPUT(<< "After casting a 2D ITK to 3D MITK images, MITK matrix values for 0|2, 1|2, 2|0, 2|1 "
"MUST be 0 and value for 2|2 must be 1");
return false;
}
}
else if ((row == 2) || (col == 2))
{
if (mitkValue != 0)
{
MITK_TEST_OUTPUT(<< "After casting a 2D ITK to 3D MITK images, MITK matrix values for 0|2, 1|2, 2|0, 2|1 "
"MUST be 0 and value for 2|2 must be 1");
return false;
}
}
else
{
double itkValue = myDirection2D[row][col];
double diff = mitkValue - itkValue;
// if you decrease this value, you can see that there might be QUITE high inaccuracy!!!
if (diff > eps) // need to check, how exact it SHOULD be .. since it is NOT EXACT!
{
std::cout << "Had a difference of : " << diff;
std::cout << "Error: Casting altered Geometry!";
std::cout << "ITK Matrix:\n" << myDirection2D;
std::cout << "Mitk Matrix (With Spacing):\n" << matrix;
std::cout << "Mitk Spacing: " << mitkImage->GetGeometry()->GetSpacing();
MITK_TEST_CONDITION_REQUIRED(false == true, "");
return false;
}
}
}
}
}
// THIS WAS TESTED:
// 2D ITK -> 2D MITK,
// 3D ITK -> 3D MITK,
// Still need to test: 2D MITK Image with ADDITIONAL INFORMATION IN MATRIX -> 2D ITK
// 1. Possibility: 3x3 MITK matrix can be converted without loss into 2x2 ITK matrix
// 2. Possibility: 3x3 MITK matrix can only be converted with loss into 2x2 ITK matrix
// .. before implementing this, we wait for further development in geometry classes (e.g. Geoemtry3D::SetRotation(..))
return EXIT_SUCCESS;
}
int mitkGeometry3DTest(int /*argc*/, char * /*argv*/ [])
{
MITK_TEST_BEGIN(mitkGeometry3DTest);
int result;
MITK_TEST_CONDITION_REQUIRED((result = testItkImageIsCenterBased()) == EXIT_SUCCESS, "");
MITK_TEST_OUTPUT(<< "Running main part of test with ImageGeometry = false");
MITK_TEST_CONDITION_REQUIRED((result = testGeometry3D(false)) == EXIT_SUCCESS, "");
MITK_TEST_OUTPUT(<< "Running main part of test with ImageGeometry = true");
MITK_TEST_CONDITION_REQUIRED((result = testGeometry3D(true)) == EXIT_SUCCESS, "");
MITK_TEST_OUTPUT(<< "Running test to see if Casting MITK to ITK and the other way around destroys geometry");
MITK_TEST_CONDITION_REQUIRED((result = testGeometryAfterCasting()) == EXIT_SUCCESS, "");
MITK_TEST_END();
return EXIT_SUCCESS;
}
diff --git a/Modules/Core/test/mitkLogTest.cpp b/Modules/Core/test/mitkLogTest.cpp
index 03ec18cf4e..cc3e99ef9d 100644
--- a/Modules/Core/test/mitkLogTest.cpp
+++ b/Modules/Core/test/mitkLogTest.cpp
@@ -1,300 +1,299 @@
/*============================================================================
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 "mitkCommon.h"
#include "mitkTestingMacros.h"
#include <itksys/SystemTools.hxx>
#include <mitkLog.h>
+#include <mitkLogBackend.h>
+#include <mitkLogBackendCout.h>
#include <mitkNumericTypes.h>
#include <mitkStandardFileLocations.h>
#include <thread>
#include <mitkUtf8Util.h>
/** Documentation
*
* @brief this class provides an accessible BackendCout to determine whether this backend was
* used to process a message or not.
* It is needed for the disable / enable backend test.
*/
-class TestBackendCout : public mbilog::BackendCout
+class TestBackendCout : public mitk::LogBackendCout
{
public:
TestBackendCout()
+ : m_Called(false)
{
- m_Called = false;
- mbilog::BackendCout();
}
- void ProcessMessage(const mbilog::LogMessage &l) override
+ void ProcessMessage(const mitk::LogMessage& message) override
{
m_Called = true;
- mbilog::BackendCout::ProcessMessage(l);
+ mitk::LogBackendCout::ProcessMessage(message);
+ }
+
+ bool WasCalled()
+ {
+ return m_Called;
}
- bool WasCalled() { return m_Called; }
private:
bool m_Called;
};
/** Documentation
*
* @brief Objects of this class can start an internal thread by calling the Start() method.
* The thread is then logging messages until the method Stop() is called. The class
* can be used to test if logging is thread-save by using multiple objects and let
* them log simuntanously.
*/
class mitkTestLoggingThread : public itk::Object
{
public:
mitkClassMacroItkParent(mitkTestLoggingThread, itk::Object);
itkFactorylessNewMacro(Self);
int NumberOfMessages;
protected:
mitkTestLoggingThread()
: NumberOfMessages(0),
LoggingRunning(true)
{
}
~mitkTestLoggingThread()
{
this->Stop();
}
bool LoggingRunning;
std::thread Thread;
void LogMessages()
{
auto ThreadID = Thread.get_id();
while (LoggingRunning)
{
MITK_INFO << "Test info stream in thread" << ThreadID << "\n even with newlines";
MITK_WARN << "Test warning stream in thread " << ThreadID << ". "
<< "Even with a very long text, even without meaning or implied meaning or content, just a long "
"sentence to see whether something has problems with long sentences or output in files or into "
"windows or commandlines or whatever.";
MITK_DEBUG << "Test debugging stream in thread " << ThreadID;
MITK_ERROR << "Test error stream in thread " << ThreadID;
MITK_FATAL << "Test fatal stream in thread " << ThreadID;
NumberOfMessages += 5;
}
}
static void ThreadStartTracking(void *instance)
{
auto* thisthread = reinterpret_cast<mitkTestLoggingThread*>(instance);
if (thisthread != nullptr)
thisthread->LogMessages();
}
public:
std::thread::id Start()
{
LoggingRunning = true;
Thread = std::thread(this->ThreadStartTracking, this);
return Thread.get_id();
}
void Stop()
{
LoggingRunning = false;
if(Thread.joinable())
Thread.join();
}
};
/** Documentation
*
* @brief This class holds static test methods to structure the test of the mitk logging mechanism.
*/
class mitkLogTestClass
{
public:
static void TestSimpleLog()
{
bool testSucceded = true;
try
{
MITK_INFO << "Test info stream.";
MITK_WARN << "Test warning stream.";
MITK_DEBUG << "Test debugging stream."; // only activated if cmake variable is on!
// so no worries if you see no output for this line
MITK_ERROR << "Test error stream.";
MITK_FATAL << "Test fatal stream.";
}
catch (const mitk::Exception &)
{
testSucceded = false;
}
MITK_TEST_CONDITION_REQUIRED(testSucceded, "Test logging streams.");
}
static void TestObjectInfoLogging()
{
bool testSucceded = true;
try
{
int i = 123;
float f = .32234;
double d = 123123;
std::string testString = "testString";
std::stringstream testStringStream;
testStringStream << "test"
<< "String"
<< "Stream";
mitk::Point3D testMitkPoint;
testMitkPoint.Fill(2);
MITK_INFO << i;
MITK_INFO << f;
MITK_INFO << d;
MITK_INFO << testString;
MITK_INFO << testStringStream.str();
MITK_INFO << testMitkPoint;
}
catch (const mitk::Exception &)
{
testSucceded = false;
}
MITK_TEST_CONDITION_REQUIRED(testSucceded, "Test logging of object information.");
}
static void TestThreadSaveLog(bool toFile)
{
bool testSucceded = true;
try
{
if (toFile)
{
std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + "/testthreadlog.log";
itksys::SystemTools::RemoveFile(mitk::Utf8Util::Local8BitToUtf8(filename).c_str()); // remove old file, we do not want to append to large files
- mitk::LoggingBackend::SetLogFile(filename.c_str());
+ mitk::LogBackend::SetLogFile(filename);
}
unsigned int numberOfThreads = 20;
unsigned int threadRuntimeInMilliseconds = 2000;
std::vector<std::thread::id> threadIDs;
std::vector<mitkTestLoggingThread::Pointer> threads;
for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
{
// initialize threads...
threads.push_back(mitkTestLoggingThread::New());
std::cout << "Created " << threadIdx << ". thread." << std::endl;
}
for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
{
// start them
std::cout << "Start " << threadIdx << ". thread." << std::endl;
threadIDs.push_back(threads[threadIdx]->Start());
std::cout << threadIdx << ". thread has ID " << threadIDs[threadIdx] << std::endl;
}
// wait for some time (milliseconds)
itksys::SystemTools::Delay(threadRuntimeInMilliseconds);
for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
{
// stop them and wait for them to end
std::cout << "Stop " << threadIdx << ". thread." << std::endl;
threads[threadIdx]->Stop();
std::cout << "Terminated " << threadIdx << ". thread (" << threads[threadIdx]->NumberOfMessages << " messages)." << std::endl;
}
}
catch (std::exception &e)
{
MITK_ERROR << "exception during 'TestThreadSaveLog': " << e.what();
testSucceded = false;
}
catch (...)
{
MITK_ERROR << "unknown exception during 'TestThreadSaveLog'";
testSucceded = false;
}
// if no error occurred until now, everything is ok
MITK_TEST_CONDITION_REQUIRED(testSucceded, "Test logging in different threads.");
}
static void TestLoggingToFile()
{
std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + "/testlog.log";
- mitk::LoggingBackend::SetLogFile(filename.c_str());
- MITK_INFO << "Test logging to default filename: " << mitk::LoggingBackend::GetLogFile();
+ mitk::LogBackend::SetLogFile(filename);
+ MITK_INFO << "Test logging to default filename: " << mitk::LogBackend::GetLogFile();
MITK_TEST_CONDITION_REQUIRED(itksys::SystemTools::FileExists(mitk::Utf8Util::Local8BitToUtf8(filename).c_str()), "Testing if log file exists.");
// TODO delete log file?
}
static void TestAddAndRemoveBackends()
{
- mbilog::BackendCout myBackend = mbilog::BackendCout();
- mbilog::RegisterBackend(&myBackend);
+ mitk::LogBackendCout myBackend;
+ mitk::RegisterBackend(&myBackend);
MITK_INFO << "Test logging";
- mbilog::UnregisterBackend(&myBackend);
+ mitk::UnregisterBackend(&myBackend);
// if no error occurred until now, everything is ok
MITK_TEST_CONDITION_REQUIRED(true, "Test add/remove logging backend.");
}
- static void TestDefaultBackend()
- {
- // not possible now, because we cannot unregister the mitk logging backend in the moment. If such a method is added
- // to mbilog utility one may add this test.
- }
-
static void TestEnableDisableBackends()
{
- TestBackendCout myCoutBackend = TestBackendCout();
- mbilog::RegisterBackend(&myCoutBackend);
+ TestBackendCout myCoutBackend;
+ mitk::RegisterBackend(&myCoutBackend);
- mbilog::DisableBackends(mbilog::Console);
+ mitk::DisableBackends(mitk::LogBackendBase::OutputType::Console);
MITK_INFO << "There should be no output!";
bool success = !myCoutBackend.WasCalled();
- mbilog::EnableBackends(mbilog::Console);
+ mitk::EnableBackends(mitk::LogBackendBase::OutputType::Console);
MITK_INFO << "Now there should be an output.";
success &= myCoutBackend.WasCalled();
- mbilog::UnregisterBackend(&myCoutBackend);
+ mitk::UnregisterBackend(&myCoutBackend);
MITK_TEST_CONDITION_REQUIRED(success, "Test disable / enable logging backends.")
}
};
int mitkLogTest(int /* argc */, char * /*argv*/ [])
{
// always start with this!
MITK_TEST_BEGIN("Log")
MITK_TEST_OUTPUT(<< "TESTING ALL LOGGING OUTPUTS, ERROR MESSAGES ARE ALSO TESTED AND NOT MEANING AN ERROR OCCURRED!")
mitkLogTestClass::TestSimpleLog();
mitkLogTestClass::TestObjectInfoLogging();
mitkLogTestClass::TestLoggingToFile();
mitkLogTestClass::TestAddAndRemoveBackends();
mitkLogTestClass::TestThreadSaveLog(false); // false = to console
mitkLogTestClass::TestThreadSaveLog(true); // true = to file
mitkLogTestClass::TestEnableDisableBackends();
// TODO actually test file somehow?
// always end with this!
MITK_TEST_END()
}
diff --git a/Modules/Core/test/mitkPixelTypeTest.cpp b/Modules/Core/test/mitkPixelTypeTest.cpp
index 0f4ad40e51..f51ee816cc 100644
--- a/Modules/Core/test/mitkPixelTypeTest.cpp
+++ b/Modules/Core/test/mitkPixelTypeTest.cpp
@@ -1,241 +1,241 @@
/*============================================================================
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.
============================================================================*/
// Testing
#include "mitkTestFixture.h"
#include "mitkTestingMacros.h"
// std includes
#include <string>
// MITK includes
#include "mitkPixelType.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
// ITK includes
#include "itkImage.h"
#include <itkVectorImage.h>
// VTK includes
#include <vtkDebugLeaks.h>
struct MyObscurePixelType
{
typedef float ValueType;
static const size_t Length = 2;
};
//## Documentation
//## main testing method
class mitkPixelTypeTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkPixelTypeTestSuite);
MITK_TEST(GetComponentType_Success);
MITK_TEST(GetPixelTypeAsString_Success);
MITK_TEST(GetBpePtype_Success);
MITK_TEST(GetNumberOfComponentsPtype_Success);
MITK_TEST(GetBitsPerComponentPtype_Success);
MITK_TEST(GetBpeItkPtype_Success);
MITK_TEST(GetNumberOfComponentsItkPtype_Success);
MITK_TEST(GetBitsPerComponentItkPtype_Success);
MITK_TEST(ConstructorWithBrackets_Success);
MITK_TEST(InitializeWithEqualSign_Success);
MITK_TEST(EqualityOperator_Success);
MITK_TEST(NotEqualityOperator_Success);
MITK_TEST(GetPixelTypeUnknown_Success);
MITK_TEST(SetLengthCorrectly_Success);
MITK_TEST(ValueTypeCorresponds_Success);
MITK_TEST(ImageTypeTraitInt3D_Success);
MITK_TEST(ImageTypeTraitShort2D_Success);
MITK_TEST(ImageTypeTraitVectorShort3D_Success);
MITK_TEST(ImageTypeTraitItkInt3D_Success);
MITK_TEST(ImageTypeTraitItkShort2D_Success);
MITK_TEST(ImageTypeTraitItkVectorShort3D_Success);
CPPUNIT_TEST_SUITE_END();
private:
typedef itk::Image<itk::FixedArray<int, 5>, 3> ItkImageType;
typedef itk::Image<MyObscurePixelType> MyObscureImageType;
typedef itk::VectorImage<short, 3> VectorImageType;
typedef itk::Image<itk::Vector<short, 7>> FixedVectorImageType;
public:
void setUp() override
{
}
void tearDown() override
{
}
void GetComponentType_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
MITK_INFO << "m_Ptype = mitk::MakePixelType<int, int, 5>();";
MITK_INFO
<< "m_ItkPtype = mitk::MakePixelType<ItkImageType>();\n with itk::Image<itk::FixedArray< int, 5>, 3> ItkImageType";
CPPUNIT_ASSERT_MESSAGE("GetComponentType()", ptype.GetComponentType() == itk::IOComponentEnum::INT);
}
void GetPixelTypeAsString_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
MITK_INFO << ptype.GetPixelTypeAsString();
MITK_INFO << typeid(ItkImageType).name();
}
void GetBpePtype_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
CPPUNIT_ASSERT_MESSAGE("[m_Ptype] GetBpe()", ptype.GetBpe() == 8 * sizeof(int) * 5);
}
void GetNumberOfComponentsPtype_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
CPPUNIT_ASSERT_MESSAGE("[ptype]GetNumberOfComponents()", ptype.GetNumberOfComponents() == 5);
}
void GetBitsPerComponentPtype_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
CPPUNIT_ASSERT_MESSAGE("[ptype]GetBitsPerComponent()", ptype.GetBitsPerComponent() == 8 * sizeof(int));
}
void GetBpeItkPtype_Success()
{
mitk::PixelType itkPtype = mitk::MakePixelType<ItkImageType>();
CPPUNIT_ASSERT_MESSAGE("[itkPType] GetBpe()", itkPtype.GetBpe() == 8 * sizeof(int) * 5);
}
void GetNumberOfComponentsItkPtype_Success()
{
mitk::PixelType itkPtype = mitk::MakePixelType<ItkImageType>();
CPPUNIT_ASSERT_MESSAGE("[itkPType] GetNumberOfComponents()", itkPtype.GetNumberOfComponents() == 5);
}
void GetBitsPerComponentItkPtype_Success()
{
mitk::PixelType itkPtype = mitk::MakePixelType<ItkImageType>();
CPPUNIT_ASSERT_MESSAGE("[itkPType] GetBitsPerComponent()", itkPtype.GetBitsPerComponent() == 8 * sizeof(int));
}
void ConstructorWithBrackets_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
mitk::PixelType ptype2(ptype);
CPPUNIT_ASSERT_MESSAGE("ptype2( ptype)- GetComponentType()", ptype2.GetComponentType() == itk::IOComponentEnum::INT);
CPPUNIT_ASSERT_MESSAGE("ptype2( ptype)-GetPixelType(", ptype2.GetPixelType() == ptype.GetPixelType());
CPPUNIT_ASSERT_MESSAGE("ptype2( ptype)-GetComponentType(", ptype2.GetComponentType() == ptype.GetComponentType());
CPPUNIT_ASSERT_MESSAGE("ptype2( ptype)-GetBpe()", ptype2.GetBpe() == 8 * sizeof(int) * 5);
CPPUNIT_ASSERT_MESSAGE("ptype2( ptype)-GetNumberOfComponents()", ptype2.GetNumberOfComponents() == 5);
CPPUNIT_ASSERT_MESSAGE("ptype2( ptype)-GetBitsPerComponent()", ptype2.GetBitsPerComponent() == 8 * sizeof(int));
}
void InitializeWithEqualSign_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
mitk::PixelType ptype2 = ptype;
CPPUNIT_ASSERT_MESSAGE("ptype2 = ptype- GetComponentType()", ptype2.GetComponentType() == itk::IOComponentEnum::INT);
CPPUNIT_ASSERT_MESSAGE("ptype2 = ptype- GetPixelType(", ptype2.GetPixelType() == ptype.GetPixelType());
CPPUNIT_ASSERT_MESSAGE("ptype2( ptype)-GetComponentType(", ptype2.GetComponentType() == ptype.GetComponentType());
CPPUNIT_ASSERT_MESSAGE("ptype2 = ptype- GetBpe()", ptype2.GetBpe() == 8 * sizeof(int) * 5);
CPPUNIT_ASSERT_MESSAGE("ptype2 = ptype- GetNumberOfComponents()", ptype2.GetNumberOfComponents() == 5);
CPPUNIT_ASSERT_MESSAGE("ptype2 = ptype- GetBitsPerComponent()", ptype2.GetBitsPerComponent() == 8 * sizeof(int));
}
void EqualityOperator_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
mitk::PixelType ptype2 = ptype;
CPPUNIT_ASSERT_MESSAGE("operator ==", ptype == ptype2);
}
void NotEqualityOperator_Success()
{
mitk::PixelType ptype = mitk::MakePixelType<int, int, 5>();
mitk::PixelType ptype3 = mitk::MakePixelType<char, char ,5>();
CPPUNIT_ASSERT_MESSAGE("operator !=", ptype != ptype3);
}
void GetPixelTypeUnknown_Success()
{
// test instantiation
mitk::PixelType obscurePixelType = mitk::MakePixelType<MyObscureImageType>();
CPPUNIT_ASSERT_MESSAGE("PixelTypeId is 'UNKNOWN' ", obscurePixelType.GetPixelType() == itk::IOPixelEnum::UNKNOWNPIXELTYPE);
}
void SetLengthCorrectly_Success()
{
mitk::PixelType obscurePixelType = mitk::MakePixelType<MyObscureImageType>();
CPPUNIT_ASSERT_MESSAGE("Length was set correctly", obscurePixelType.GetNumberOfComponents() == MyObscurePixelType::Length);
}
void ValueTypeCorresponds_Success()
{
mitk::PixelType obscurePixelType = mitk::MakePixelType<MyObscureImageType>();
CPPUNIT_ASSERT_MESSAGE("ValueType corresponds.",
obscurePixelType.GetComponentType() == mitk::MapPixelComponentType<MyObscurePixelType::ValueType>::value);
}
void ImageTypeTraitInt3D_Success()
{
// test ImageTypeTrait traits class
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid int 3D equals ITK typeid",
typeid(mitk::ImageTypeTrait<int, 3>::ImageType) == typeid(itk::Image<int, 3>));
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image", (mitk::ImageTypeTrait<int, 3>::IsVectorImage == false));
}
void ImageTypeTraitShort2D_Success()
{
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid short 2D equals ITK typeid",
typeid(mitk::ImageTypeTrait<itk::FixedArray<short, 2>, 3>::ImageType) ==
typeid(itk::Image<itk::FixedArray<short, 2>, 3>));
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image", (mitk::ImageTypeTrait<itk::FixedArray<short, 2>, 3>::IsVectorImage == false));
}
void ImageTypeTraitVectorShort3D_Success()
{
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid short 3D equals ITK typeid",
typeid(mitk::ImageTypeTrait<itk::VariableLengthVector<short>, 3>::ImageType) == typeid(itk::VectorImage<short, 3>));
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is a vector image", (mitk::ImageTypeTrait<itk::VariableLengthVector<short>, 3>::IsVectorImage == true));
}
void ImageTypeTraitItkInt3D_Success()
{
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid ITK int 3D equals ITK typeid",
typeid(mitk::ImageTypeTrait<itk::Image<int, 3>>::ImageType) == typeid(itk::Image<int, 3>));
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image", (mitk::ImageTypeTrait<itk::Image<int, 3>>::IsVectorImage == false));
}
void ImageTypeTraitItkShort2D_Success()
{
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid ITK short 2D equals ITK typeid",
typeid(mitk::ImageTypeTrait<itk::Image<itk::FixedArray<short, 2>, 3>>::ImageType) ==
typeid(itk::Image<itk::FixedArray<short, 2>, 3>));
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image",
(mitk::ImageTypeTrait<itk::Image<itk::FixedArray<short, 2>, 3>>::IsVectorImage == false));
}
void ImageTypeTraitItkVectorShort3D_Success()
{
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid ITK short 3D equals ITK typeid",
typeid(mitk::ImageTypeTrait<itk::VectorImage<short, 3>>::ImageType) == typeid(itk::VectorImage<short, 3>));
CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is a vector image",
(mitk::ImageTypeTrait<itk::VectorImage<short, 3>>::IsVectorImage == true));
}
};
MITK_TEST_SUITE_REGISTRATION(mitkPixelType)
diff --git a/Modules/Core/test/mitkPointTypeConversionTest.cpp b/Modules/Core/test/mitkPointTypeConversionTest.cpp
index 9b706c1e03..22d6267c35 100644
--- a/Modules/Core/test/mitkPointTypeConversionTest.cpp
+++ b/Modules/Core/test/mitkPointTypeConversionTest.cpp
@@ -1,139 +1,139 @@
/*============================================================================
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 "mitkTestFixture.h"
#include "itkPoint.h"
#include "mitkNumericConstants.h"
#include "mitkNumericTypes.h" // for Equal method
#include "mitkPoint.h"
#include "mitkTestingMacros.h"
#include "vtkPoints.h"
#include "vtkSmartPointer.h"
#include <iostream>
using namespace mitk;
class mitkPointTypeConversionTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkPointTypeConversionTestSuite);
MITK_TEST(Vector2Point);
MITK_TEST(Mitk2Itk_PointCompatibility);
MITK_TEST(Itk2Mitk_PointCompatibility);
MITK_TEST(Vtk2Mitk_PointCompatibility);
MITK_TEST(Mitk2Pod_PointCompatibility);
MITK_TEST(Pod2Mitk_PointCompatibility);
CPPUNIT_TEST_SUITE_END();
private:
vtkSmartPointer<vtkPoints> a_vtkPoints;
ScalarType originalValues[3];
ScalarType valuesToCopy[3];
/**
* @brief Convenience method to test if one vector has been assigned successfully to the other.
*
* More specifically, tests if v1 = v2 was performed correctly.
*
* @param v1 The vector v1 of the assignment v1 = v2
* @param v2 The vector v2 of the assignment v1 = v2
* @param v1Name The type name of v1 (e.g.: mitk::Vector3D). Necessary for the correct test output.
* @param v2Name The type name of v2 (e.g.: mitk::Vector3D). Necessary for the correct test output.
* @param eps defines the allowed tolerance when testing for equality.
*/
template <typename T1, typename T2>
void TestForEquality(T1 v1, T2 v2, std::string v1Name, std::string v2Name, ScalarType eps = mitk::eps)
{
CPPUNIT_ASSERT_EQUAL_MESSAGE(
"\nAssigning " + v2Name + " to " + v1Name + ":\n both are equal", true, EqualArray(v1, v2, 3, eps));
}
public:
void setUp(void) override
{
FillVector3D(originalValues, 1.0, 2.0, 3.0);
FillVector3D(valuesToCopy, 4.0, 5.0, 6.0);
a_vtkPoints = vtkSmartPointer<vtkPoints>::New();
a_vtkPoints->Initialize();
}
void tearDown(void) override
{
// a_vtkPoints = nullptr;
}
void Mitk2Itk_PointCompatibility()
{
mitk::Point3D point3D = valuesToCopy;
itk::Point<ScalarType, 3> itkPoint3D = point3D;
TestForEquality(itkPoint3D, point3D, "itk::Point", "mitk:Point");
}
void Itk2Mitk_PointCompatibility()
{
itk::Point<ScalarType, 3> itkPoint3D = valuesToCopy;
mitk::Point3D point3D = itkPoint3D;
TestForEquality(point3D, itkPoint3D, "mitk:Point", "itk::Point");
}
void Vtk2Mitk_PointCompatibility()
{
a_vtkPoints->InsertNextPoint(valuesToCopy);
double vtkPoint[3];
a_vtkPoints->GetPoint(0, vtkPoint);
mitk::Point3D point3D = vtkPoint;
TestForEquality(point3D, vtkPoint, "mitk:Point", "vtkPoint");
}
void Mitk2Pod_PointCompatibility()
{
ScalarType podPoint[] = {1.0, 2.0, 3.0};
mitk::Point3D point3D = valuesToCopy;
point3D.ToArray(podPoint);
TestForEquality(podPoint, point3D, "POD point", "mitk::Point");
}
void Pod2Mitk_PointCompatibility()
{
ScalarType podPoint[] = {4.0, 5.0, 6.0};
itk::Point<double, 3> point3D = podPoint;
TestForEquality(point3D, podPoint, "mitk::Point3D", "POD point");
}
void Vector2Point()
{
itk::Vector<double, 3> vector3D = originalValues;
- itk::Point<double, 3> point3D = vector3D;
+ itk::Point<double, 3> point3D(vector3D.GetDataPointer());
TestForEquality(point3D, vector3D, "mitk::Point", "mitk::Vector");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkPointTypeConversion)
diff --git a/Modules/Core/test/mitkPropertyTest.cpp b/Modules/Core/test/mitkPropertyTest.cpp
index 3d2fa11b29..93c3d71a83 100644
--- a/Modules/Core/test/mitkPropertyTest.cpp
+++ b/Modules/Core/test/mitkPropertyTest.cpp
@@ -1,489 +1,489 @@
/*============================================================================
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.
============================================================================*/
// Testing
#include "mitkTestFixture.h"
#include "mitkTestingMacros.h"
// std includes
#include <string>
// MITK includes
#include <mitkAnnotationProperty.h>
#include <mitkClippingProperty.h>
#include <mitkColorProperty.h>
#include <mitkLevelWindowProperty.h>
#include <mitkLookupTableProperty.h>
#include <mitkLookupTables.h>
#include <mitkProperties.h>
#include <mitkSmartPointerProperty.h>
#include <mitkStringProperty.h>
#include <mitkTransferFunctionProperty.h>
#include <mitkWeakPointerProperty.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
// ITK includes
#include <itkCommand.h>
// VTK includes
#include <vtkDebugLeaks.h>
struct PropertyModifiedListener
{
typedef itk::SimpleMemberCommand<PropertyModifiedListener> CmdType;
PropertyModifiedListener() : m_Modified(false), m_Cmd(CmdType::New())
{
m_Cmd->SetCallbackFunction(this, &PropertyModifiedListener::Modified);
}
void Modified() { m_Modified = true; }
bool Pop()
{
bool b = m_Modified;
m_Modified = false;
return b;
}
bool m_Modified;
CmdType::Pointer m_Cmd;
};
class mitkPropertyTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkPropertyTestSuite);
MITK_TEST(TestBoolProperty_Success);
MITK_TEST(TestIntProperty_Success);
MITK_TEST(TestFloatProperty_Success);
MITK_TEST(TestDoubleProperty_Success);
MITK_TEST(TestVector3DProperty_Success);
MITK_TEST(TestPoint3D_Success);
MITK_TEST(TestPoint4D_Success);
MITK_TEST(TestPoint3I_Success);
MITK_TEST(TestFloatLookupTable_Success);
MITK_TEST(TestBoolLookupTable_Success);
MITK_TEST(TestIntLookupTable_Success);
MITK_TEST(TestStringLookupTable_Success);
MITK_TEST(TestAnnotationProperty_Success);
MITK_TEST(TestClippingProperty_Success);
MITK_TEST(TestColorProperty_Success);
MITK_TEST(TestLevelWindowProperty_Success);
MITK_TEST(TestSmartPointerProperty_Success);
MITK_TEST(TestStringProperty_Success);
MITK_TEST(TestTransferFunctionProperty_Success);
MITK_TEST(TestWeakPointerProperty_Success);
MITK_TEST(TestLookupTablePropertyProperty_Success);
CPPUNIT_TEST_SUITE_END();
private:
PropertyModifiedListener m_L;
public:
void setUp()
{
}
void tearDown()
{
}
template <class T>
void TestPropInequality(T prop, T prop2)
{
mitk::BaseProperty::Pointer baseProp2(prop2.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Test inequality 1", !(*prop == *prop2));
CPPUNIT_ASSERT_MESSAGE("Test polymorphic inequality 1", !(*prop == *baseProp2));
CPPUNIT_ASSERT_MESSAGE("Test polymorphic inequality 2", !(*baseProp2 == *prop));
}
template <class T>
void TestPropAssignment(T prop, T prop2, const std::string &strProp)
{
unsigned long tag = prop->AddObserver(itk::ModifiedEvent(), m_L.m_Cmd.GetPointer());
mitk::BaseProperty::Pointer baseProp2(prop2.GetPointer());
*prop = *baseProp2;
CPPUNIT_ASSERT_MESSAGE("Test modified event", m_L.Pop());
std::string msg = std::string("Test assignment [") + prop->GetValueAsString() + " == " + strProp + "]";
CPPUNIT_ASSERT_MESSAGE(msg, prop->GetValueAsString() == strProp);
CPPUNIT_ASSERT_MESSAGE("Test equality", *prop == *prop2);
CPPUNIT_ASSERT_MESSAGE("Test equality", *prop == *baseProp2);
CPPUNIT_ASSERT_MESSAGE("Test polymorphic equality", *baseProp2 == *prop);
prop->RemoveObserver(tag);
}
template <class T>
void TestPropPolymorphicAssignment(T prop, T prop2, const std::string &strProp)
{
mitk::BaseProperty::Pointer baseProp(prop.GetPointer());
unsigned long tag = baseProp->AddObserver(itk::ModifiedEvent(), m_L.m_Cmd.GetPointer());
*baseProp = *prop2;
CPPUNIT_ASSERT_MESSAGE("Test modified event", m_L.Pop());
std::string msg =
std::string("Test polymorphic assignment [") + baseProp->GetValueAsString() + " == " + strProp + "]";
CPPUNIT_ASSERT_MESSAGE(msg, baseProp->GetValueAsString() == strProp);
CPPUNIT_ASSERT_MESSAGE("Test equality", *prop == *prop2);
CPPUNIT_ASSERT_MESSAGE("Test equality", *prop2 == *baseProp);
CPPUNIT_ASSERT_MESSAGE("Test polymorphic equality", *baseProp == *prop2);
baseProp->RemoveObserver(tag);
}
template <class T>
void TestPropCloning(T prop)
{
T prop2 = prop->Clone();
CPPUNIT_ASSERT_MESSAGE("Test clone pointer", prop.GetPointer() != prop2.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Test equality of the clone", *prop == *prop2);
}
template <class T>
void TestProperty(const typename T::ValueType &v1,
const typename T::ValueType &v2,
const std::string &strV1,
const std::string &strV2)
{
typename T::Pointer prop = T::New(v1);
MITK_TEST_OUTPUT(<< "**** Test [" << prop->GetNameOfClass() << "] ****");
CPPUNIT_ASSERT_MESSAGE("Test constructor", prop->GetValue() == v1);
std::string msg = std::string("Test GetValueAsString() [") + prop->GetValueAsString() + " == " + strV1 + "]";
CPPUNIT_ASSERT_MESSAGE(msg, prop->GetValueAsString() == strV1);
TestPropCloning(prop);
typename T::Pointer prop2 = T::New();
prop2->AddObserver(itk::ModifiedEvent(), m_L.m_Cmd.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Test modified", !m_L.m_Modified);
prop2->SetValue(v2);
CPPUNIT_ASSERT_MESSAGE("Test modified", m_L.Pop());
CPPUNIT_ASSERT_MESSAGE("Test SetValue()", prop2->GetValue() == v2);
prop2->SetValue(v2);
CPPUNIT_ASSERT_MESSAGE("Test for no modification", !m_L.Pop());
TestPropInequality(prop, prop2);
TestPropAssignment(prop, prop2, strV2);
prop->SetValue(v1);
TestPropPolymorphicAssignment(prop2, prop, strV1);
}
void TestBoolProperty_Success()
{
TestProperty<mitk::BoolProperty>(false, true, "0", "1");
}
void TestIntProperty_Success()
{
TestProperty<mitk::IntProperty>(3, 5, "3", "5");
}
void TestFloatProperty_Success()
{
TestProperty<mitk::FloatProperty>(0.3f, -23.5f, "0.3", "-23.5");
}
void TestDoubleProperty_Success()
{
TestProperty<mitk::DoubleProperty>(64.1f, 2.34f, "64.1", "2.34");
}
void TestVector3DProperty_Success()
{
mitk::Vector3D p1;
p1[0] = 2.0;
p1[1] = 3.0;
p1[2] = 4.0;
mitk::Vector3D p2;
p2[0] = -1.0;
p2[1] = 2.0;
p2[2] = 3.0;
TestProperty<mitk::Vector3DProperty>(p1, p2, "[2, 3, 4]", "[-1, 2, 3]");
}
void TestPoint3D_Success()
{
mitk::Point3D p1;
p1[0] = 2.0;
p1[1] = 3.0;
p1[2] = 4.0;
mitk::Point3D p2;
p2[0] = -1.0;
p2[1] = 2.0;
p2[2] = 3.0;
TestProperty<mitk::Point3dProperty>(p1, p2, "[2, 3, 4]", "[-1, 2, 3]");
}
void TestPoint4D_Success()
{
mitk::Point4D p1;
p1[0] = 2.0;
p1[1] = 3.0;
p1[2] = 4.0;
p1[3] = -2.0;
mitk::Point4D p2;
p2[0] = -1.0;
p2[1] = 2.0;
p2[2] = 3.0;
p2[3] = 5.0;
TestProperty<mitk::Point4dProperty>(p1, p2, "[2, 3, 4, -2]", "[-1, 2, 3, 5]");
}
void TestPoint3I_Success()
{
mitk::Point3I p1;
p1[0] = 2;
p1[1] = 3;
p1[2] = 4;
mitk::Point3I p2;
p2[0] = 8;
p2[1] = 7;
p2[2] = 6;
TestProperty<mitk::Point3iProperty>(p1, p2, "[2, 3, 4]", "[8, 7, 6]");
}
void TestFloatLookupTable_Success()
{
mitk::FloatLookupTable lut1;
lut1.SetTableValue(1, 0.3f);
lut1.SetTableValue(4, 323.7f);
mitk::FloatLookupTable lut2;
lut2.SetTableValue(6, -0.3f);
lut2.SetTableValue(2, 25.7f);
TestProperty<mitk::FloatLookupTableProperty>(lut1, lut2, "[1 -> 0.3, 4 -> 323.7]", "[2 -> 25.7, 6 -> -0.3]");
}
void TestBoolLookupTable_Success()
{
mitk::BoolLookupTable lut1;
lut1.SetTableValue(3, false);
lut1.SetTableValue(5, true);
mitk::BoolLookupTable lut2;
lut2.SetTableValue(1, false);
lut2.SetTableValue(2, false);
TestProperty<mitk::BoolLookupTableProperty>(lut1, lut2, "[3 -> 0, 5 -> 1]", "[1 -> 0, 2 -> 0]");
}
void TestIntLookupTable_Success()
{
mitk::IntLookupTable lut1;
lut1.SetTableValue(5, -12);
lut1.SetTableValue(7, 3);
mitk::IntLookupTable lut2;
lut2.SetTableValue(4, -6);
lut2.SetTableValue(8, -45);
TestProperty<mitk::IntLookupTableProperty>(lut1, lut2, "[5 -> -12, 7 -> 3]", "[4 -> -6, 8 -> -45]");
}
void TestStringLookupTable_Success()
{
mitk::StringLookupTable lut1;
lut1.SetTableValue(0, "a");
lut1.SetTableValue(2, "b");
mitk::StringLookupTable lut2;
lut2.SetTableValue(0, "a");
lut2.SetTableValue(2, "c");
TestProperty<mitk::StringLookupTableProperty>(lut1, lut2, "[0 -> a, 2 -> b]", "[0 -> a, 2 -> c]");
}
void TestAnnotationProperty_Success()
{
std::string label1("Label1");
mitk::Point3D point1;
point1[0] = 3;
point1[1] = 5;
point1[2] = -4;
std::string str1 = "Label1[3, 5, -4]";
std::string label2("Label2");
mitk::Point3D point2;
point2[0] = -2;
point2[1] = 8;
point2[2] = -4;
std::string str2 = "Label2[-2, 8, -4]";
mitk::AnnotationProperty::Pointer prop = mitk::AnnotationProperty::New(label1, point1);
MITK_TEST_OUTPUT(<< "**** Test [" << prop->GetNameOfClass() << "] ****");
CPPUNIT_ASSERT_MESSAGE("Test constructor", prop->GetLabel() == label1 && prop->GetPosition() == point1);
std::string msg = std::string("Test GetValueAsString() [") + prop->GetValueAsString() + " == " + str1 + "]";
CPPUNIT_ASSERT_MESSAGE(msg, prop->GetValueAsString() == str1);
mitk::AnnotationProperty::Pointer prop2 = mitk::AnnotationProperty::New();
prop2->AddObserver(itk::ModifiedEvent(), m_L.m_Cmd.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Test not modified", !m_L.m_Modified);
prop2->SetLabel(label2);
CPPUNIT_ASSERT_MESSAGE("Test modified", m_L.Pop());
prop2->SetPosition(point2);
CPPUNIT_ASSERT_MESSAGE("Test modified", m_L.Pop());
CPPUNIT_ASSERT_MESSAGE("Test Setter", prop2->GetLabel() == label2 && prop2->GetPosition() == point2);
prop2->SetLabel(label2);
CPPUNIT_ASSERT_MESSAGE("Test for no modification", !m_L.Pop());
prop2->SetPosition(point2);
CPPUNIT_ASSERT_MESSAGE("Test for no modification", !m_L.Pop());
TestPropInequality(prop, prop2);
TestPropAssignment(prop, prop2, str2);
prop->SetLabel(label1);
prop->SetPosition(point1);
TestPropPolymorphicAssignment(prop2, prop, str1);
}
void TestClippingProperty_Success()
{
bool enabled1 = true;
mitk::Point3D point1;
point1[0] = 3;
point1[1] = 5;
point1[2] = -4;
mitk::Vector3D vec1;
vec1[0] = 0;
vec1[1] = 2;
vec1[2] = -1;
std::string str1 = "1[3, 5, -4][0, 2, -1]";
bool enabled2 = false;
mitk::Point3D point2;
point2[0] = -2;
point2[1] = 8;
point2[2] = -4;
mitk::Vector3D vec2;
vec2[0] = 0;
vec2[1] = 2;
vec2[2] = 4;
std::string str2 = "0[-2, 8, -4][0, 2, 4]";
mitk::ClippingProperty::Pointer prop = mitk::ClippingProperty::New(point1, vec1);
MITK_TEST_OUTPUT(<< "**** Test [" << prop->GetNameOfClass() << "] ****");
CPPUNIT_ASSERT_MESSAGE("Test constructor",
prop->GetClippingEnabled() == enabled1 && prop->GetOrigin() == point1 && prop->GetNormal() == vec1);
std::string msg = std::string("Test GetValueAsString() [") + prop->GetValueAsString() + " == " + str1 + "]";
CPPUNIT_ASSERT_MESSAGE(msg, prop->GetValueAsString() == str1);
mitk::ClippingProperty::Pointer prop2 = mitk::ClippingProperty::New();
prop2->AddObserver(itk::ModifiedEvent(), m_L.m_Cmd.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Test not modified", !m_L.m_Modified);
prop2->SetClippingEnabled(enabled2);
CPPUNIT_ASSERT_MESSAGE("Test not modified", !m_L.Pop());
prop2->SetOrigin(point2);
CPPUNIT_ASSERT_MESSAGE("Test modified", m_L.Pop());
prop2->SetNormal(vec2);
CPPUNIT_ASSERT_MESSAGE("Test modified", m_L.Pop());
CPPUNIT_ASSERT_MESSAGE("Test Setter",
prop2->GetClippingEnabled() == enabled2 && prop2->GetOrigin() == point2 && prop2->GetNormal() == vec2);
prop2->SetClippingEnabled(enabled2);
CPPUNIT_ASSERT_MESSAGE("Test for no modification", !m_L.Pop());
prop2->SetOrigin(point2);
CPPUNIT_ASSERT_MESSAGE("Test for no modification", !m_L.Pop());
prop2->SetNormal(vec2);
CPPUNIT_ASSERT_MESSAGE("Test for no modification", !m_L.Pop());
TestPropInequality(prop, prop2);
TestPropAssignment(prop, prop2, str2);
prop->SetClippingEnabled(enabled1);
prop->SetOrigin(point1);
prop->SetNormal(vec1);
TestPropPolymorphicAssignment(prop2, prop, str1);
}
void TestColorProperty_Success()
{
mitk::Color c1;
c1[0] = 0.2;
c1[1] = 0.6;
c1[2] = 0.8;
mitk::Color c2;
c2[0] = 0.2;
c2[1] = 0.4;
c2[2] = 0.1;
TestProperty<mitk::ColorProperty>(c1, c2, "0.2 0.6 0.8", "0.2 0.4 0.1");
}
void TestLevelWindowProperty_Success()
{
mitk::LevelWindow lw1(50, 100);
mitk::LevelWindow lw2(120, 30);
TestProperty<mitk::LevelWindowProperty>(lw1, lw2, "L:50 W:100", "L:120 W:30");
}
void TestSmartPointerProperty_Success()
{
itk::Object::Pointer sp1 = itk::Object::New();
itk::Object::Pointer sp2 = itk::Object::New();
// to generate the UIDs, we set the smartpointers
mitk::SmartPointerProperty::Pointer spp1 = mitk::SmartPointerProperty::New(sp1.GetPointer());
mitk::SmartPointerProperty::Pointer spp2 = mitk::SmartPointerProperty::New(sp2.GetPointer());
TestProperty<mitk::SmartPointerProperty>(sp1, sp2, spp1->GetReferenceUIDFor(sp1), spp2->GetReferenceUIDFor(sp2));
}
void TestStringProperty_Success()
{
TestProperty<mitk::StringProperty>("1", "2", "1", "2");
}
void TestTransferFunctionProperty_Success()
{
mitk::TransferFunction::Pointer tf1 = mitk::TransferFunction::New();
mitk::TransferFunction::Pointer tf2 = mitk::TransferFunction::New();
tf2->AddScalarOpacityPoint(0.4, 0.8);
std::stringstream ss;
ss << tf1;
std::string strTF1 = ss.str();
ss.str("");
ss << tf2;
std::string strTF2 = ss.str();
TestProperty<mitk::TransferFunctionProperty>(tf1, tf2, strTF1, strTF2);
}
void TestWeakPointerProperty_Success()
{
itk::Object::Pointer sp1 = itk::Object::New();
itk::Object::Pointer sp2 = itk::Object::New();
mitk::WeakPointerProperty::ValueType wp1 = sp1.GetPointer();
mitk::WeakPointerProperty::ValueType wp2 = sp2.GetPointer();
std::stringstream ss;
ss << sp1.GetPointer();
std::string str1 = ss.str();
ss.str("");
ss << sp2.GetPointer();
std::string str2 = ss.str();
TestProperty<mitk::WeakPointerProperty>(wp1, wp2, str1, str2);
}
void TestLookupTablePropertyProperty_Success()
{
mitk::LookupTable::Pointer lut1 = mitk::LookupTable::New();
lut1->GetVtkLookupTable()->SetTableValue(0, 0.2, 0.3, 0.4);
mitk::LookupTable::Pointer lut2 = mitk::LookupTable::New();
lut2->GetVtkLookupTable()->SetTableValue(0, 0.2, 0.4, 0.4);
std::stringstream ss;
ss << lut1;
std::string strLUT1 = ss.str();
ss.str("");
ss << lut2;
std::string strLUT2 = ss.str();
TestProperty<mitk::LookupTableProperty>(lut1, lut2, strLUT1, strLUT2);
}
};
MITK_TEST_SUITE_REGISTRATION(mitkProperty)
diff --git a/Modules/Core/test/mitkSliceNavigationControllerTest.cpp b/Modules/Core/test/mitkSliceNavigationControllerTest.cpp
index a546ced931..262a1683c1 100644
--- a/Modules/Core/test/mitkSliceNavigationControllerTest.cpp
+++ b/Modules/Core/test/mitkSliceNavigationControllerTest.cpp
@@ -1,196 +1,177 @@
/*============================================================================
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 <mitkGeometry3D.h>
#include <mitkPlaneGeometry.h>
#include <mitkSlicedGeometry3D.h>
#include <mitkSliceNavigationController.h>
#include <mitkArbitraryTimeGeometry.h>
#include <mitkTestFixture.h>
#include <mitkTestingMacros.h>
// T22254
class mitkSliceNavigationControllerTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkSliceNavigationControllerTestSuite);
CPPUNIT_TEST(validateAxialViewDirection);
CPPUNIT_TEST(validateCoronalViewDirection);
CPPUNIT_TEST(validateSagittalViewDirection);
- CPPUNIT_TEST(GetSelectedTimePoint);
CPPUNIT_TEST_SUITE_END();
mitk::Geometry3D::Pointer m_Geometry3D;
mitk::ArbitraryTimeGeometry::Pointer m_TimeGeometry;
public:
void setUp() override
{
mitk::Point3D origin;
mitk::FillVector3D(origin, 10.0, 20.0, 30.0);
mitk::Vector3D firstAxisVector;
mitk::FillVector3D(firstAxisVector, 100.0, 0.0, 0.0);
mitk::Vector3D secondAxisVector;
mitk::FillVector3D(secondAxisVector, 0.0, 50.0, 0.0);
mitk::Vector3D spacing;
mitk::FillVector3D(spacing, 1.0, 1.0, 2.0);
auto planeGeometry = mitk::PlaneGeometry::New();
planeGeometry->InitializeStandardPlane(firstAxisVector, secondAxisVector, &spacing);
planeGeometry->SetOrigin(origin);
unsigned int numberOfSlices = 100U;
auto slicedGeometry3D = mitk::SlicedGeometry3D::New();
slicedGeometry3D->InitializeEvenlySpaced(planeGeometry, numberOfSlices);
m_Geometry3D = mitk::Geometry3D::New();
m_Geometry3D->SetBounds(slicedGeometry3D->GetBounds());
m_Geometry3D->SetIndexToWorldTransform(slicedGeometry3D->GetIndexToWorldTransform());
m_TimeGeometry = mitk::ArbitraryTimeGeometry::New();
m_TimeGeometry->AppendNewTimeStepClone(m_Geometry3D, 0.5, 10.);
m_TimeGeometry->AppendNewTimeStepClone(m_Geometry3D, 10., 30.);
m_TimeGeometry->AppendNewTimeStepClone(m_Geometry3D, 30., 50.);
m_TimeGeometry->AppendNewTimeStepClone(m_Geometry3D, 50., 60.);
m_TimeGeometry->Update();
}
void tearDown() override
{
}
void validateAxialViewDirection()
{
auto sliceNavigationController = mitk::SliceNavigationController::New();
sliceNavigationController->SetInputWorldTimeGeometry(m_TimeGeometry);
sliceNavigationController->SetViewDirection(mitk::AnatomicalPlane::Axial);
sliceNavigationController->Update();
mitk::Point3D origin;
mitk::FillVector3D(origin, 10.0, 70.0, 229.0);
mitk::Vector3D firstAxisVector;
mitk::FillVector3D(firstAxisVector, 100.0, 0.0, 0.0);
mitk::Vector3D secondAxisVector;
mitk::FillVector3D(secondAxisVector, 0.0, -50.0, 0.0);
mitk::Vector3D thirdAxisVector;
mitk::FillVector3D(thirdAxisVector, 0.0, 0.0, -200.0);
std::cout << "Axial view direction" << std::endl;
CPPUNIT_ASSERT(this->validateGeometry(sliceNavigationController->GetCurrentGeometry3D(), origin, firstAxisVector, secondAxisVector, thirdAxisVector));
}
void validateCoronalViewDirection()
{
auto sliceNavigationController = mitk::SliceNavigationController::New();
sliceNavigationController->SetInputWorldTimeGeometry(m_TimeGeometry);
sliceNavigationController->SetViewDirection(mitk::AnatomicalPlane::Coronal);
sliceNavigationController->Update();
mitk::Point3D origin;
mitk::FillVector3D(origin, 10.0, 69.5, 30.0);
mitk::Vector3D firstAxisVector;
mitk::FillVector3D(firstAxisVector, 100.0, 0.0, 0.0);
mitk::Vector3D secondAxisVector;
mitk::FillVector3D(secondAxisVector, 0.0, 0.0, 200.0);
mitk::Vector3D thirdAxisVector;
mitk::FillVector3D(thirdAxisVector, 0.0, -50.0, 0.0);
std::cout << "Coronal view direction" << std::endl;
CPPUNIT_ASSERT(this->validateGeometry(sliceNavigationController->GetCurrentGeometry3D(), origin, firstAxisVector, secondAxisVector, thirdAxisVector));
}
void validateSagittalViewDirection()
{
auto sliceNavigationController = mitk::SliceNavigationController::New();
sliceNavigationController->SetInputWorldTimeGeometry(m_TimeGeometry);
sliceNavigationController->SetViewDirection(mitk::AnatomicalPlane::Sagittal);
sliceNavigationController->Update();
mitk::Point3D origin;
mitk::FillVector3D(origin, 10.5, 20.0, 30.0);
mitk::Vector3D firstAxisVector;
mitk::FillVector3D(firstAxisVector, 0.0, 50.0, 0.0);
mitk::Vector3D secondAxisVector;
mitk::FillVector3D(secondAxisVector, 0.0, 0.0, 200.0);
mitk::Vector3D thirdAxisVector;
mitk::FillVector3D(thirdAxisVector, 100.0, 0.0, 0.0);
std::cout << "Sagittal view direction" << std::endl;
CPPUNIT_ASSERT(this->validateGeometry(sliceNavigationController->GetCurrentGeometry3D(), origin, firstAxisVector, secondAxisVector, thirdAxisVector));
}
- void GetSelectedTimePoint()
- {
- auto sliceNavigationController = mitk::SliceNavigationController::New();
-
- CPPUNIT_ASSERT(sliceNavigationController->GetSelectedTimePoint() == 0.);
-
- sliceNavigationController->SetInputWorldTimeGeometry(m_TimeGeometry);
- sliceNavigationController->SetViewDirection(mitk::AnatomicalPlane::Sagittal);
- sliceNavigationController->Update();
-
- CPPUNIT_ASSERT(sliceNavigationController->GetSelectedTimeStep() == 0);
- CPPUNIT_ASSERT(sliceNavigationController->GetSelectedTimePoint() == 0.5);
-
- sliceNavigationController->GetTime()->SetPos(2);
- CPPUNIT_ASSERT(sliceNavigationController->GetSelectedTimeStep() == 2);
- CPPUNIT_ASSERT(sliceNavigationController->GetSelectedTimePoint() == 30.0);
- }
-
private:
bool validateGeometry(mitk::BaseGeometry::ConstPointer geometry, const mitk::Point3D &origin, const mitk::Vector3D &firstAxisVector, const mitk::Vector3D &secondAxisVector, const mitk::Vector3D &thirdAxisVector)
{
bool result = true;
std::cout << " Origin" << std::endl;
if (!mitk::Equal(geometry->GetOrigin(), origin, mitk::eps, true))
result = false;
std::cout << " First axis vector" << std::endl;
if (!mitk::Equal(geometry->GetAxisVector(0), firstAxisVector, mitk::eps, true))
result = false;
std::cout << " Second axis vector" << std::endl;
if (!mitk::Equal(geometry->GetAxisVector(1), secondAxisVector, mitk::eps, true))
result = false;
std::cout << " Third axis vector" << std::endl;
if (!mitk::Equal(geometry->GetAxisVector(2), thirdAxisVector, mitk::eps, true))
result = false;
return result;
}
};
MITK_TEST_SUITE_REGISTRATION(mitkSliceNavigationController)
diff --git a/Modules/Core/test/mitkUIDGeneratorTest.cpp b/Modules/Core/test/mitkUIDGeneratorTest.cpp
index b2b735beae..cb06e0ecfe 100644
--- a/Modules/Core/test/mitkUIDGeneratorTest.cpp
+++ b/Modules/Core/test/mitkUIDGeneratorTest.cpp
@@ -1,55 +1,55 @@
/*============================================================================
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.
============================================================================*/
// Testing
#include "mitkTestFixture.h"
#include "mitkTestingMacros.h"
// std includes
#include <string>
// MITK includes
#include "mitkUIDGenerator.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkTestFixture.h>
#include <mitkTestingMacros.h>
class mitkUIDGeneratorTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkUIDGeneratorTestSuite);
MITK_TEST(UIDGeneratorInstanceRenewalSucceed);
MITK_TEST(UIDGeneratorMultipleInstancesSucceed);
CPPUNIT_TEST_SUITE_END();
void UIDGeneratorInstanceRenewalSucceed()
{
mitk::UIDGenerator uidGen1("UID_");
auto uid1_1 = uidGen1.GetUID();
uidGen1 = mitk::UIDGenerator("UID_");
auto uid2_1 = uidGen1.GetUID();
CPPUNIT_ASSERT_MESSAGE("Different UIDs are not allowed to be equal", uid1_1 != uid2_1);
}
void UIDGeneratorMultipleInstancesSucceed()
{
mitk::UIDGenerator uidGen1("UID_");
mitk::UIDGenerator uidGen2("UID_");
auto uid1_1 = uidGen1.GetUID();
auto uid2_1 = uidGen2.GetUID();
CPPUNIT_ASSERT_MESSAGE("Different UIDs are not allowed to be equal", uid1_1 != uid2_1);
}
};
MITK_TEST_SUITE_REGISTRATION(mitkUIDGenerator)
diff --git a/Modules/CppMicroServices/core/doc/doxygen/MicroServices_Debugging.dox b/Modules/CppMicroServices/core/doc/doxygen/MicroServices_Debugging.dox
index 4e3c735c8f..ca4b4005e5 100644
--- a/Modules/CppMicroServices/core/doc/doxygen/MicroServices_Debugging.dox
+++ b/Modules/CppMicroServices/core/doc/doxygen/MicroServices_Debugging.dox
@@ -1,70 +1,60 @@
-
-/**
- * \ingroup MicroServicesUtils
- *
- * \enum MsgType
- * This enum describes the messages that can be sent to a message handler (MsgHandler).
- * You can use the enum to identify and associate the various message types with the
- * appropriate actions.
- */
-
/**
* \ingroup MicroServicesUtils
*
* \var MsgType DebugMsg
* A debug message.
*/
/**
* \ingroup MicroServicesUtils
*
* \var MsgType InfoMsg
* An informational message.
*/
/**
* \ingroup MicroServicesUtils
*
* \var MsgType WarningMsg
* A warning message.
*/
/**
* \ingroup MicroServicesUtils
*
* \var MsgType ErrorMsg
* An error message.
*/
/**
* \ingroup MicroServicesUtils
*
* \typedef MsgHandler
* A message handler callback function.
*/
/**
* \ingroup MicroServicesUtils
*
* \fn MsgHandler installMsgHandler(MsgHandler)
* \brief Installs a message handler which has been defined previously.
*
* Returns a pointer to the previous message handler (which may be 0).
*
* The message handler is a function that prints out debug messages, warnings,
* and fatal error messages. The C++ Micro Services library (debug mode) contains
* warning messages that are printed when internal errors (usually invalid function
* arguments) occur. The library built in release mode also contains such warnings
* unless US_NO_WARNING_OUTPUT has been set during compilation. In both debug and release mode
* debugging message are suppressed by default, unless US_ENABLE_DEBUGGING_OUTPUT
* has been set during compilation. If you implement your own message handler,
* you get total control of these messages.
*
* The default message handler prints the message to the standard output. If it is
* an error message, the application aborts immediately.
*
* Only one message handler can be defined, since this is usually done on an
* application-wide basis to control debug output.
*
* To restore the message handler, call installMsgHandler(0).
*/
diff --git a/Modules/CppMicroServices/core/include/usLDAPFilter.h b/Modules/CppMicroServices/core/include/usLDAPFilter.h
index 3340e04340..cca5bbab05 100644
--- a/Modules/CppMicroServices/core/include/usLDAPFilter.h
+++ b/Modules/CppMicroServices/core/include/usLDAPFilter.h
@@ -1,171 +1,169 @@
/*============================================================================
Library: CppMicroServices
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
============================================================================*/
#ifndef USLDAPFILTER_H
#define USLDAPFILTER_H
#include "usServiceProperties.h"
#include "usSharedData.h"
US_BEGIN_NAMESPACE
class LDAPFilterData;
class ServiceReferenceBase;
/**
* \ingroup MicroServices
*
* An <a href="https://www.ietf.org/rfc/rfc1960.txt">RFC 1960</a>-based Filter.
*
* <p>
* A <code>LDAPFilter</code> can be used numerous times to determine if the match
* argument matches the filter string that was used to create the <code>LDAPFilter</code>.
* <p>
* Some examples of LDAP filters are:
*
* - "(cn=Babs Jensen)"
* - "(!(cn=Tim Howes))"
* - "(&(" + ServiceConstants::OBJECTCLASS() + "=Person)(|(sn=Jensen)(cn=Babs J*)))"
* - "(o=univ*of*mich*)"
*
* \remarks This class is thread safe.
*
* \sa LDAPProp for a fluent API generating LDAP filter strings
*/
class US_Core_EXPORT LDAPFilter {
private:
typedef SharedDataPointer<LDAPFilterData> LDAPFilter::*bool_type;
public:
/**
* Creates in invalid <code>LDAPFilter</code> object.
* Test the validity by using the boolean conversion operator.
*
* <p>
* Calling methods on an invalid <code>LDAPFilter</code>
* will result in undefined behavior.
*/
LDAPFilter();
/**
* Creates a <code>LDAPFilter</code> object. This <code>LDAPFilter</code>
* object may be used to match a <code>ServiceReference</code> object or a
* <code>ServiceProperties</code> object.
*
- * <p>
* If the filter cannot be parsed, an std::invalid_argument will be
* thrown with a human readable message where the filter became unparsable.
*
* @param filter The filter string.
- * @return A <code>LDAPFilter</code> object encapsulating the filter string.
* @throws std::invalid_argument If <code>filter</code> contains an invalid
* filter string that cannot be parsed.
* @see "Framework specification for a description of the filter string syntax." TODO!
*/
LDAPFilter(const std::string& filter);
LDAPFilter(const LDAPFilter& other);
~LDAPFilter();
operator bool_type() const;
/**
* Filter using a service's properties.
* <p>
* This <code>LDAPFilter</code> is executed using the keys and values of the
* referenced service's properties. The keys are looked up in a case
* insensitive manner.
*
* @param reference The reference to the service whose properties are used
* in the match.
* @return <code>true</code> if the service's properties match this
* <code>LDAPFilter</code> <code>false</code> otherwise.
*/
bool Match(const ServiceReferenceBase& reference) const;
/**
* Filter using a <code>ServiceProperties</code> object with case insensitive key lookup. This
* <code>LDAPFilter</code> is executed using the specified <code>ServiceProperties</code>'s keys
* and values. The keys are looked up in a case insensitive manner.
*
* @param dictionary The <code>ServiceProperties</code> whose key/value pairs are used
* in the match.
* @return <code>true</code> if the <code>ServiceProperties</code>'s values match this
* filter; <code>false</code> otherwise.
*/
bool Match(const ServiceProperties& dictionary) const;
/**
* Filter using a <code>ServiceProperties</code>. This <code>LDAPFilter</code> is executed using
* the specified <code>ServiceProperties</code>'s keys and values. The keys are looked
* up in a normal manner respecting case.
*
* @param dictionary The <code>ServiceProperties</code> whose key/value pairs are used
* in the match.
* @return <code>true</code> if the <code>ServiceProperties</code>'s values match this
* filter; <code>false</code> otherwise.
*/
bool MatchCase(const ServiceProperties& dictionary) const;
/**
* Returns this <code>LDAPFilter</code>'s filter string.
* <p>
* The filter string is normalized by removing whitespace which does not
* affect the meaning of the filter.
*
* @return This <code>LDAPFilter</code>'s filter string.
*/
std::string ToString() const;
/**
* Compares this <code>LDAPFilter</code> to another <code>LDAPFilter</code>.
*
* <p>
* This implementation returns the result of calling
* <code>this->ToString() == other.ToString()</code>.
*
* @param other The object to compare against this <code>LDAPFilter</code>.
* @return Returns the result of calling
* <code>this->ToString() == other.ToString()</code>.
*/
bool operator==(const LDAPFilter& other) const;
LDAPFilter& operator=(const LDAPFilter& filter);
protected:
SharedDataPointer<LDAPFilterData> d;
};
US_END_NAMESPACE
/**
* \ingroup MicroServices
*/
US_Core_EXPORT std::ostream& operator<<(std::ostream& os, const US_PREPEND_NAMESPACE(LDAPFilter)& filter);
#endif // USLDAPFILTER_H
diff --git a/Modules/CppMicroServices/doc/doxygen.conf.in b/Modules/CppMicroServices/doc/doxygen.conf.in
index 6e7ffad4eb..89881d49b2 100644
--- a/Modules/CppMicroServices/doc/doxygen.conf.in
+++ b/Modules/CppMicroServices/doc/doxygen.conf.in
@@ -1,2293 +1,2749 @@
-# Doxyfile 1.8.5
+# Doxyfile 1.9.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "C++ Micro Services"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = @CppMicroServices_VERSION@
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "A dynamic OSGi-like C++ service registry"
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = "@US_DOXYGEN_OUTPUT_DIR@"
+OUTPUT_DIRECTORY = @US_DOXYGEN_OUTPUT_DIR@
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL = 8
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-
-# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi,
-# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en,
-# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
-# Turkish, Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = YES
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 2
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
-# "sideeffect=@par Side Effects:\n"
+# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
ALIASES = "FIXME=\par Fix Me's:\n" \
"embmainpage{1}=@US_DOXYGEN_MAIN_PAGE_CMD@"
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding "class=itcl::class"
-# will allow you to use the command class in the itcl::class meaning.
-
-TCL_SUBST =
-
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C.
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = YES
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = NO
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = YES
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = NO
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = YES
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS = @US_DOXYGEN_ENABLED_SECTIONS@
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 0
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = NO
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = NO
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
-# search path. Do not use file names with spaces, bibtex cannot handle them. See
-# also \cite for info how to create references.
+# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = YES
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT = "at line $line of file $file"
+
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
-# error (stderr).
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = "@PROJECT_SOURCE_DIR@" \
"@PROJECT_SOURCE_DIR@/cmake/usFunctionAddResources.cmake" \
"@PROJECT_SOURCE_DIR@/cmake/usFunctionEmbedResources.cmake" \
"@PROJECT_SOURCE_DIR@/cmake/usFunctionGenerateModuleInit.cmake" \
"@PROJECT_SOURCE_DIR@/cmake/usFunctionGetResourceSource.cmake" \
"@PROJECT_BINARY_DIR@/include/usGlobalConfig.h" \
"@PROJECT_BINARY_DIR@/core/include"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING =
+
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.h \
*.dox \
*.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE = "@PROJECT_SOURCE_DIR@/README.md" \
"@PROJECT_SOURCE_DIR@/gh-pages/" \
"@PROJECT_SOURCE_DIR@/third_party/" \
"@PROJECT_SOURCE_DIR@/.git/"
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = */test/* \
*/snippets/* \
*/core/examples/* \
*/.git/* \
*_p.h \
*Private.*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
+# ANamespace::AClass, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS = us \
US_NAMESPACE \
*Private* \
ModuleInfo \
ServiceObjectsBase* \
TrackedService*
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH = "@PROJECT_SOURCE_DIR@/core/doc/snippets/" \
"@PROJECT_SOURCE_DIR@/core/examples/"
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
# <filter> <input-file>
#
# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS = *.cmake=@CMakeDoxygenFilter_EXECUTABLE@
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER = 72
+
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = NO
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
+# entity all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = NO
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX = 3
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_OUTPUT = "@US_DOXYGEN_HTML_OUTPUT@"
+HTML_OUTPUT = @US_DOXYGEN_HTML_OUTPUT@
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_HEADER = "@US_DOXYGEN_HEADER@"
+HTML_HEADER = @US_DOXYGEN_HEADER@
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FOOTER = "@US_DOXYGEN_FOOTER@"
+HTML_FOOTER = @US_DOXYGEN_FOOTER@
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
-# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
-# defined cascading style sheet that is included after the standard style sheets
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
-# Doxygen will copy the style sheet file to the output directory. For an example
-# see the documentation.
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET = "@US_DOXYGEN_EXTRA_CSS@"
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE = AUTO_LIGHT
+
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = NO
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file.
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE =
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER =
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 300
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
-FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use <access key> + S
# (what the <access key> is depends on the OS and browser, but it is typically
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
# key> to jump into the search results window, the results can be navigated
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
# to select a filter and <Enter> or <escape> to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
-# are two flavours of web server based searching depending on the
-# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
-# searching and an index file used by the script. When EXTERNAL_SEARCH is
-# enabled the indexing and searching needs to be provided by external tools. See
-# the section "External Indexing and Searching" for details.
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES = amssymb
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
#
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
-# replace them by respectively the title of the page, the current date and time,
-# only the current date, the version number of doxygen, the project name (see
-# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = NO
-# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
+# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE = NO
-
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = YES
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
-# preprocessor.
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = "@PROJECT_BINARY_DIR@/include/"
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS = *.h
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = US_PREPEND_NAMESPACE(x)=x \
US_BEGIN_NAMESPACE= \
US_END_NAMESPACE= \
US_Core_EXPORT= \
US_ABI_LOCAL= \
US_MSVC_POP_WARNING=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
-# all uppercase name, and do not end with a semicolon. Such function macros are
-# typically used for boiler-plate code, and will confuse the parser if not
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
-# Note: Each tag file must have an unique name (where the name does NOT include
+# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = NO
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
-CLASS_DIAGRAMS = YES
+DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = @US_HAVE_DOT@
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = @US_DOXYGEN_DOT_NUM_THREADS@
-# When you want a differently looking font n the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
+
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTNAME = Helvetica
+DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTSIZE = 10
+DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = YES
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = NO
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = NO
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = NO
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = NO
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
-# Possible values are: png, jpg, gif and svg.
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH = "@US_DOXYGEN_DOT_PATH@"
+DOT_PATH = @US_DOXYGEN_DOT_PATH@
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/Modules/DICOM/src/mitkDICOMTag.cpp b/Modules/DICOM/src/mitkDICOMTag.cpp
index 9b6c7aab13..632866b1ff 100644
--- a/Modules/DICOM/src/mitkDICOMTag.cpp
+++ b/Modules/DICOM/src/mitkDICOMTag.cpp
@@ -1,209 +1,209 @@
/*============================================================================
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 "mitkDICOMTag.h"
#include <gdcmGlobal.h>
#include <gdcmDicts.h>
#include <boost/algorithm/string.hpp>
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include "dcmtk/ofstd/ofstd.h"
mitk::DICOMTag
::DICOMTag(unsigned int group, unsigned int element)
:m_Group(group)
,m_Element(element)
{
}
mitk::DICOMTag
::DICOMTag(const DICOMTag& other)
:m_Group(other.m_Group)
,m_Element(other.m_Element)
{
}
bool
mitk::DICOMTag
::operator==(const DICOMTag& other) const
{
return
m_Group == other.m_Group &&
m_Element == other.m_Element
;
}
mitk::DICOMTag&
mitk::DICOMTag
::operator=(const DICOMTag& other)
{
if (this != &other)
{
m_Group = other.m_Group;
m_Element = other.m_Element;
}
return *this;
}
unsigned int
mitk::DICOMTag
::GetGroup() const
{
return m_Group;
}
unsigned int
mitk::DICOMTag
::GetElement() const
{
return m_Element;
}
bool
mitk::DICOMTag
::operator<(const DICOMTag& other) const
{
return
( this->m_Group < other.m_Group )
||
( ( this->m_Group == other.m_Group )
&&
( this->m_Element < other.m_Element )
);
}
std::string
mitk::DICOMTag
::GetName() const
{
gdcm::Tag t(m_Group, m_Element);
const gdcm::Global& g = gdcm::Global::GetInstance(); // sum of all knowledge !
const gdcm::Dicts& dicts = g.GetDicts();
const gdcm::Dict& pub = dicts.GetPublicDict(); // Part 6
const gdcm::DictEntry& entry = pub.GetDictEntry(t);
std::string name = entry.GetName();
if (name.empty())
{
name = "Unknown Tag";
}
return name;
}
std::string
mitk::DICOMTag
::toHexString(unsigned int i) const
{
std::stringstream ss;
ss << std::setfill ('0') << std::setw(4) << std::hex << i;
return ss.str();
}
void
mitk::DICOMTag
::Print(std::ostream& os) const
{
os << "(" << toHexString(m_Group) << "," << toHexString(m_Element) << ") " << this->GetName();
}
void mitk::DICOMStringToOrientationVectors( const std::string& s,
Vector3D& right,
Vector3D& up,
bool& successful )
{
successful = false;
try
{
std::vector<std::string> strs;
boost::split( strs, s, boost::is_any_of( "\\" ) );
if ( strs.size() == 6 )
{
int i = 0;
for ( ; i < 3; ++i )
{
right[i] = OFStandard::atof( strs[i].c_str() );
}
for ( ; i < 6; ++i )
{
up[i - 3] = OFStandard::atof( strs[i].c_str() );
}
successful = true;
}
}
catch ( const std::exception& /*e*/ )
{
right.Fill( 0.0 );
right[0] = 1.0;
up.Fill( 0.0 );
up[1] = 1.0;
successful = false;
}
}
bool
mitk::DICOMStringToSpacing(const std::string& s, ScalarType& spacingX, ScalarType& spacingY)
{
bool successful = false;
try
{
std::vector<std::string> strs;
boost::split( strs, s, boost::is_any_of( "\\" ) );
if ( strs.size() > 1 )
{
spacingY = OFStandard::atof( strs[0].c_str() );
spacingX = OFStandard::atof( strs[1].c_str() );
successful = true;
}
}
catch ( const std::exception& /*e*/ )
{
}
return successful;
}
mitk::Point3D mitk::DICOMStringToPoint3D( const std::string& s, bool& successful )
{
Point3D p;
successful = true;
try
{
std::vector<std::string> strs;
boost::split( strs, s, boost::is_any_of( "\\" ) );
if ( strs.size() == 3 )
{
for ( int i = 0; i < 3; ++i )
{
p[i] = OFStandard::atof( strs[i].c_str() );
}
}
}
catch ( const std::exception& /*e*/ )
{
p.Fill( 0.0 );
}
return p;
}
diff --git a/Modules/DICOM/src/mitkGantryTiltInformation.cpp b/Modules/DICOM/src/mitkGantryTiltInformation.cpp
index 74c0162c42..a14b30014e 100644
--- a/Modules/DICOM/src/mitkGantryTiltInformation.cpp
+++ b/Modules/DICOM/src/mitkGantryTiltInformation.cpp
@@ -1,255 +1,255 @@
/*============================================================================
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
#include "mitkGantryTiltInformation.h"
#include "mitkDICOMTag.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
mitk::GantryTiltInformation::GantryTiltInformation()
: m_ShiftUp(0.0)
, m_ShiftRight(0.0)
, m_ShiftNormal(0.0)
, m_ITKAssumedSliceSpacing(0.0)
, m_NumberOfSlicesApart(0)
{
}
#define doublepoint(x) \
Point3Dd x; \
x[0] = x ## f[0]; \
x[1] = x ## f[1]; \
x[2] = x ## f[2];
#define doublevector(x) \
Vector3Dd x; \
x[0] = x ## f[0]; \
x[1] = x ## f[1]; \
x[2] = x ## f[2];
mitk::GantryTiltInformation::GantryTiltInformation(
const Point3D& origin1f, const Point3D& origin2f,
const Vector3D& rightf, const Vector3D& upf,
unsigned int numberOfSlicesApart)
: m_ShiftUp(0.0)
, m_ShiftRight(0.0)
, m_ShiftNormal(0.0)
, m_ITKAssumedSliceSpacing(0.0)
, m_NumberOfSlicesApart(numberOfSlicesApart)
{
assert(numberOfSlicesApart);
doublepoint(origin1);
doublepoint(origin2);
doublevector(right);
doublevector(up);
// determine if slice 1 (imagePosition1 and imageOrientation1) and slice 2 can be in one orthogonal slice stack:
// calculate a line from origin 1, directed along the normal of slice (calculated as the cross product of orientation 1)
// check if this line passes through origin 2
/*
Determine if line (imagePosition2 + l * normal) contains imagePosition1.
Done by calculating the distance of imagePosition1 from line (imagePosition2 + l *normal)
E.g. https://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
squared distance = | (pointAlongNormal - origin2) x (origin2 - origin1) | ^ 2
/
|pointAlongNormal - origin2| ^ 2
( x meaning the cross product )
*/
Vector3Dd normal = itk::CrossProduct(right, up);
Point3Dd pointAlongNormal = origin2 + normal;
double numerator = itk::CrossProduct( pointAlongNormal - origin2 , origin2 - origin1 ).GetSquaredNorm();
double denominator = (pointAlongNormal - origin2).GetSquaredNorm();
double distance = sqrt(numerator / denominator);
if ( distance > 0.001 ) // mitk::eps is too small; 1/1000 of a mm should be enough to detect tilt
{
MITK_DEBUG << " Series seems to contain a tilted (or sheared) geometry";
MITK_DEBUG << " Distance of expected slice origin from actual slice origin: " << distance;
MITK_DEBUG << " ==> storing this shift for later analysis:";
MITK_DEBUG << " v origin1: " << origin1;
MITK_DEBUG << " v origin2: " << origin2;
MITK_DEBUG << " v right: " << right;
MITK_DEBUG << " v up: " << up;
MITK_DEBUG << " v normal: " << normal;
Point3Dd projectionRight = projectPointOnLine( origin1, origin2, right );
Point3Dd projectionNormal = projectPointOnLine( origin1, origin2, normal );
m_ShiftRight = (projectionRight - origin2).GetNorm();
m_ShiftNormal = (projectionNormal - origin2).GetNorm();
/*
now also check to which side the image is shifted.
Calculation e.g. from
https://mathworld.wolfram.com/Point-PlaneDistance.html
*/
Point3Dd testPoint = origin1;
Vector3Dd planeNormal = up;
double signedDistance = (
planeNormal[0] * testPoint[0]
+ planeNormal[1] * testPoint[1]
+ planeNormal[2] * testPoint[2]
- (
planeNormal[0] * origin2[0]
+ planeNormal[1] * origin2[1]
+ planeNormal[2] * origin2[2]
)
)
/
sqrt( planeNormal[0] * planeNormal[0]
+ planeNormal[1] * planeNormal[1]
+ planeNormal[2] * planeNormal[2]
);
m_ShiftUp = signedDistance;
m_ITKAssumedSliceSpacing = (origin2 - origin1).GetNorm();
// How do we now this is assumed? See header documentation for ITK code references
//double itkAssumedSliceSpacing = sqrt( m_ShiftUp * m_ShiftUp + m_ShiftNormal * m_ShiftNormal );
MITK_DEBUG << " calculated from slices " << m_NumberOfSlicesApart << " slices apart";
MITK_DEBUG << " shift normal: " << m_ShiftNormal;
MITK_DEBUG << " shift normal assumed by ITK: " << m_ITKAssumedSliceSpacing;
MITK_DEBUG << " shift up: " << m_ShiftUp;
MITK_DEBUG << " shift right: " << m_ShiftRight;
MITK_DEBUG << " tilt angle (deg): " << atan( m_ShiftUp / m_ShiftNormal ) * 180.0 / 3.1415926535;
}
}
mitk::GantryTiltInformation
mitk::GantryTiltInformation
::MakeFromTagValues(
const std::string& origin1String,
const std::string& origin2String,
const std::string& orientationString,
unsigned int numberOfSlicesApart)
{
Vector3D right; right.Fill(0.0);
Vector3D up; right.Fill(0.0); // might be down as well, but it is just a name at this point
bool orientationConversion(false);
DICOMStringToOrientationVectors( orientationString, right, up, orientationConversion );
if (orientationConversion
&& !origin1String.empty() && !origin2String.empty()
)
{
bool firstOriginConversion(false);
bool lastOriginConversion(false);
Point3D firstOrigin = DICOMStringToPoint3D( origin1String, firstOriginConversion );
Point3D lastOrigin = DICOMStringToPoint3D( origin2String, lastOriginConversion );
if (firstOriginConversion && lastOriginConversion)
{
return GantryTiltInformation( firstOrigin, lastOrigin, right, up, numberOfSlicesApart );
}
}
std::stringstream ss;
ss << "Invalid tag values when constructing tilt information from origin1 '" << origin1String
<< "', origin2 '" << origin2String
<< "', and orientation '" << orientationString << "'";
throw std::invalid_argument(ss.str());
}
void
mitk::GantryTiltInformation
::Print(std::ostream& os) const
{
os << " calculated from slices " << m_NumberOfSlicesApart << " slices apart" << std::endl;
os << " shift normal: " << m_ShiftNormal << std::endl;
os << " shift normal assumed by ITK: " << m_ITKAssumedSliceSpacing << std::endl;
os << " shift up: " << m_ShiftUp << std::endl;
os << " shift right: " << m_ShiftRight << std::endl;
os << " tilt angle (deg): " << atan( m_ShiftUp / m_ShiftNormal ) * 180.0 / 3.1415926535 << std::endl;
}
mitk::Point3D
mitk::GantryTiltInformation::projectPointOnLine( Point3Dd p, Point3Dd lineOrigin, Vector3Dd lineDirection )
{
/**
See illustration at https://mo.mathematik.uni-stuttgart.de/inhalt/aussage/aussage472/
vector(lineOrigin,p) = normal * ( innerproduct((p - lineOrigin),normal) / squared-length(normal) )
*/
Vector3Dd lineOriginToP = p - lineOrigin;
double innerProduct = lineOriginToP * lineDirection;
double factor = innerProduct / lineDirection.GetSquaredNorm();
Point3Dd projection = lineOrigin + factor * lineDirection;
return projection;
}
double
mitk::GantryTiltInformation::GetTiltCorrectedAdditionalSize(unsigned int imageSizeZ) const
{
return fabs(m_ShiftUp / static_cast<double>(m_NumberOfSlicesApart) * static_cast<double>(imageSizeZ-1));
}
double
mitk::GantryTiltInformation::GetTiltAngleInDegrees() const
{
return atan( fabs(m_ShiftUp) / m_ShiftNormal ) * 180.0 / 3.1415926535;
}
double
mitk::GantryTiltInformation::GetMatrixCoefficientForCorrectionInWorldCoordinates() const
{
// so many mm need to be shifted per slice!
return m_ShiftUp / static_cast<double>(m_NumberOfSlicesApart);
}
double
mitk::GantryTiltInformation::GetRealZSpacing() const
{
return m_ShiftNormal / static_cast<double>(m_NumberOfSlicesApart);
}
bool
mitk::GantryTiltInformation::IsSheared() const
{
return m_NumberOfSlicesApart &&
( fabs(m_ShiftRight) > 0.001
|| fabs(m_ShiftUp) > 0.001);
}
bool
mitk::GantryTiltInformation::IsRegularGantryTilt() const
{
return m_NumberOfSlicesApart &&
( fabs(m_ShiftRight) < 0.001
&& fabs(m_ShiftUp) > 0.001);
}
diff --git a/Modules/DICOMPM/autoload/DICOMPMIO/mitkDICOMPMIOMimeTypes.cpp b/Modules/DICOMPM/autoload/DICOMPMIO/mitkDICOMPMIOMimeTypes.cpp
index 63e303070e..3a7dd1d764 100644
--- a/Modules/DICOMPM/autoload/DICOMPMIO/mitkDICOMPMIOMimeTypes.cpp
+++ b/Modules/DICOMPM/autoload/DICOMPMIO/mitkDICOMPMIOMimeTypes.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 "mitkDICOMPMIOMimeTypes.h"
#include "mitkIOMimeTypes.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <itkGDCMImageIO.h>
#include <itksys/SystemTools.hxx>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmdata/dcdeftag.h>
namespace mitk
{
std::vector<CustomMimeType *> MitkDICOMPMIOMimeTypes::Get()
{
std::vector<CustomMimeType *> mimeTypes;
// order matters here (descending rank for mime types)
mimeTypes.push_back(DICOMPM_MIMETYPE().Clone());
return mimeTypes;
}
MitkDICOMPMIOMimeTypes::MitkDICOMPMMimeType::MitkDICOMPMMimeType() : CustomMimeType(DICOMPM_MIMETYPE_NAME())
{
this->AddExtension("dcm");
this->SetCategory(IOMimeTypes::CATEGORY_IMAGES());
this->SetComment("DICOM PM");
}
bool MitkDICOMPMIOMimeTypes::MitkDICOMPMMimeType::AppliesTo(const std::string &path) const
{
std::ifstream myfile;
myfile.open(path, std::ios::binary);
// myfile.seekg (128);
char *buffer = new char[128];
myfile.read(buffer, 128);
myfile.read(buffer, 4);
if (std::string(buffer).compare("DICM") != 0)
{
delete[] buffer;
return false;
}
delete[] buffer;
bool canRead(CustomMimeType::AppliesTo(path));
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if (!itksys::SystemTools::FileExists(path.c_str()))
{
return canRead;
}
// end fix for bug 18572
DcmFileFormat dcmFileFormat;
OFCondition status = dcmFileFormat.loadFile(path.c_str());
if (status.bad())
{
canRead = false;
}
if (!canRead)
{
return canRead;
}
OFString modality;
if (dcmFileFormat.getDataset()->findAndGetOFString(DCM_Modality, modality).good())
{
if (modality.compare("RWV") == 0)
{
canRead = true;
}
else
{
canRead = false;
}
}
return canRead;
}
MitkDICOMPMIOMimeTypes::MitkDICOMPMMimeType *MitkDICOMPMIOMimeTypes::MitkDICOMPMMimeType::Clone() const
{
return new MitkDICOMPMMimeType(*this);
}
MitkDICOMPMIOMimeTypes::MitkDICOMPMMimeType MitkDICOMPMIOMimeTypes::DICOMPM_MIMETYPE()
{
return MitkDICOMPMMimeType();
}
// Names
std::string MitkDICOMPMIOMimeTypes::DICOMPM_MIMETYPE_NAME()
{
// create a unique and sensible name for this mime type
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".image.dicom.pm";
return name;
}
}
diff --git a/Modules/DICOMUI/src/QmitkDicomExternalDataWidget.cpp b/Modules/DICOMUI/src/QmitkDicomExternalDataWidget.cpp
index 3e727a99f7..31d5b396fc 100644
--- a/Modules/DICOMUI/src/QmitkDicomExternalDataWidget.cpp
+++ b/Modules/DICOMUI/src/QmitkDicomExternalDataWidget.cpp
@@ -1,255 +1,255 @@
/*============================================================================
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.
============================================================================*/
// Qmitk
#include "QmitkDicomExternalDataWidget.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
// CTK
#include <ctkDICOMIndexer.h>
#include <ctkFileDialog.h>
// Qt
#include <QCheckBox>
#include <QMessageBox>
#include <QTemporaryFile>
const std::string QmitkDicomExternalDataWidget::Widget_ID = "org.mitk.Widgets.QmitkDicomExternalDataWidget";
QmitkDicomExternalDataWidget::QmitkDicomExternalDataWidget(QWidget *parent)
: QWidget(parent), m_ProgressDialog(nullptr), m_Controls(nullptr)
{
Initialize();
CreateQtPartControl(this);
}
QmitkDicomExternalDataWidget::~QmitkDicomExternalDataWidget()
{
}
void QmitkDicomExternalDataWidget::CreateQtPartControl(QWidget *parent)
{
// build up qt Widget, unless already done
if (!m_Controls)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkDicomExternalDataWidgetControls;
m_Controls->setupUi(parent);
m_Controls->viewExternalDataButton->setVisible(true);
m_Controls->ctkDICOMBrowser->setTableOrientation(Qt::Vertical);
m_Controls->ctkDICOMBrowser->setDICOMDatabase(m_ExternalDatabase);
SetupImportDialog();
// connect buttons
connect(m_Controls->downloadButton, SIGNAL(clicked()), this, SLOT(OnDownloadButtonClicked()));
connect(m_Controls->viewExternalDataButton, SIGNAL(clicked()), this, SLOT(OnViewButtonClicked()));
connect(m_Controls->directoryButton, SIGNAL(clicked()), m_ImportDialog, SLOT(show()));
connect(m_Controls->ctkDICOMBrowser,
SIGNAL(seriesSelectionChanged(const QStringList &)),
this,
SLOT(OnSeriesSelectionChanged(const QStringList &)));
connect(
m_Controls->ctkDICOMBrowser, SIGNAL(seriesDoubleClicked(const QModelIndex &)), this, SLOT(OnViewButtonClicked()));
connect(m_ImportDialog, SIGNAL(fileSelected(QString)), this, SLOT(OnStartDicomImport(QString)));
connect(m_ExternalIndexer,
SIGNAL(progressStep(QString)),
this,
SLOT(OnProgressStep(const QString&)));
connect(m_ExternalIndexer,
SIGNAL(progressDetail(QString)),
this,
SLOT(OnProgressDetail(const QString &)));
connect(m_ExternalIndexer, SIGNAL(progress(int)), this, SLOT(OnProgress(int)));
// actually the progress dialog closes if the maximum value is reached, BUT
// the following line is needed since the external indexer wont reach maximum value (100 % progress)
connect(m_ExternalIndexer, SIGNAL(indexingComplete(int, int, int, int)), this, SLOT(OnIndexingComplete(int, int, int, int)));
}
}
void QmitkDicomExternalDataWidget::OnProgressStep(const QString& step)
{
if (m_ProgressDialog == nullptr)
this->SetupProgressDialog();
m_ProgressStep = step;
m_ProgressDialog->setLabelText(step);
}
void QmitkDicomExternalDataWidget::OnProgressDetail(const QString& detail)
{
if (m_ProgressDialog == nullptr)
this->SetupProgressDialog();
m_ProgressDialog->setLabelText(m_ProgressStep+"\n"+detail);
}
void QmitkDicomExternalDataWidget::OnProgress(int value)
{
if (m_ProgressDialog == nullptr)
this->SetupProgressDialog();
m_ProgressDialog->setValue(value);
}
void QmitkDicomExternalDataWidget::OnIndexingComplete(int, int, int, int)
{
if (m_ProgressDialog != nullptr)
{
m_ProgressDialog->close();
m_ProgressDialog = nullptr;
}
}
void QmitkDicomExternalDataWidget::Initialize()
{
m_ExternalDatabase = new ctkDICOMDatabase(this);
try
{
// this used to be an in-memory database, but latest CTK enhancements made it difficult
// to maintain this mechanism
QTemporaryFile tmpDatabaseFile;
tmpDatabaseFile.open();
tmpDatabaseFile.setAutoRemove(false);
m_ExternalDatabase->openDatabase(tmpDatabaseFile.fileName(), QString("EXTERNAL-DB"));
}
catch (const std::exception&)
{
MITK_ERROR << "Database error: " << m_ExternalDatabase->lastError().toStdString();
m_ExternalDatabase->closeDatabase();
return;
}
m_ExternalIndexer = new ctkDICOMIndexer(this);
}
void QmitkDicomExternalDataWidget::OnDownloadButtonClicked()
{
QStringList filesToDownload = GetFileNamesFromIndex();
if (filesToDownload.size() == 0)
{
QMessageBox info;
info.setText("You have to select an entry in the DICOM browser for import.");
info.exec();
return;
}
emit SignalStartDicomImport(GetFileNamesFromIndex());
}
void QmitkDicomExternalDataWidget::OnViewButtonClicked()
{
QStringList uids = m_Controls->ctkDICOMBrowser->currentSeriesSelection();
QString uid;
foreach (uid, uids)
{
QStringList filesForSeries = m_ExternalDatabase->filesForSeries(uid);
QHash<QString, QVariant> eventProperty;
eventProperty.insert("FilesForSeries", filesForSeries);
if (!filesForSeries.isEmpty())
{
QString modality = m_ExternalDatabase->fileValue(filesForSeries.at(0), "0008,0060");
eventProperty.insert("Modality", modality);
}
emit SignalDicomToDataManager(eventProperty);
}
}
QStringList QmitkDicomExternalDataWidget::GetFileNamesFromIndex()
{
QStringList filePaths;
QString uid;
QStringList seriesUIDs = m_Controls->ctkDICOMBrowser->currentSeriesSelection();
foreach (uid, seriesUIDs)
{
filePaths.append(m_ExternalDatabase->filesForSeries(uid));
}
if (!filePaths.empty())
return filePaths;
QStringList studyUIDs = m_Controls->ctkDICOMBrowser->currentStudiesSelection();
foreach (uid, studyUIDs)
{
seriesUIDs = m_ExternalDatabase->seriesForStudy(uid);
foreach (uid, seriesUIDs)
{
filePaths.append(m_ExternalDatabase->filesForSeries(uid));
}
}
if (!filePaths.empty())
return filePaths;
QStringList patientsUIDs = m_Controls->ctkDICOMBrowser->currentPatientsSelection();
foreach (uid, patientsUIDs)
{
studyUIDs = m_ExternalDatabase->studiesForPatient(uid);
foreach (uid, studyUIDs)
{
seriesUIDs = m_ExternalDatabase->seriesForStudy(uid);
foreach (uid, seriesUIDs)
{
filePaths.append(m_ExternalDatabase->filesForSeries(uid));
}
}
}
return filePaths;
}
void QmitkDicomExternalDataWidget::OnStartDicomImport(const QString &directory)
{
m_ImportDialog->close();
// no need to show / start the progress dialog, as the dialog
// appears by receiving the progress signal from the external indexer
m_LastImportDirectory = directory;
m_ExternalIndexer->addDirectory(m_ExternalDatabase, m_LastImportDirectory);
}
void QmitkDicomExternalDataWidget::OnSeriesSelectionChanged(const QStringList &s)
{
m_Controls->viewExternalDataButton->setEnabled((s.size() != 0));
}
void QmitkDicomExternalDataWidget::SetupImportDialog()
{
// Initialize import widget
m_ImportDialog = new ctkFileDialog(this);
// Since copy on import is not working at the moment
// this feature is disabled
// QCheckBox* importCheckbox = new QCheckBox("Copy on import", m_ImportDialog);
// m_ImportDialog->setBottomWidget(importCheckbox);
m_ImportDialog->setFileMode(QFileDialog::Directory);
m_ImportDialog->setLabelText(QFileDialog::Accept, "Import");
m_ImportDialog->setWindowTitle("Import DICOM files from directory");
m_ImportDialog->setWindowModality(Qt::WindowModal);
}
void QmitkDicomExternalDataWidget::SetupProgressDialog()
{
if (m_ProgressDialog != nullptr)
return;
m_ProgressDialog = new QProgressDialog("Initialization ...", "Cancel", 0, 100, this);
m_ProgressDialog->setAttribute(Qt::WA_DeleteOnClose);
m_ProgressDialog->setWindowTitle("DICOM Import");
m_ProgressDialog->setWindowModality(Qt::WindowModal);
m_ProgressDialog->setMinimumDuration(0);
connect(m_ProgressDialog, SIGNAL(canceled()), m_ExternalIndexer, SLOT(cancel()));
}
diff --git a/Modules/DICOMUI/src/QmitkDicomLocalStorageWidget.cpp b/Modules/DICOMUI/src/QmitkDicomLocalStorageWidget.cpp
index 460b412664..8ee0dae06b 100644
--- a/Modules/DICOMUI/src/QmitkDicomLocalStorageWidget.cpp
+++ b/Modules/DICOMUI/src/QmitkDicomLocalStorageWidget.cpp
@@ -1,230 +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.
============================================================================*/
// Qmitk
#include "QmitkDicomLocalStorageWidget.h"
-//#include <mitkLogMacros.h>
// Qt
#include <QLabel>
#include <QMessageBox>
#include <QProgressDialog>
#include <QVariant>
#include <ctkDICOMIndexer.h>
const std::string QmitkDicomLocalStorageWidget::Widget_ID = "org.mitk.Widgets.QmitkDicomLocalStorageWidget";
QmitkDicomLocalStorageWidget::QmitkDicomLocalStorageWidget(QWidget *parent)
: QWidget(parent), m_LocalIndexer(new ctkDICOMIndexer(parent)), m_Controls(nullptr)
{
CreateQtPartControl(this);
}
QmitkDicomLocalStorageWidget::~QmitkDicomLocalStorageWidget()
{
m_LocalDatabase->closeDatabase();
}
void QmitkDicomLocalStorageWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
m_Controls = new Ui::QmitkDicomLocalStorageWidgetControls;
m_Controls->setupUi(parent);
connect(m_Controls->deleteButton, SIGNAL(clicked()), this, SLOT(OnDeleteButtonClicked()));
connect(m_Controls->viewInternalDataButton, SIGNAL(clicked()), this, SLOT(OnViewButtonClicked()));
connect(m_Controls->ctkDicomBrowser,
SIGNAL(seriesSelectionChanged(const QStringList &)),
this,
SLOT(OnSeriesSelectionChanged(const QStringList &)));
connect(m_Controls->ctkDicomBrowser,
SIGNAL(seriesSelectionChanged(const QStringList &)),
this,
SLOT(OnSeriesSelectionChanged(const QStringList &)));
connect(
m_Controls->ctkDicomBrowser, SIGNAL(seriesDoubleClicked(const QModelIndex &)), this, SLOT(OnViewButtonClicked()));
connect(m_LocalIndexer, SIGNAL(indexingComplete(int, int, int, int)), this, SIGNAL(SignalFinishedImport()));
m_Controls->ctkDicomBrowser->setTableOrientation(Qt::Vertical);
}
}
void QmitkDicomLocalStorageWidget::OnStartDicomImport(const QString &dicomData)
{
if (m_LocalDatabase->isOpen())
{
m_LocalIndexer->addDirectory(dicomData);
}
}
void QmitkDicomLocalStorageWidget::OnStartDicomImport(const QStringList &dicomData)
{
if (m_LocalDatabase->isOpen())
{
m_LocalIndexer->addListOfFiles( dicomData);
}
}
void QmitkDicomLocalStorageWidget::OnDeleteButtonClicked()
{
if (!this->DeletePatients())
{
if (!this->DeleteStudies())
{
this->DeleteSeries();
}
}
m_Controls->ctkDicomBrowser->updateTableViews();
}
bool QmitkDicomLocalStorageWidget::DeletePatients()
{
auto selectedPatientUIDs = m_Controls->ctkDicomBrowser->currentPatientsSelection();
if (!selectedPatientUIDs.empty())
{
QStringList studyUIDs;
for (const auto &patientUID : qAsConst(selectedPatientUIDs))
studyUIDs.append(m_LocalDatabase->studiesForPatient(patientUID));
QStringList seriesUIDs;
for (const auto &studyUID : studyUIDs)
seriesUIDs.append(m_LocalDatabase->seriesForStudy(studyUID));
auto answer = QMessageBox::question(nullptr,
"Delete Patients",
QString("Do you really want to delete %1 %2, containing %3 series in %4 %5?")
.arg(selectedPatientUIDs.count())
.arg(selectedPatientUIDs.count() != 1 ? "patients" : "patient")
.arg(seriesUIDs.count())
.arg(studyUIDs.count())
.arg(studyUIDs.count() != 1 ? "studies" : "study"),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No);
if (answer == QMessageBox::Yes)
{
for (const auto &patientUID : qAsConst(selectedPatientUIDs))
m_LocalDatabase->removePatient(patientUID);
}
return true;
}
return false;
}
bool QmitkDicomLocalStorageWidget::DeleteStudies()
{
auto selectedStudyUIDs = m_Controls->ctkDicomBrowser->currentStudiesSelection();
if (!selectedStudyUIDs.empty())
{
QStringList seriesUIDs;
for (const auto &studyUID : qAsConst(selectedStudyUIDs))
seriesUIDs.append(m_LocalDatabase->seriesForStudy(studyUID));
auto answer = QMessageBox::question(nullptr,
"Delete Studies",
QString("Do you really want to delete %1 %2, containing %3 series?")
.arg(selectedStudyUIDs.count())
.arg(selectedStudyUIDs.count() != 1 ? "studies" : "study")
.arg(seriesUIDs.count()),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No);
if (answer == QMessageBox::Yes)
{
for (const auto &studyUID : qAsConst(selectedStudyUIDs))
m_LocalDatabase->removeStudy(studyUID);
}
return true;
}
return false;
}
bool QmitkDicomLocalStorageWidget::DeleteSeries()
{
auto selectedSeriesUIDs = m_Controls->ctkDicomBrowser->currentSeriesSelection();
if (!selectedSeriesUIDs.empty())
{
auto answer =
QMessageBox::question(nullptr,
"Delete Series",
QString("Do you really want to delete %1 series?").arg(selectedSeriesUIDs.count()),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No);
if (answer == QMessageBox::Yes)
{
for (const auto &seriesUID : qAsConst(selectedSeriesUIDs))
m_LocalDatabase->removeSeries(seriesUID);
}
return true;
}
return false;
}
void QmitkDicomLocalStorageWidget::OnViewButtonClicked()
{
QStringList uids = m_Controls->ctkDicomBrowser->currentSeriesSelection();
QString uid;
foreach (uid, uids)
{
QStringList filesForSeries = m_LocalDatabase->filesForSeries(uid);
QHash<QString, QVariant> eventProperty;
eventProperty.insert("FilesForSeries", filesForSeries);
if (!filesForSeries.isEmpty())
{
QString modality = m_LocalDatabase->fileValue(filesForSeries.at(0), "0008,0060");
eventProperty.insert("Modality", modality);
}
emit SignalDicomToDataManager(eventProperty);
}
}
void QmitkDicomLocalStorageWidget::SetDatabaseDirectory(QString newDatatbaseDirectory)
{
QDir databaseDirecory = QDir(newDatatbaseDirectory);
if (!databaseDirecory.exists())
{
databaseDirecory.mkpath(databaseDirecory.absolutePath());
}
QString newDatatbaseFile = databaseDirecory.absolutePath() + QString("/ctkDICOM.sql");
this->SetDatabase(newDatatbaseFile);
}
void QmitkDicomLocalStorageWidget::SetDatabase(QString databaseFile)
{
m_LocalDatabase = new ctkDICOMDatabase(databaseFile);
m_LocalDatabase->setParent(this);
m_Controls->ctkDicomBrowser->setDICOMDatabase(m_LocalDatabase);
m_LocalIndexer->setDatabase(m_LocalDatabase);
}
void QmitkDicomLocalStorageWidget::OnSeriesSelectionChanged(const QStringList &s)
{
m_Controls->viewInternalDataButton->setEnabled((s.size() != 0));
}
diff --git a/Modules/DataTypesExt/CMakeLists.txt b/Modules/DataTypesExt/CMakeLists.txt
index fd7c68b54a..79a8245e24 100644
--- a/Modules/DataTypesExt/CMakeLists.txt
+++ b/Modules/DataTypesExt/CMakeLists.txt
@@ -1,6 +1,6 @@
mitk_create_module(
DEPENDS MitkCore
- PACKAGE_DEPENDS lz4
+ TARGET_DEPENDS PRIVATE LZ4::lz4_shared
)
add_subdirectory(test)
diff --git a/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.cpp
index 19bc8ffa15..ba923a831c 100644
--- a/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.cpp
+++ b/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.cpp
@@ -1,247 +1,247 @@
/*============================================================================
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 "mitkNavigationDataToPointSetFilter.h"
#include <mitkPointOperation.h>
#include <mitkInteractionConst.h>
#include <itksys/SystemTools.hxx>
mitk::NavigationDataToPointSetFilter::NavigationDataToPointSetFilter()
{
mitk::PointSet::Pointer output = mitk::PointSet::New();
this->SetNumberOfRequiredOutputs(1);
this->SetNthOutput(0, output.GetPointer());
this->SetNumberOfRequiredInputs(1);
m_OperationMode = Mode3D;
m_CurrentTimeStep = 0;
m_RingBufferSize = 50; //the default ring buffer size
m_NumberForMean = 100;
}
mitk::NavigationDataToPointSetFilter::~NavigationDataToPointSetFilter()
{
}
void mitk::NavigationDataToPointSetFilter::GenerateData()
{
switch (m_OperationMode)
{
case Mode3D:
GenerateDataMode3D();
break;
case Mode3DMean:
GenerateDataMode3DMean();
break;
case Mode4D:
GenerateDataMode4D();
break;
default:
break;
}
}
void mitk::NavigationDataToPointSetFilter::SetInput(const NavigationData* nd)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(0, const_cast<NavigationData*>(nd));
this->CreateOutputsForAllInputs();
}
void mitk::NavigationDataToPointSetFilter::SetInput(unsigned int idx, const NavigationData* nd)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(idx, const_cast<NavigationData*>(nd));
this->CreateOutputsForAllInputs();
}
const mitk::NavigationData* mitk::NavigationDataToPointSetFilter::GetInput( void )
{
if (this->GetNumberOfInputs() < 1)
return nullptr;
return static_cast<const NavigationData*>(this->ProcessObject::GetInput(0));
}
const mitk::NavigationData* mitk::NavigationDataToPointSetFilter::GetInput( unsigned int idx )
{
if (this->GetNumberOfInputs() < 1)
return nullptr;
return static_cast<const NavigationData*>(this->ProcessObject::GetInput(idx));
}
void mitk::NavigationDataToPointSetFilter::CreateOutputsForAllInputs()
{
switch (m_OperationMode)
{
case Mode3D:
this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); // create one pointset output for each navigation data input
break;
case Mode3DMean:
this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); // create one pointset output for each navigation data input
break;
case Mode4D:
this->SetNumberOfIndexedOutputs(1); // create just one output pointset that will contain all input navigation data objects
break;
default:
break;
}
for (unsigned int idx = 0; idx < this->GetNumberOfIndexedOutputs(); ++idx)
{
if (this->GetOutput(idx) == nullptr)
{
DataObjectPointer newOutput = this->MakeOutput(idx);
this->SetNthOutput(idx, newOutput);
}
}
this->Modified();
}
void mitk::NavigationDataToPointSetFilter::GenerateDataMode3D()
{
for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) // for each output PointSet
{
mitk::PointSet* output = this->GetOutput(i);
assert(output);
const mitk::NavigationData* input = this->GetInput(i);
assert(input);
if (input->IsDataValid() == false) // don't add point if input is invalid
continue;
mitk::PointSet::PointType pos = input->GetPosition(); // NavigationData::PositionType must be compatible with PointSet::PointType!
output->InsertPoint(output->GetSize(), pos); // add point with current position of input NavigationData to the output PointSet
// \TODO: regard ringbuffersize
}
}
/**
* @brief read n times all connected inputs and sum them into outputs. Finish with dividing each output by n.
**/
void mitk::NavigationDataToPointSetFilter::GenerateDataMode3DMean()
{
//make it editable through a Set method if needed
//check for outputs and inputs
for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) // for each output PointSet; change through pointsets to collect all navigation data in order
{
assert(this->GetOutput(i));
assert(this->GetInput(i));
}
//vector of counters for each output
std::vector<unsigned int> counterVec(this->GetNumberOfIndexedOutputs(),0);
//vector of old timesteps for each output
std::vector<mitk::NavigationData::TimeStampType> vectorOldTime(this->GetNumberOfIndexedOutputs());
//use first Output to get the size of the pointsets. All output pointssets have to have the same size!
mitk::PointSet::PointIdentifier newPointId = this->GetOutput()->GetSize();
bool numberForMean_is_reached = false;
while (!numberForMean_is_reached)
{
for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) // for each output PointSet; change through pointsets to collect all navigation data in order
{
mitk::PointSet* output = this->GetOutput(i);
const mitk::NavigationData* input = this->GetInput(i);
if (input->IsDataValid() == false) // don't add point if input is invalid
continue;//do not store
mitk::PointSet::PointType pos;
if (counterVec[i] == 0) //first Element must be inserted
{
vectorOldTime[i] = input->GetIGTTimeStamp();
//no need to call an update
pos = input->GetPosition(); // NavigationData::PositionType must be compatible with PointSet::PointType!
output->InsertPoint(newPointId, pos); // add point with current position of input NavigationData to the output PointSet
counterVec[i]++;
}
else
{
//manually call an update to track new positions
this->ProcessObject::GetInput(i)->Update();
input = this->GetInput(i);
mitk::NavigationData::TimeStampType newTime = input->GetIGTTimeStamp();
if (vectorOldTime[i]<newTime)
{
pos = input->GetPosition(); // NavigationData::PositionType must be compatible with PointSet::PointType!
//calculate the summ of the old position and the current coordinate
mitk::Vector3D vec(0.0);
vec.SetVnlVector(pos.GetVnlVector().as_ref());
mitk::PointSet::PointType oPoint = output->GetPoint(newPointId);
oPoint += vec;//summ up
output->SetPoint(newPointId, oPoint);
//store in counterVec to know how many have been added (and not skipped because of invalid data)
counterVec[i]++;
vectorOldTime[i] = newTime;
}
}
// \TODO: regard ringbuffersize
}
numberForMean_is_reached = true;
for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i)
{
if (counterVec[i]<m_NumberForMean)
numberForMean_is_reached = false;
}
}
//divide with counterVec
for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) // for each output PointSet; change through pointsets to collect all navigation data in order
{
mitk::PointSet* output = this->GetOutput(i);
mitk::PointSet::PointType oPoint = output->GetPoint(newPointId);
for (unsigned int index = 0; index < oPoint.Size(); index++)
oPoint[index] = oPoint[index] / counterVec[i];
output->SetPoint(newPointId, oPoint);
- MBI_INFO << "For output # " << i << ", " << counterVec[i] << " tracked positions used for averaging";
+ MITK_INFO << "For output # " << i << ", " << counterVec[i] << " tracked positions used for averaging";
}
}
void mitk::NavigationDataToPointSetFilter::GenerateDataMode4D()
{
mitk::PointSet* output = this->GetOutput();
assert(output);
for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++)
{
const mitk::NavigationData* nd = GetInput(index);
assert(nd);
mitk::NavigationData::PositionType point = nd->GetPosition(); //get the position
output->SetPoint( index, point, m_CurrentTimeStep); //store it in the pointset always at the current time step
}
if (m_CurrentTimeStep == m_RingBufferSize - 1) // update ring buffer index
m_CurrentTimeStep = 0;
else
m_CurrentTimeStep++;
}
void mitk::NavigationDataToPointSetFilter::SetOperationMode( OperationMode mode )
{
m_OperationMode = mode;
//Initialize 4D Mode
if (m_OperationMode == Mode4D)
m_CurrentTimeStep = 0;
this->Modified();
this->CreateOutputsForAllInputs();
}
diff --git a/Modules/IGT/TrackingDevices/mitkClaronInterfaceStub.h b/Modules/IGT/TrackingDevices/mitkClaronInterfaceStub.h
index bb7ccac41d..f592796e45 100644
--- a/Modules/IGT/TrackingDevices/mitkClaronInterfaceStub.h
+++ b/Modules/IGT/TrackingDevices/mitkClaronInterfaceStub.h
@@ -1,115 +1,115 @@
/*============================================================================
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 mitkClaronInterface_h // Must be equal to include guard in mitkClaronInterface.h
#define mitkClaronInterface_h
#include <vector>
#include <string>
#include <MitkIGTExports.h>
#include <itkObject.h>
#include <itkObjectFactory.h>
#include "mitkCommon.h"
typedef int mtHandle;
namespace mitk
{
typedef int claronToolHandle;
/** Documentation:
* \brief An object of this class represents the interface to the MicronTracker. Normally the methods of this class
* are calling the c-functions which are provided by the MTC-library. But in this case the MicronTracker is
* not installed and so we only have stubs here. These stubs send error messages when you try to call the
* methods.
* \ingroup IGT
*/
- class MITKIGT_EXPORT ClaronInterface : public itk::Object
+ class MITKIGT_EXPORT ClaronInterface /** \cond */ : public itk::Object /** \endcond */
{
public:
mitkClassMacroItkParent(ClaronInterface, itk::Object);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self)
/**
* \brief Initialization of claroninterface.
* \param calibrationDir The directory where the device can find the camera calibration file.
* \param toolFilesDir The directory for the tool files.
*/
void Initialize(std::string calibrationDir, std::string toolFilesDir);
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
bool StartTracking();
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
bool StopTracking();
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
std::vector<claronToolHandle> GetAllActiveTools();
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
std::vector<double> GetTipPosition(claronToolHandle c);
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
std::vector<double> GetTipQuaternions(claronToolHandle c);
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
std::vector<double> GetPosition(claronToolHandle c);
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
std::vector<double> GetQuaternions(claronToolHandle c);
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
const char* GetName(claronToolHandle c);
/**
* \brief This is only a stub, please switch the cmake variable USE_MICRON_TRACKER to on if you want to use the Microntracker.
*/
void GrabFrame();
/**
* \return Returns wether the MicronTracker is installed (means wether the C-Make-Variable "MITK_USE_MICRON_TRACKER" is set),
* so returns false in this case.
*/
bool IsMicronTrackerInstalled();
protected:
/**
* \brief standard constructor
*/
ClaronInterface();
/**
* \brief standard destructor
*/
~ClaronInterface() override;
};
}//mitk
#endif
diff --git a/Modules/IGT/TrackingDevices/mitkOptitrackTrackingDevice.h b/Modules/IGT/TrackingDevices/mitkOptitrackTrackingDevice.h
index 409841a297..cc6271ddef 100644
--- a/Modules/IGT/TrackingDevices/mitkOptitrackTrackingDevice.h
+++ b/Modules/IGT/TrackingDevices/mitkOptitrackTrackingDevice.h
@@ -1,301 +1,291 @@
/*============================================================================
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 mitkOptitrackTrackingDevice_h
#define mitkOptitrackTrackingDevice_h
#include <MitkIGTExports.h>
#include <mitkTrackingDevice.h>
#include <mitkTrackingTypes.h>
#include <mitkIGTTimeStamp.h>
#include <itksys/SystemTools.hxx>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <thread>
#include <mutex>
/**
* \brief IGT Exceptions
*/
#include "mitkIGTIOException.h"
#include "mitkIGTTimeStamp.h"
#include "mitkIGTException.h"
/**
* \brief OptitrackTrackingTools
*/
#include "mitkOptitrackTrackingTool.h"
namespace mitk
{
/** Documentation:
* \brief An object of this class represents the Optitrack device. You can add tools to this
* device, then open the connection and start tracking. The tracking device will then
* continuously update the tool coordinates. Remember that it will be necessary to
* to have a license for using the Optitrack System.
* See https://www.naturalpoint.com/ for details.
* \author E. Marinetto (emarinetto@hggm.es) Instituto de Investigación Sanitaria Gregorio Marañón, Madrid, Spain. & M. Noll (matthias.noll@igd.fraunhofer.de) Cognitive Computing & Medical Imaging | Fraunhofer IGD
* \ingroup IGT
*/
class MITKIGT_EXPORT OptitrackTrackingDevice : public mitk::TrackingDevice
{
friend class OptitrackTrackingTool;
public:
mitkClassMacro(OptitrackTrackingDevice, mitk::TrackingDevice);
itkNewMacro(Self);
/**
* @returns Returns true if the Optitrack tracker is installed on this build (means activated in CMAKE). False if not.
*/
bool IsDeviceInstalled() override;
// Define the Type of Tracker as DefinitionOfTool (MITK)
typedef mitk::TrackingDeviceType OptiTrackTrackingDeviceType;
/**
* \brief Open the Connection with the Tracker. Calls LoadCalibration function and set the system up with the calibration file.
* Remember that you have to set a calibration file first to open a correct connection to the Optical Tracking System.
* \return Returns true if the connection is well done. Throws an exception if an error occures related to the Optitrack API messages.
* @throw mitk::IGTException Throws an exception if InitializeCameras or LoadCalibration failed.
*/
bool OpenConnection() override;
/**
* \brief Close the Connection with the Tracker. Also CleanUp the Optitrack variables using the API: TT_CleanUp and TT_ShutDown.
* Sometimes API does not work properly and some problems during the Clean Up has been reported.
* \return Returns true if the cleaning up and shutdown worked correctly. Throws an exception if an error occures related to the Optitrack API messages.
* @throw mitk::IGTException Throws an exception if the System cannot ShutDown now or was not initialized.
*/
bool CloseConnection() override;
/**
* \brief Start to Track the tools already defined. If no tools are defined for this tracker, it returns an error.
* Tools can be added using either AddToolByDescriptionFile or AddToolsByConfigurationFiles
* \return Returns true at least one tool was defined and the tracking is correct
* @throw mitk::IGTException Throws an exception if the System is not in State Ready .
*/
bool StartTracking() override;
/**
* \brief Stop the Tracking Thread and tools will not longer be updated.
* \return Returns true if Tracking thread could be stopped.
* @throw mitk::IGTException Throws an exception if System is not in State Tracking.
*/
bool StopTracking() override;
/**
* \brief Return the tool pointer of the tool number toolNumber
* \param toolNumber The number of the tool which should be given back.
* \return Returns the tool which the number "toolNumber". Returns nullptr, if there is
* no tool with this number.
*/
TrackingTool* GetTool(unsigned int toolNumber) const override;
/**
* \brief Return the tool pointer of the tool number toolNumber
* \param toolNumber The number of the tool which should be given back.
* \return Returns the tool which the number "toolNumber". Returns nullptr, if there is
* no tool with this number.
* @throw mitk::IGTException Throws an exception if there is the required tool does not exist.
*/
OptitrackTrackingTool* GetOptitrackTool(unsigned int toolNumber) const;
/**
* \brief Returns the number of defined tools
* \return Returns the number of defined tools in the Optitrack device.
*/
unsigned int GetToolCount() const override;
/** @brief Sets the directory where the calibration file of the MicronTracker can be found. */
itkSetMacro(Exp,int);
/** @brief Gets the current calibration directory. */
itkGetMacro(Exp,int);
/** @brief Sets the directory where the calibration file of the MicronTracker can be found. */
itkSetMacro(Led,int);
/** @brief Gets the current calibration directory. */
itkGetMacro(Led,int);
/** @brief Sets the directory where the calibration file of the MicronTracker can be found. */
itkSetMacro(Thr,int);
/** @brief Gets the current calibration directory. */
itkGetMacro(Thr,int);
/** @brief Sets the file where the calibration of the OptitrackTracker can be found. */
void SetCalibrationPath(std::string calibrationPath);
/** @brief Gets the current calibration file. */
itkGetMacro(calibrationPath,std::string);
/**
* \brief Start the Tracking Thread for the tools
*/
void ThreadStartTracking();
/**
* \brief Update each tool location in the list m_AllTools
* @throw mitk::IGTException Throws an exception if the getting data operation failed for a defined tool
*/
void TrackTools();
/**
* \brief Load the Calibration file to the Optitrack System and set the cameras in calibrated locations
* \return Returns true if the calibration was uploaded correctly
* @throw mitk::IGTException Throws an exception if Calibration Path is empty, the System cannot load a calibration file or System is not ready for load a calibration file because it has not been initialized yet
*/
bool LoadCalibration();
/**
* \brief Set the Cameras Exposure, Threshold and Intensity of IR LEDs. By Default it set the Video type to 4: Precision Mode for tracking
* //== VideoType:
* //== 0 = Segment Mode
* //== 1 = Grayscale Mode
* //== 2 = Object Mode
* //== 4 = Precision Mode
* //== 6 = MJPEG Mode (V100R2 only)
* \return Returns true if all cameras were set up correctly
* @throw mitk::IGTException Throws an exception if System is not Initialized
*/
bool SetCameraParams(int exposure, int threshold, int intensity, int videoType = 4);
/**
* \brief Initialize the Optitrack System
* \return Returns true if system was initialized correctly
* @throw mitk::IGTException Throws an exception if the Optitrack Tracking System cannot be initialized
*/
bool InitializeCameras();
/**
* \brief Add a new tool using a text file which described the tool.
* The file must to have the next structure
* ToolName
* \#NumberOfMarkers
* X Y Z - for the first marker
* X Y Z - for the second marker
* ...
* X Y Z - for the last marker, the number \#NumberOfMarkers
* X Y Z - for the PIVOT point
* \return Returns true if system was initialized correctly
* @throw mitk::IGTException Throws an exception if Tool could not be added or System is not Initialized
*/
bool AddToolByDefinitionFile(std::string fileName); // ^????? We should give an example of defined tool
- /**
- * \brief This function load a file with Tools definitions provided for the software
- * \return Returns true if file is correctly loaded with all the tools
- * @throw mitk::IGTException Throws an exception if there is an error during the Initialization
- */
-// bool AddToolByConfigurationFil(std::string fileName); // For next release....
-
protected:
- /**
- * \brief Constructor & Destructor of the class
- */
OptitrackTrackingDevice();
~OptitrackTrackingDevice() override;
private:
/**
* \brief The calibration file path. This file is produced by TrackingTools/Motive software.
* This variable is used to determine what will be the calibration file absolute path.
*/
std::string m_calibrationPath;
/**
* \brief The Cameras Exposition
*/
int m_Exp;
/**
* \brief The Cameras LED power
*/
int m_Led;
/**
* \brief The Cameras Thr
*/
int m_Thr;
/**
* \brief Described if the system was initialized at least once during execution. This is due
* to some reported problems during the clean up , shutdown and initialization again.
*/
bool m_initialized;
/**
* \brief Vector of pointers pointing to all defined tools
*/
std::vector<mitk::OptitrackTrackingTool::Pointer> m_AllTools;
/**
* \brief Mutex for coordinated access of tool container
*/
mutable std::mutex m_ToolsMutex;
std::thread m_Thread;
/* TODO:
// For Tracking
-bool AddToolByConfigurationFil(std::string fileName);
TTAPI NPRESULT TT_LoadTrackables (const char *filename); //== Load Trackables ======----
TTAPI NPRESULT TT_SaveTrackables (const char *filename); //== Save Trackables ======----
TTAPI NPRESULT TT_AddTrackables (const char *filename); //== Add Trackables ======----
TTAPI void TT_ClearTrackableList(); //== Clear all trackables =====---
TTAPI NPRESULT TT_RemoveTrackable(int Index); //== Remove single trackable ====---
TTAPI void TT_SetTrackableEnabled(int index, bool enabled); //== Set Tracking ====---
TTAPI bool TT_TrackableEnabled(int index); //== Get Tracking ====---
TTAPI int TT_TrackableMarkerCount(int index); //== Get marker count ====---
TTAPI void TT_TrackableMarker(int RigidIndex, //== Get Trackable mrkr ====---
int MarkerIndex, float *x, float *y, float *z);
//For projects
TTAPI NPRESULT TT_LoadProject(const char *filename); //== Load Project File ==========--
TTAPI NPRESULT TT_SaveProject(const char *filename); //== Save Project File ==========--
// For VRPN connection
TTAPI NPRESULT TT_StreamVRPN(bool enabled, int port);//== Start/stop VRPN Stream ===----
// For frame testing
TTAPI int TT_FrameMarkerCount(); //== Returns Frame Markers Count ---
TTAPI float TT_FrameMarkerX(int index); //== Returns X Coord of Marker -----
TTAPI float TT_FrameMarkerY(int index); //== Returns Y Coord of Marker -----
TTAPI float TT_FrameMarkerZ(int index); //== Returns Z Coord of Marker -----
TTAPI int TT_FrameMarkerLabel(int index); //== Returns Label of Marker -------
TTAPI double TT_FrameTimeStamp(); //== Time Stamp of Frame (seconds) -
// For cameras handling
TTAPI int TT_CameraCount(); //== Returns Camera Count =====-----
TTAPI float TT_CameraXLocation(int index); //== Returns Camera's X Coord =-----
TTAPI float TT_CameraYLocation(int index); //== Returns Camera's Y Coord =-----
TTAPI float TT_CameraZLocation(int index); //== Returns Camera's Z Coord =-----
TTAPI float TT_CameraOrientationMatrix(int camera, int index); //== Orientation -----
*/
};
}
#endif
diff --git a/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.cpp
index cdf8a4a56f..37c67f5fbd 100644
--- a/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.cpp
+++ b/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.cpp
@@ -1,307 +1,307 @@
/*============================================================================
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 "mitkVirtualTrackingDevice.h"
#include "mitkIGTTimeStamp.h"
#include "mitkIGTException.h"
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <itksys/SystemTools.hxx>
#include <random>
#include <mitkVirtualTrackerTypeInformation.h>
mitk::VirtualTrackingDevice::VirtualTrackingDevice() : mitk::TrackingDevice(),
m_AllTools(), m_RefreshRate(100), m_NumberOfControlPoints(20), m_GaussianNoiseEnabled(false),
m_MeanDistributionParam(0.0), m_DeviationDistributionParam(1.0)
{
m_Data = mitk::VirtualTrackerTypeInformation::GetDeviceDataVirtualTracker();
m_Bounds[0] = m_Bounds[2] = m_Bounds[4] = -400.0; // initialize bounds to -400 ... +400 (mm) cube
m_Bounds[1] = m_Bounds[3] = m_Bounds[5] = 400.0;
}
mitk::VirtualTrackingDevice::~VirtualTrackingDevice()
{
if (this->GetState() == Tracking)
{
this->StopTracking();
}
if (this->GetState() == Ready)
{
this->CloseConnection();
}
/* cleanup tracking thread */
if (m_Thread.joinable())
m_Thread.join();
m_AllTools.clear();
}
mitk::TrackingTool* mitk::VirtualTrackingDevice::AddTool(const char* toolName)
{
//if (this->GetState() == Tracking)
//{
// return nullptr;
//}
mitk::VirtualTrackingTool::Pointer t = mitk::VirtualTrackingTool::New();
t->SetToolName(toolName);
t->SetVelocity(0.1);
this->InitializeSpline(t);
std::lock_guard<std::mutex> lock(m_ToolsMutex); // lock and unlock the mutex
m_AllTools.push_back(t);
return t;
}
bool mitk::VirtualTrackingDevice::StartTracking()
{
if (this->GetState() != Ready)
return false;
this->SetState(Tracking); // go to mode Tracking
this->m_StopTrackingMutex.lock();
this->m_StopTracking = false;
this->m_StopTrackingMutex.unlock();
mitk::IGTTimeStamp::GetInstance()->Start(this);
if (m_Thread.joinable())
m_Thread.detach();
m_Thread = std::thread(&VirtualTrackingDevice::ThreadStartTracking, this); // start a new thread that executes the TrackTools() method
return true;
}
bool mitk::VirtualTrackingDevice::StopTracking()
{
if (this->GetState() == Tracking) // Only if the object is in the correct state
{
m_StopTrackingMutex.lock(); // m_StopTracking is used by two threads, so we have to ensure correct thread handling
m_StopTracking = true;
m_StopTrackingMutex.unlock();
m_TrackingFinishedMutex.lock();
this->SetState(Ready);
m_TrackingFinishedMutex.unlock();
}
mitk::IGTTimeStamp::GetInstance()->Stop(this);
return true;
}
unsigned int mitk::VirtualTrackingDevice::GetToolCount() const
{
std::lock_guard<std::mutex> lock(m_ToolsMutex); // lock and unlock the mutex
return static_cast<unsigned int>(this->m_AllTools.size());
}
mitk::TrackingTool* mitk::VirtualTrackingDevice::GetTool(unsigned int toolNumber) const
{
std::lock_guard<std::mutex> lock(m_ToolsMutex); // lock and unlock the mutex
if (toolNumber < m_AllTools.size())
return this->m_AllTools.at(toolNumber);
return nullptr;
}
bool mitk::VirtualTrackingDevice::OpenConnection()
{
if (m_NumberOfControlPoints < 1)
{
mitkThrowException(mitk::IGTException) << "to few control points for spline interpolation";
}
srand(time(nullptr)); //Init random number generator
this->SetState(Ready);
return true;
}
void mitk::VirtualTrackingDevice::InitializeSpline(mitk::VirtualTrackingTool* t)
{
if (t == nullptr)
return;
typedef mitk::VirtualTrackingTool::SplineType SplineType;
/* create random control points */
SplineType::ControlPointListType controlPoints;
controlPoints.reserve(m_NumberOfControlPoints + 1);
controlPoints.push_back(this->GetRandomPoint()); // insert point 0
double length = 0.0; // estimate spline length by calculating line segments lengths
for (unsigned int i = 1; i < m_NumberOfControlPoints - 1; ++i) // set points 1..n-2
{
SplineType::ControlPointType pos;
pos = this->GetRandomPoint();
length += controlPoints.at(i - 1).EuclideanDistanceTo(pos);
controlPoints.push_back(pos);
}
controlPoints.push_back(controlPoints.at(0)); // close spline --> insert point last control point with same value as first control point
length += controlPoints.at(controlPoints.size() - 2).EuclideanDistanceTo(controlPoints.at(controlPoints.size() - 1));
/* Create knot list. TODO: rethink knot list values and list size. Is there a better solution? */
SplineType::KnotListType knotList;
knotList.push_back(0.0);
for (unsigned int i = 1; i < controlPoints.size() + t->GetSpline()->GetSplineOrder() + 1; ++i)
knotList.push_back(i);
knotList.push_back(controlPoints.size() + t->GetSpline()->GetSplineOrder() + 1);
t->GetSpline()->SetControlPoints(controlPoints);
t->GetSpline()->SetKnots(knotList);
t->SetSplineLength(length);
}
bool mitk::VirtualTrackingDevice::CloseConnection()
{
bool returnValue = true;
if (this->GetState() == Setup)
return true;
this->SetState(Setup);
return returnValue;
}
mitk::ScalarType mitk::VirtualTrackingDevice::GetSplineChordLength(unsigned int idx)
{
mitk::VirtualTrackingTool* t = this->GetInternalTool(idx);
if (t != nullptr)
return t->GetSplineLength();
else
throw std::invalid_argument("invalid index");
}
void mitk::VirtualTrackingDevice::SetToolSpeed(unsigned int idx, mitk::ScalarType roundsPerSecond)
{
if (roundsPerSecond < 0.0001)
throw std::invalid_argument("Minimum tool speed is 0.0001 rounds per second");
mitk::VirtualTrackingTool* t = this->GetInternalTool(idx);
if (t != nullptr)
t->SetVelocity(roundsPerSecond);
else
throw std::invalid_argument("invalid index");
}
mitk::VirtualTrackingTool* mitk::VirtualTrackingDevice::GetInternalTool(unsigned int idx)
{
std::lock_guard<std::mutex> toolsMutexLockHolder(m_ToolsMutex); // lock and unlock the mutex
if (idx < m_AllTools.size())
return m_AllTools.at(idx);
else
return nullptr;
}
void mitk::VirtualTrackingDevice::TrackTools()
{
/* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */
std::lock_guard<std::mutex> trackingFinishedLockHolder(m_TrackingFinishedMutex); // keep lock until end of scope
if (this->GetState() != Tracking)
return;
bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here
this->m_StopTrackingMutex.lock(); // update the local copy of m_StopTracking
localStopTracking = this->m_StopTracking;
this->m_StopTrackingMutex.unlock();
mitk::ScalarType t = 0.0;
while ((this->GetState() == Tracking) && (localStopTracking == false))
{
//for (ToolContainer::iterator itAllTools = m_AllTools.begin(); itAllTools != m_AllTools.end(); itAllTools++)
for (unsigned int i = 0; i < this->GetToolCount(); ++i) // use mutexed methods to access tool container
{
mitk::VirtualTrackingTool::Pointer currentTool = this->GetInternalTool(i);
mitk::VirtualTrackingTool::SplineType::PointType pos;
/* calculate tool position with spline interpolation */
pos = currentTool->GetSpline()->EvaluateSpline(t);
mitk::Point3D mp;
mitk::itk2vtk(pos, mp); // convert from SplineType::PointType to mitk::Point3D
//Add Gaussian Noise to Tracking Coordinates if enabled
if (this->m_GaussianNoiseEnabled)
{
std::random_device rd;
std::mt19937 generator(rd());
std::normal_distribution<double> dist(this->m_MeanDistributionParam, this->m_DeviationDistributionParam);
double noise = dist(generator);
- mp = mp + noise;
+ mp = mp + mitk::Vector(noise);
}
currentTool->SetPosition(mp);
// Currently, a constant speed is used. TODO: use tool velocity setting
t += 0.001;
if (t >= 1.0)
t = 0.0;
mitk::Quaternion quat;
/* fix quaternion rotation */
quat.x() = 0.0;
quat.y() = 0.0;
quat.z() = 0.0;
quat.r() = 1.0;
quat.normalize();
currentTool->SetOrientation(quat);
// TODO: rotate once per cycle around a fixed rotation vector
currentTool->SetTrackingError(2 * (rand() / (RAND_MAX + 1.0))); // tracking error in 0 .. 2 Range
currentTool->SetDataValid(true);
currentTool->Modified();
}
itksys::SystemTools::Delay(m_RefreshRate);
/* Update the local copy of m_StopTracking */
this->m_StopTrackingMutex.lock();
localStopTracking = m_StopTracking;
this->m_StopTrackingMutex.unlock();
} // tracking ends if we pass this line
}
void mitk::VirtualTrackingDevice::ThreadStartTracking()
{
this->TrackTools();
}
mitk::VirtualTrackingDevice::ControlPointType mitk::VirtualTrackingDevice::GetRandomPoint()
{
ControlPointType pos;
pos[0] = m_Bounds[0] + (m_Bounds[1] - m_Bounds[0]) * (rand() / (RAND_MAX + 1.0)); // X = xMin + xRange * (random number between 0 and 1)
pos[1] = m_Bounds[2] + (m_Bounds[3] - m_Bounds[2]) * (rand() / (RAND_MAX + 1.0)); // Y
pos[2] = m_Bounds[4] + (m_Bounds[5] - m_Bounds[4]) * (rand() / (RAND_MAX + 1.0)); // Z
return pos;
}
void mitk::VirtualTrackingDevice::EnableGaussianNoise()
{
this->m_GaussianNoiseEnabled = true;
}
void mitk::VirtualTrackingDevice::DisableGaussianNoise()
{
this->m_GaussianNoiseEnabled = false;
}
void mitk::VirtualTrackingDevice::SetParamsForGaussianNoise(double meanDistribution, double deviationDistribution)
{
this->m_MeanDistributionParam = meanDistribution;
this->m_DeviationDistributionParam = deviationDistribution;
}
double mitk::VirtualTrackingDevice::GetDeviationDistribution()
{
return m_DeviationDistributionParam;
}
double mitk::VirtualTrackingDevice::GetMeanDistribution()
{
return m_MeanDistributionParam;
}
diff --git a/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.h b/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.h
index 84d331c72e..2bbf698ea7 100644
--- a/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.h
+++ b/Modules/IGT/TrackingDevices/mitkVirtualTrackingDevice.h
@@ -1,214 +1,213 @@
/*============================================================================
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 mitkVirtualTrackingDevice_h
#define mitkVirtualTrackingDevice_h
#include <MitkIGTExports.h>
#include <mitkTrackingDevice.h>
#include <mitkVirtualTrackingTool.h>
#include <mutex>
#include <thread>
#include <vector>
namespace mitk
{
/** Documentation
* \brief Class representing a tracking device which generates random positions / orientations.
* No hardware is needed for tracking device.
*
* This TrackingDevice class does not interface with a physical tracking device. It simulates
* a tracking device by moving the tools on a randomly generated spline path.
*
* \ingroup IGT
*/
class MITKIGT_EXPORT VirtualTrackingDevice : public TrackingDevice
{
public:
mitkClassMacro(VirtualTrackingDevice, TrackingDevice);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
/**
* \brief Sets the refresh rate of the virtual tracking device in ms
* \warning This refresh rate is not guaranteed. A thread is used to refresh the positions
* of the virtual tools. However, this thread may not run at all during this refresh time period.
- * \return Sets the refresh rate of the virtual tracking device in ms
*/
itkSetMacro(RefreshRate, unsigned int);
/**
* \brief Returns the refresh rate in ms.
* \return Returns the refresh rate in ms.
*/
itkGetConstMacro(RefreshRate, unsigned int);
/**
* \brief Starts the tracking.
*
* After StartTracking() is called,
* the tools will move on their spline paths with a constant velocity that can be set with
* SetToolSpeed(). The standard velocity is 10 seconds for one complete cycle along the spline path.
* \warning tool speed is not yet used in the current version
* \return Returns true if the tracking is started. Returns false if there was an error.
*/
bool StartTracking() override;
/**
* \brief Stops the tracking.
* \return Returns true if the tracking is stopped. Returns false if there was an error.
*/
bool StopTracking() override;
/**
* \brief Opens the connection to the device. This have to be done before the tracking is started.
* @throw mitk::IGTException Throws an exception if there are two less control points to start the the virtual device.
*/
bool OpenConnection() override;
/**
* \brief Closes the connection and clears all resources.
*/
bool CloseConnection() override;
/**
* \return Returns the number of tools which have been added to the device.
*/
unsigned int GetToolCount() const override;
/**
* \param toolNumber The number of the tool which should be given back.
* \return Returns the tool which the number "toolNumber". Returns nullptr, if there is
* no tool with this number.
*/
TrackingTool* GetTool(unsigned int toolNumber) const override;
/**
* \brief Adds a tool to the tracking device.
*
* The tool will have a random path on which it will move around. The path is created with a
* spline function and random control points inside the tracking volume.
*
* \param toolName The tool which will be added.
* \return Returns true if the tool has been added, false otherwise.
*/
TrackingTool* AddTool(const char* toolName);
/**
* \brief Set the tracking volume bounds
*
* This will set the tracking volume as an axis aligned bounding box
* defined by the six bounds values xMin, xMax, yMin, yMax, zMin, zMax.
* Note that the random path of existing tools will not be updated with the new
* tracking volume. Tools that are created after calling SetBounds() will use the
* new tracking volume
*/
itkSetVectorMacro(Bounds, mitk::ScalarType, 6);
/**
* \brief return the tracking volume bounds
*
* This will return the tracking volume as an axis aligned bounding box
* defined by the six bounds values xMin, xMax, yMin, yMax, zMin, zMax
*/
const mitk::ScalarType* GetBounds() const
{
return m_Bounds;
};
/**
* \brief return the approximate length of the spline for tool with index idx in millimeter
*
* if the index idx is not a
* valid tool index, a std::invalid_argument exception is thrown.
* GetSplineChordLength() returns the distance between all control points of the
* spline in millimeter. This can be used as an approximation for the length of the spline path.
*/
mitk::ScalarType GetSplineChordLength(unsigned int idx);
/**
* \brief sets the speed of the tool idx in rounds per second
*
* The virtual tools will travel along a closed spline path.
* This method sets the speed of a tool as a factor of how many rounds per second
* the tool should move. A setting of 1.0 will indicate one complete round per second.
* Together with GetSplineChordLength(), the speed in millimeter per second can be estimated.
* roundsPerSecond must be positive and larger than 0.0001.
* \warning Tool speed is currently not used.
* \todo use tool speed
*/
void SetToolSpeed(unsigned int idx, mitk::ScalarType roundsPerSecond);
/**
* \brief enable addition of Gaussian Noise to tracking coordinates
*/
void EnableGaussianNoise();
/**
* \brief disable addition of Gaussian Noise to Trackin coordinates
*/
void DisableGaussianNoise();
/**
* \brief sets the mean distribution and the standard deviation for the Gaussian Noise
*
*/
void SetParamsForGaussianNoise(double meanDistribution, double deviationDistribution);
/**
* \brief returns the mean distribution for the Gaussian Noise
*/
double GetMeanDistribution();
/**
* \brief returns the deviation distribution for the Gaussian Noise
*/
double GetDeviationDistribution();
protected:
VirtualTrackingDevice();
~VirtualTrackingDevice() override;
/**
* \brief This method tracks tools as long as the variable m_Mode is set to "Tracking".
* Tracking tools means generating random numbers for the tool position and orientation.
* @throw mitk::IGTException Throws an mitk::IGTException if there is an error during virtual tool tracking.
*/
void TrackTools();
void InitializeSpline(mitk::VirtualTrackingTool* t); ///< initializes the spline path of the tool t with random control points inside the current tracking volume
void ThreadStartTracking(); ///< static start method for tracking thread
typedef mitk::VirtualTrackingTool::SplineType::ControlPointType ControlPointType;
ControlPointType GetRandomPoint(); ///< returns a random position inside the tracking volume (defined by m_Bounds)
mitk::VirtualTrackingTool* GetInternalTool(unsigned int idx);
typedef std::vector<VirtualTrackingTool::Pointer> ToolContainer; ///< container type for tracking tools
ToolContainer m_AllTools; ///< container for all tracking tools
mutable std::mutex m_ToolsMutex; ///< mutex for coordinated access of tool container
std::thread m_Thread;
unsigned int m_RefreshRate; ///< refresh rate of the internal tracking thread in milliseconds (NOT refreshs per second!)
unsigned int m_NumberOfControlPoints; ///< number of control points for the random path generation
mitk::ScalarType m_Bounds[6]; ///< bounding box of the tracking volume stored as {xMin, xMax, yMin, yMax, zMin, zMax}
bool m_GaussianNoiseEnabled; ///< adding Gaussian Noise to tracking coordinates or not, false by default
double m_MeanDistributionParam; /// mean distribution for Gaussion Noise, 0.0 by default
double m_DeviationDistributionParam; ///< deviation distribution for Gaussian Noise, 1.0 by default
};
}//mitk
#endif
diff --git a/Modules/IGTBase/include/mitkIGTException.h b/Modules/IGTBase/include/mitkIGTException.h
index 0bc18470da..08b44fc2b6 100644
--- a/Modules/IGTBase/include/mitkIGTException.h
+++ b/Modules/IGTBase/include/mitkIGTException.h
@@ -1,31 +1,31 @@
/*============================================================================
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 mitkIGTException_h
#define mitkIGTException_h
#include <MitkIGTBaseExports.h>
#include <mitkException.h>
#include "mitkExceptionMacro.h"
namespace mitk {
/**Documentation
* \brief An object of this class represents an exception of the MITK-IGT module.
*
* \ingroup IGT
-*/ class MITKIGTBASE_EXPORT IGTException : public mitk::Exception
+*/ class MITKIGTBASE_EXPORT IGTException /** \cond */ : public mitk::Exception /** \endcond */
{
public:
- mitkExceptionClassMacro(IGTException,mitk::Exception);
+ mitkExceptionClassMacro(IGTException, mitk::Exception)
};
} // namespace mitk
#endif
diff --git a/Modules/IGTBase/include/mitkIGTHardwareException.h b/Modules/IGTBase/include/mitkIGTHardwareException.h
index 201b5fc886..a92ea8c771 100644
--- a/Modules/IGTBase/include/mitkIGTHardwareException.h
+++ b/Modules/IGTBase/include/mitkIGTHardwareException.h
@@ -1,30 +1,30 @@
/*============================================================================
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 mitkIGTHardwareException_h
#define mitkIGTHardwareException_h
#include "mitkIGTException.h"
#include "mitkExceptionMacro.h"
namespace mitk {
/**Documentation
* \brief An object of this class represents an exception of the MITK-IGT module which are releated to the hardware (e.g. connection problems, etc.).
*
* \ingroup IGT
- */ class MITKIGTBASE_EXPORT IGTHardwareException : public mitk::IGTException
+ */ class MITKIGTBASE_EXPORT IGTHardwareException /** \cond */ : public mitk::IGTException /** \endcond */
{
public:
mitkExceptionClassMacro(IGTHardwareException,mitk::IGTException);
};
} // namespace mitk
#endif
diff --git a/Modules/IGTBase/include/mitkIGTIOException.h b/Modules/IGTBase/include/mitkIGTIOException.h
index eef5dc8ebb..d95a5c02af 100644
--- a/Modules/IGTBase/include/mitkIGTIOException.h
+++ b/Modules/IGTBase/include/mitkIGTIOException.h
@@ -1,30 +1,30 @@
/*============================================================================
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 mitkIGTIOException_h
#define mitkIGTIOException_h
#include <mitkIGTException.h>
#include "mitkExceptionMacro.h"
namespace mitk {
/**Documentation
* \brief An object of this class represents an exception of the MITK-IGT module which are releated to the input/output problems (e.g. reading writing files, etc.).
*
* \ingroup IGT
- */ class MITKIGTBASE_EXPORT IGTIOException : public mitk::IGTException
+ */ class MITKIGTBASE_EXPORT IGTIOException /** \cond */ : public mitk::IGTException /** \endcond */
{
public:
mitkExceptionClassMacro(IGTIOException,mitk::IGTException);
};
} // namespace mitk
#endif
diff --git a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp
index 01cb561002..343f7eb519 100644
--- a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp
+++ b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp
@@ -1,891 +1,891 @@
/*============================================================================
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 MITK_NO_DEPRECATED_WARNINGS
#include "QmitkNDIConfigurationWidget.h"
#include <QTableWidget>
#include <QMessageBox>
#include <QFileDialog>
#include <QInputDialog>
#include <QDir>
#include <QFileInfo>
#include <mitkNavigationToolWriter.h>
#include <mitkNavigationToolReader.h>
#include <mitkIGTException.h>
#include <mitkIOUtil.h>
#include <QmitkIGTCommonHelper.h>
#include "QmitkCustomVariants.h"
//#include <QtConcurrentMap>
#include "QmitkNDIToolDelegate.h"
#include "mitkNDIAuroraTypeInformation.h"
#include "mitkNDIPolarisTypeInformation.h"
/* VIEW MANAGEMENT */
QmitkNDIConfigurationWidget::QmitkNDIConfigurationWidget(QWidget* parent)
: QWidget(parent), m_Controls(nullptr), m_Tracker(nullptr), m_Source(nullptr),
m_Delegate(nullptr), m_SROMCellDefaultText("<click to load SROM file>"), m_RepresentatonCellDefaultText("<click to select representation>")
{
this->CreateQtPartControl(this);
}
QmitkNDIConfigurationWidget::~QmitkNDIConfigurationWidget()
{
m_Controls = nullptr;
m_Tracker = nullptr;
m_Source = nullptr;
}
void QmitkNDIConfigurationWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkNDIConfigurationWidget;
m_Controls->setupUi(parent);
QStringList comPorts;
#ifdef WIN32
comPorts << "COM1" << "COM2" << "COM3" << "COM4" << "COM5" << "COM6" << "COM7" << "COM8" << "COM9";
#else
comPorts << "/dev/ttyS1" << "/dev/ttyS2" << "/dev/ttyS3" << "/dev/ttyS4" << "/dev/ttyS5" << "/dev/ttyUSB0" << "/dev/ttyUSB1" << "/dev/ttyUSB2" << "/dev/ttyUSB3";
#endif
m_Controls->m_ComPortSelector->addItems(comPorts);
m_Delegate = new QmitkNDIToolDelegate(m_Controls->m_ToolTable);
m_Delegate->SetDataStorage(nullptr); //needs to be set later using the setter methods
m_Delegate->SetPredicate(nullptr);
m_Delegate->SetTypes(QStringList());
m_Controls->m_ToolTable->setItemDelegate(m_Delegate);
this->CreateConnections();
this->HidePolarisOptionsGroupbox(true);
this->HideAuroraOptionsGroupbox(true);
}
}
void QmitkNDIConfigurationWidget::CreateConnections()
{
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
connect(m_Controls->m_DiscoverToolsBtn, SIGNAL(clicked()), this, SLOT(OnDiscoverTools()));
connect(m_Controls->m_AddToolBtn, SIGNAL(clicked()), this, SLOT(OnAddPassiveTool()));
connect(m_Controls->m_DisoverDevicesBtn, SIGNAL(clicked()), this, SLOT(OnDiscoverDevices()));
connect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &)));
connect(m_Controls->m_DisoverDevicesBtnInfo, SIGNAL(clicked()), this, SLOT(OnDisoverDevicesBtnInfo()));
connect(m_Controls->m_SaveToolPushButton, SIGNAL(clicked()), this, SLOT(OnSaveTool()) );
connect(m_Controls->m_LoadToolPushButton, SIGNAL(clicked()), this, SLOT(OnLoadTool()) );
}
void QmitkNDIConfigurationWidget::OnConnect()
{
if (m_Tracker.IsNotNull())
{
m_Tracker->CloseConnection();
m_Tracker = nullptr;
}
this->CreateTracker();
this->SetupTracker();
bool okay = false;
try
{
okay = m_Tracker->OpenConnection();
}
catch(mitk::IGTException &e)
{
QMessageBox::warning(nullptr, "Error", QString("Connection failed, error message: ") + e.GetDescription());
m_Tracker->CloseConnection();
this->m_Tracker = nullptr;
}
if (okay)
{
// show/hide options according to connected device
if(m_Tracker->GetType() == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName())
{
this->HideAuroraOptionsGroupbox(true);
this->HidePolarisOptionsGroupbox(false);
}
else if (m_Tracker->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName())
{
this->HidePolarisOptionsGroupbox(true);
this->HideAuroraOptionsGroupbox(false);
}
this->UpdateWidgets();
this->UpdateToolTable();
connect(m_Controls->m_ToolTable, SIGNAL(cellChanged(int,int)), this, SLOT(OnTableCellChanged(int,int)));
emit ToolsAdded(this->GetToolNamesList());
emit Connected();
}
else
{
QMessageBox::warning(nullptr, "Error", QString("Connection failed due to an unknown reason!"));
m_Tracker->CloseConnection();
this->m_Tracker = nullptr;
}
}
void QmitkNDIConfigurationWidget::OnDisconnect()
{
if (m_Tracker.IsNull())
return;
m_Tracker->CloseConnection();
m_Tracker = nullptr;
disconnect(m_Controls->m_ToolTable, SIGNAL(cellChanged(int,int)), this, SLOT(OnTableCellChanged(int,int)));
m_Controls->m_ToolSelectionComboBox->clear();
this->UpdateToolTable();
this->UpdateWidgets();
emit ToolsAdded(this->GetToolNamesList());
emit Disconnected();
this->HidePolarisOptionsGroupbox(true);
this->HideAuroraOptionsGroupbox(true);
}
void QmitkNDIConfigurationWidget::UpdateWidgets()
{
m_Controls->m_DeviceStatus->setText(this->GetStatusText());
if (m_Tracker.IsNull()) // not connected to tracker
{
m_Controls->m_Connect->setText("Connect");
m_Controls->m_lConnection->setText("III. Enable connection to device ");
disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect()));
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
m_Controls->m_DiscoverToolsBtn->setDisabled(true);
m_Controls->m_AddToolBtn->setDisabled(true);
return;
}
if (m_Tracker->GetState() == mitk::TrackingDevice::Setup)
{
m_Controls->m_Connect->setText("Connect");
m_Controls->m_lConnection->setText("III. Enable connection to device ");
disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect()));
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
m_Controls->m_DiscoverToolsBtn->setDisabled(true);
m_Controls->m_AddToolBtn->setDisabled(true);
return;
}
if ((m_Tracker->GetState() == mitk::TrackingDevice::Ready) || (m_Tracker->GetState() == mitk::TrackingDevice::Tracking))
{
m_Controls->m_Connect->setText("Disconnect");
m_Controls->m_lConnection->setText("III. Disable connection to device ");
disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect()));
m_Controls->m_DiscoverToolsBtn->setEnabled(true);
m_Controls->m_AddToolBtn->setEnabled(true);
}
}
QString QmitkNDIConfigurationWidget::GetStatusText()
{
if (m_Tracker.IsNull())
return QString("Not connected");
QString devName = QString::fromStdString(m_Tracker->GetType());
if (m_Tracker->GetState() == mitk::TrackingDevice::Ready)
return QString("Connected to %1 on %2. Device is ready.").arg(devName).arg(m_Tracker->GetDeviceName());
if (m_Tracker->GetState() == mitk::TrackingDevice::Tracking)
return QString("%1 is tracking.").arg(devName);
return QString("");
}
void QmitkNDIConfigurationWidget::OnDiscoverTools()
{
if (m_Tracker.IsNull())
{
QMessageBox::warning(nullptr, "Error", QString("Connection failed. No tracking device found."));
return;
}
m_Tracker->DiscoverWiredTools();
this->UpdateToolTable();
emit ToolsAdded(this->GetToolNamesList());
}
void QmitkNDIConfigurationWidget::OnAddPassiveTool()
{
if (m_Tracker.IsNull())
this->CreateTracker();
QStringList filenames = QFileDialog::getOpenFileNames(this, "Select NDI SROM file", QmitkIGTCommonHelper::GetLastFileLoadPath(),"NDI SROM files (*.rom)");
if (filenames.isEmpty())
{
this->m_Tracker = nullptr;
return;
}
QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(filenames.at(0));
foreach(QString fileName, filenames)
{
//QString toolName = QInputDialog::getText(this, "Enter a name for the tool", "Name of the tool: ", QLineEdit::Normal, QFileInfo(filename).baseName(), &ok);
//if (ok == false || toolName.isEmpty())
// return;
m_Tracker->AddTool(QFileInfo(fileName).baseName().toLatin1(), fileName.toLatin1());
m_Tracker->Modified();
}
emit ToolsAdded(this->GetToolNamesList());
this->UpdateToolTable();
}
void QmitkNDIConfigurationWidget::CreateTracker()
{
m_Tracker = mitk::NDITrackingDevice::New();
}
void QmitkNDIConfigurationWidget::SetupTracker()
{
if (m_Tracker.IsNull())
return;
m_Tracker->SetDeviceName(this->GetDeviceName());
m_Tracker->SetBaudRate(mitk::SerialCommunication::BaudRate115200);
}
std::string QmitkNDIConfigurationWidget::GetDeviceName() const
{
if (m_Controls == nullptr)
return nullptr;
QString deviceName = m_Controls->m_ComPortSelector->currentText();
#if WIN32
deviceName.prepend("\\\\.\\"); // always prepend "\\.\ to all COM ports, to be able to connect to ports > 9"
#endif
return deviceName.toStdString();
}
void QmitkNDIConfigurationWidget::SetDeviceName( const char* dev )
{
if (m_Controls == nullptr)
return;
m_Controls->m_ComPortSelector->setCurrentIndex(m_Controls->m_ComPortSelector->findText(dev));
}
void QmitkNDIConfigurationWidget::UpdateToolTable()
{
//disconnect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // stop listening to table changes
disconnect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &)));
disconnect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & )));
m_Controls->m_ToolTable->clearContents();
m_Controls->m_ToolTable->setRowCount(0);
if (m_Tracker.IsNull() || (m_Controls == nullptr))
return;
m_Controls->m_ToolSelectionComboBox->clear();
m_Controls->m_ToolTable->setRowCount(m_Tracker->GetToolCount());
for (unsigned int i = 0; i < m_Tracker->GetToolCount(); ++i)
{
mitk::TrackingTool* t = m_Tracker->GetTool(i);
if (t == nullptr)
{
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::IndexCol, new QTableWidgetItem("INVALID")); // Index
continue;
}
m_Controls->m_ToolSelectionComboBox->addItem(m_Tracker->GetTool(i)->GetToolName());
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::IndexCol, new QTableWidgetItem(QString::number(i))); // Index
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::NameCol, new QTableWidgetItem(t->GetToolName())); // Name
if (dynamic_cast<mitk::NDIPassiveTool*>(t)->GetSROMDataLength() > 0)
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem("SROM file loaded")); // SROM file
else
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem(m_SROMCellDefaultText)); // SROM file
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::TypeCol, new QTableWidgetItem("<click to set type>")); // Type
if (t->IsEnabled())
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Enabled")); // Status
else
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Disabled")); // Status
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::NodeCol, new QTableWidgetItem("<click to select node>")); // Node
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(m_RepresentatonCellDefaultText)); // Representation
/* set read-only/editable flags */
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::IndexCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Index
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Name
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::SROMCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // SROM file
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::TypeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Type
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::StatusCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Status
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Node
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags); // Representation surface file
}
m_Controls->m_ToolTable->resizeColumnsToContents();
//connect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // listen to table changes again
connect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &)));
connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & )));
}
void QmitkNDIConfigurationWidget::OnDiscoverDevices()
{
PortDeviceMap portsAndDevices;
QString status = "Scanning ";
#ifdef WIN32
QString devName;
for (unsigned int i = 1; i < 40; ++i)
{
if (i<10)
devName = QString("COM%1").arg(i);
else
devName = QString("\\\\.\\COM%1").arg(i); // prepend "\\.\ to COM ports >9, to be able to allow connection"
portsAndDevices[devName];
status += QString("COM%1").arg(i) + ", ";
}
#else //linux/posix systems
for(unsigned int i = 1; i < 6; ++i)
{
QString devName = QString("/dev/ttyS%1").arg(i);
portsAndDevices[devName];
status += devName + ", ";
}
for(unsigned int i = 0; i <7; ++i)
{
QString devName = QString("/dev/ttyUSB%1").arg(i);
portsAndDevices[devName];
status += devName + ", ";
}
#endif
status.chop(2); // remove last ", "
status += " for NDI tracking devices...";
m_Controls->m_DeviceStatus->setText(status);
ScanPortsForNDITrackingDevices(portsAndDevices);
m_Controls->m_ComPortSelector->clear();
QString result = "The following tracking devices were found:<BR/>\n";
for (PortDeviceMap::const_iterator it = portsAndDevices.begin(); it != portsAndDevices.end(); ++it)
{
QString tmpComPort = it.key();
if (tmpComPort.startsWith("\\"))
{
tmpComPort.remove(0,4); // remove "\\.\" for nice ui visualisation
}
result += tmpComPort + ": ";
if (mitk::NDIPolarisTypeInformation::GetTrackingDeviceName() == it.value() || mitk::NDIAuroraTypeInformation::GetTrackingDeviceName() == it.value())
{
result += QString::fromStdString(it.value());
result += "<BR/>\n";
m_Controls->m_ComPortSelector->addItem(tmpComPort);
}
else
{
result += "No NDI tracking device found<BR/>\n";
}
}
//QMessageBox::information(nullptr, "Tracking Device Discovery", result);
m_Controls->m_DeviceStatus->setText(result);
}
mitk::TrackingDeviceType QmitkNDIConfigurationWidget::ScanPort(QString port)
{
mitk::NDITrackingDevice::Pointer tracker = mitk::NDITrackingDevice::New();
tracker->SetDeviceName(port.toStdString());
return tracker->TestConnection();
}
void QmitkNDIConfigurationWidget::ScanPortsForNDITrackingDevices( PortDeviceMap& portsAndDevices )
{
// Iterative scanning:
for (PortDeviceMap::iterator it = portsAndDevices.begin(); it != portsAndDevices.end(); ++it)
it.value() = this->ScanPort(it.key());
// \Todo: use parallel scanning
//QtConcurrent::blockingMap( portsAndDevices.begin(), portsAndDevices.end(), ScanPort );
//MITK_INFO << portsAndDevices;
}
QStringList QmitkNDIConfigurationWidget::GetToolNamesList()
{
QStringList toolNames;
if (m_Tracker.IsNull())
return toolNames;
for (unsigned int i = 0; i < m_Tracker->GetToolCount(); ++i)
{
mitk::TrackingTool* t = m_Tracker->GetTool(i);
if (t == nullptr)
continue;
toolNames << t->GetToolName();
}
return toolNames;
}
mitk::NDITrackingDevice* QmitkNDIConfigurationWidget::GetTracker() const
{
return m_Tracker.GetPointer();
}
void QmitkNDIConfigurationWidget::SetToolTypes(const QStringList& types)
{
m_Delegate->SetTypes(types);
}
void QmitkNDIConfigurationWidget::SetDataStorage(mitk::DataStorage* ds)
{
m_Delegate->SetDataStorage(ds);
}
void QmitkNDIConfigurationWidget::SetPredicate(mitk::NodePredicateBase::Pointer p)
{
m_Delegate->SetPredicate(p);
}
void QmitkNDIConfigurationWidget::SetTagPropertyName( const std::string& name )
{
m_Delegate->SetTagPropertyName(name);
}
void QmitkNDIConfigurationWidget::SetTagProperty( mitk::BaseProperty::Pointer prop )
{
m_Delegate->SetTagProperty(prop);
}
void QmitkNDIConfigurationWidget::OnTableItemClicked(const QModelIndex & topLeft )
{
QString filename;
QTableWidgetItem* filenameItem;
switch (topLeft.column())
{
case QmitkNDIToolDelegate::RepCol:
filename = QFileDialog::getOpenFileName(this, "Select Surface File", QmitkIGTCommonHelper::GetLastFileLoadPath(),"STL files (*.stl)");
QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(filename);
filenameItem = new QTableWidgetItem(filename);
m_Controls->m_ToolTable->setItem( topLeft.row(), topLeft.column(), filenameItem );
if(QFileInfo(filename).exists())
{
mitk::Surface::Pointer surface = this->LoadSurfaceFromSTLFile(filename);
if(surface.IsNotNull())
emit RepresentationChanged( topLeft.row(), surface);
}
break;
default:
break;
}
}
void QmitkNDIConfigurationWidget::UpdateTrackerFromToolTable(const QModelIndex & topLeft, const QModelIndex & /*bottomRight*/)
{
//Colums ID doesn't have to be processed.
if (topLeft.column()<1)
return;
if (m_Tracker.IsNull())
return;
if (topLeft.row() >= (int) m_Tracker->GetToolCount())
return;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
//define topleft contains row and column; row 0 is tool 0; column is index =0, Name =1, SROMFileName = 2; Type = 3; Status = 4; Node (?) = 5
//only update the changed item
mitk::NDIPassiveTool* tool = dynamic_cast<mitk::NDIPassiveTool*> (m_Tracker->GetTool(topLeft.row()));
if (tool == nullptr)
return;
switch (topLeft.column())
{
case QmitkNDIToolDelegate::IndexCol: //index
break;
case QmitkNDIToolDelegate::NameCol: //name
tool->SetToolName(model->data(model->index(topLeft.row(), 1)).toString().toLatin1());
emit ToolsChanged();
break;
case QmitkNDIToolDelegate::SROMCol: //SROM File Name
{
QString romfile = model->data(model->index(topLeft.row(), QmitkNDIToolDelegate::SROMCol)).toString();
if (QFileInfo(romfile).exists())
tool->LoadSROMFile(romfile.toLatin1());
m_Tracker->UpdateTool(tool);
break;
}
//TODO: Add Node Status and Type here as well
default:
break;
}
}
const QString QmitkNDIConfigurationWidget::GetToolType( unsigned int index ) const
{
if (m_Controls == nullptr)
return QString("");
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
QModelIndex modelIndex = model->index(index, QmitkNDIToolDelegate::TypeCol);
if (modelIndex.isValid() == false)
return QString("");
return model->data(modelIndex).toString();
}
const QString QmitkNDIConfigurationWidget::GetToolName( unsigned int index ) const
{
if (m_Controls == nullptr)
return QString("");
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
QModelIndex modelIndex = model->index(index, QmitkNDIToolDelegate::NameCol);
if (modelIndex.isValid() == false)
return QString("");
return model->data(modelIndex).toString();
}
QMap<QString, unsigned int> QmitkNDIConfigurationWidget::GetToolAndTypes() const
{
QMap<QString, unsigned int> map;
if (m_Controls == nullptr)
return map;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
for (int i = 0; i < model->rowCount(); ++i)
{
QModelIndex indexIndex = model->index(i, QmitkNDIToolDelegate::IndexCol);
QModelIndex typeIndex = model->index(i, QmitkNDIToolDelegate::TypeCol);
if ((indexIndex.isValid() == false) || (typeIndex.isValid() == false))
continue;
map.insert(model->data(typeIndex).toString(), model->data(indexIndex).toUInt());
}
return map;
}
QList<unsigned int> QmitkNDIConfigurationWidget::GetToolsByToolType( QString toolType ) const
{
QList<unsigned int> list;
if (m_Controls == nullptr)
return list;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
for (int i = 0; i < model->rowCount(); ++i)
{
QModelIndex indexIndex = model->index(i, QmitkNDIToolDelegate::IndexCol);
QModelIndex typeIndex = model->index(i, QmitkNDIToolDelegate::TypeCol);
if ((indexIndex.isValid() == false) || (typeIndex.isValid() == false))
continue;
if (model->data(typeIndex).toString() == toolType)
list.append(model->data(indexIndex).toUInt());
}
return list;
}
mitk::DataNode* QmitkNDIConfigurationWidget::GetNode( unsigned int index ) const
{
if (m_Controls == nullptr)
return nullptr;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
QVariant data = model->data(model->index(index, QmitkNDIToolDelegate::NodeCol), QmitkNDIToolDelegate::OrganNodeRole);
return data.value<mitk::DataNode*>();
}
void QmitkNDIConfigurationWidget::HidePolarisOptionsGroupbox( bool on )
{
m_Controls->m_gbPolarisOptions->setHidden(on);
}
void QmitkNDIConfigurationWidget::HideAuroraOptionsGroupbox( bool on )
{
m_Controls->m_gbAuroraOptions->setHidden(on);
}
void QmitkNDIConfigurationWidget::ShowToolRepresentationColumn()
{
int cols = m_Controls->m_ToolTable->columnCount();
//checking if representation column is inserted at right index
if(cols != QmitkNDIToolDelegate::RepCol)
{
//throw std::exception("Representation Column is not inserted at it's designated index!");
return;
}
m_Controls->m_ToolTable->insertColumn(cols); // insert new column at end of table
m_Controls->m_ToolTable->setHorizontalHeaderItem(QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(QString("Representation"))); // inser column header for new colum
//m_Controls->m_ToolTable->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers);
int rows = m_Controls->m_ToolTable->rowCount();
// make all representation colum items not editable
for(int i=0; i < rows; ++i)
{
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem("<click to select representation>")); // Representation
m_Controls->m_ToolTable->item(i,QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags);
}
//connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & )));
}
void QmitkNDIConfigurationWidget::OnDisoverDevicesBtnInfo()
{
QMessageBox *infoBox = new QMessageBox(this);
infoBox->setText("Click \"Scan Ports\" to get a list of all connected NDI tracking devices. This will clear the selection menu below and add the ports for discovered NDI tracking devices. Use this function, if a port is not listed.");
infoBox->exec();
delete infoBox;
}
void QmitkNDIConfigurationWidget::OnTableCellChanged(int row, int column)
{
if(m_Tracker.IsNull())
return;
QString toolName;
switch (column)
{
case QmitkNDIToolDelegate::NameCol:
toolName = m_Controls->m_ToolTable->item(row,column)->text();
m_Controls->m_ToolSelectionComboBox->setItemText(row, toolName);
emit SignalToolNameChanged(row, toolName);
break;
default:
break;
}
}
void QmitkNDIConfigurationWidget::OnSaveTool()
{
if(m_Tracker.IsNull() || m_Tracker->GetToolCount() <= 0)
return;
int currId = m_Controls->m_ToolSelectionComboBox->currentIndex();
QString filename = QFileDialog::getSaveFileName(nullptr, "Save NDI-Tool", QString(QString(m_Tracker->GetTool(currId)->GetToolName())),"NDI Tracking Tool file(*.ntf)");
mitk::TrackingTool* selectedTool = m_Tracker->GetTool(currId);
if(filename.isEmpty())
return;
mitk::NavigationTool::Pointer navTool = mitk::NavigationTool::New();
mitk::NavigationToolWriter::Pointer toolWriter = mitk::NavigationToolWriter::New();
try {
toolWriter->DoWrite(filename.toStdString(), this->GenerateNavigationTool(selectedTool));
}
catch( ... )
{
QMessageBox::warning(nullptr, "Saving Tool Error", QString("An error occured! Could not save tool!\n\n"));
- MBI_ERROR<<"Could not save tool surface!";
- MBI_ERROR<< toolWriter->GetErrorMessage();
+ MITK_ERROR<<"Could not save tool surface!";
+ MITK_ERROR<< toolWriter->GetErrorMessage();
QFile maybeCorruptFile(filename);
if(maybeCorruptFile.exists())
maybeCorruptFile.remove();
}
emit SignalSavedTool(currId, filename);
}
void QmitkNDIConfigurationWidget::OnLoadTool()
{
if(m_Tracker.IsNull() || m_Tracker->GetToolCount() <= 0)
return;
QString filename = QFileDialog::getOpenFileName(nullptr, "Load NDI-Tools", QmitkIGTCommonHelper::GetLastFileLoadPath(),"NDI Tracking Tool file(*.ntf)");
int currId = m_Controls->m_ToolSelectionComboBox->currentIndex();
if(filename.isEmpty())
return;
QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(filename);
mitk::DataNode::Pointer toolNode;
mitk::NavigationToolReader::Pointer toolReader = mitk::NavigationToolReader::New();
mitk::NavigationTool::Pointer navTool;
try {
navTool = toolReader->DoRead(filename.toStdString());
}
catch( ... )
{
QMessageBox::warning(nullptr, "Loading Tool Error", QString("An error occured! Could not load tool!\n\n"));
- MBI_ERROR<<"Could not load tool surface!";
- MBI_ERROR<< toolReader->GetErrorMessage();
+ MITK_ERROR<<"Could not load tool surface!";
+ MITK_ERROR<< toolReader->GetErrorMessage();
}
int currSelectedToolID = m_Controls->m_ToolSelectionComboBox->currentIndex();
// name
m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::NameCol)->setText(navTool->GetToolName().c_str());
dynamic_cast<mitk::NDIPassiveTool*>(m_Tracker->GetTool(currSelectedToolID))->SetToolName(navTool->GetToolName().c_str()); // also setting name to tool directly
//calibration file (.srom) filename
m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(navTool->GetCalibrationFile().c_str());
//type
if(navTool->GetType() == mitk::NavigationTool::Instrument)
m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Instrument");
else if(navTool->GetType() == mitk::NavigationTool::Fiducial)
m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Fiducial");
else if(navTool->GetType() == mitk::NavigationTool::Skinmarker)
m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Skinmarker");
else
m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Unknown");
//representation
m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(m_RepresentatonCellDefaultText);
emit SignalLoadTool(currId, navTool->GetDataNode());
}
mitk::NavigationTool::Pointer QmitkNDIConfigurationWidget::GenerateNavigationTool(mitk::TrackingTool* tool)
{
mitk::NavigationTool::Pointer navTool = mitk::NavigationTool::New();
mitk::NDIPassiveTool::Pointer passiveTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
if(passiveTool.IsNull())
throw std::runtime_error("Could not cast TrackingTool to PassiveTool");
int currSelectedToolID = m_Controls->m_ToolSelectionComboBox->currentIndex();
QString sromFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::SROMCol)->text();
QString surfaceFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::RepCol)->text();
//calibration file (.srom) filename
QFile sromFile(sromFileName);
if(sromFile.exists())
navTool->SetCalibrationFile(sromFileName.toStdString());
//serial number
navTool->SetSerialNumber(passiveTool->GetSerialNumber());
// name and surface as dataNode
mitk::DataNode::Pointer node = mitk::DataNode::New();
mitk::Surface::Pointer toolSurface;
try{
toolSurface = this->LoadSurfaceFromSTLFile(surfaceFileName);
}
catch( ... )
{
QMessageBox::warning(nullptr, "Loading Surface Error", QString("An error occured! Could not load surface from .stl file!\n\n"));
- MBI_ERROR<<"Could not load .stl tool surface!";
+ MITK_ERROR<<"Could not load .stl tool surface!";
}
if(toolSurface.IsNotNull())
{
node->SetData(toolSurface);
node->SetName(tool->GetToolName());
}
navTool->SetDataNode(node);
// type
mitk::NavigationTool::NavigationToolType type;
QString currentToolType = m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->text();
if(currentToolType.compare("Instrument") == 0)
type = mitk::NavigationTool::Instrument;
else if(currentToolType.compare("Fiducial") == 0)
type = mitk::NavigationTool::Fiducial;
else if(currentToolType.compare("Skinmarker") == 0)
type = mitk::NavigationTool::Skinmarker;
else
type = mitk::NavigationTool::Unknown;
navTool->SetType(type);
return navTool;
}
mitk::Surface::Pointer QmitkNDIConfigurationWidget::LoadSurfaceFromSTLFile(QString surfaceFilename)
{
mitk::Surface::Pointer toolSurface;
QFile surfaceFile(surfaceFilename);
if(surfaceFile.exists())
{
try{
toolSurface = mitk::IOUtil::Load<mitk::Surface>(surfaceFilename.toStdString().c_str());
}
catch(std::exception& e )
{
- MBI_ERROR<<"Could not load surface for tool!";
- MBI_ERROR<< e.what();
+ MITK_ERROR<<"Could not load surface for tool!";
+ MITK_ERROR<< e.what();
throw e;
}
}
return toolSurface;
}
void QmitkNDIConfigurationWidget::EnableAddToolsButton(bool enable) {
m_Controls->m_AddToolBtn->setEnabled(enable);
}
void QmitkNDIConfigurationWidget::EnableDiscoverNewToolsButton(bool enable) {
m_Controls->m_DiscoverToolsBtn->setEnabled(enable);
}
diff --git a/Modules/ImageStatistics/CMakeLists.txt b/Modules/ImageStatistics/CMakeLists.txt
index 1cf692bc6f..6d4ee2dcf7 100644
--- a/Modules/ImageStatistics/CMakeLists.txt
+++ b/Modules/ImageStatistics/CMakeLists.txt
@@ -1,8 +1,8 @@
mitk_create_module(
DEPENDS MitkImageExtraction MitkPlanarFigure MitkMultilabel
- PACKAGE_DEPENDS PRIVATE ITK|VTK VTK|IOImage
+ PACKAGE_DEPENDS PRIVATE ITK|Convolution+FFT+VTK VTK|IOImage
)
if(BUILD_TESTING)
add_subdirectory(Testing)
endif()
diff --git a/Modules/ImageStatistics/Testing/mitkImageStatisticsHotspotTest.cpp b/Modules/ImageStatistics/Testing/mitkImageStatisticsHotspotTest.cpp
index fff3c3eee2..0e9198f5ce 100644
--- a/Modules/ImageStatistics/Testing/mitkImageStatisticsHotspotTest.cpp
+++ b/Modules/ImageStatistics/Testing/mitkImageStatisticsHotspotTest.cpp
@@ -1,650 +1,643 @@
/*============================================================================
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 "mitkImageStatisticsCalculator.h"
#include "itkMultiGaussianImageSource.h"
#include "mitkTestingMacros.h"
-#include "mitkImageCast.h"
+#include <mitkITKImageImport.h>
#include <itkImageRegionIterator.h>
#include <stdexcept>
#include <itkDOMNode.h>
#include <itkDOMReader.h>
#include <mitkHotspotMaskGenerator.h>
#include <mitkImageMaskGenerator.h>
#include <mitkIOUtil.h>
/**
\section hotspotCalculationTestCases Testcases
To see the different Hotspot-Testcases have a look at the \ref hotspottestdoc.
Note from an intensive session of checking the test results:
- itk::MultiGaussianImageSource needs a review
- the test idea is ok, but the combination of XML files for parameters and MultiGaussianImageSource has serious flaws
- the XML file should contain exactly the parameters that MultiGaussianImageSource requires
- in contrast, now the XML file mentions index coordinates for gaussian centers while the MultiGaussianImageSource expects world coordinates
- this requires a transformation (index * spacing assuming no rotation) that was actually broken until recently
*/
struct mitkImageStatisticsHotspotTestClass
{
/**
\brief Test parameters for one test case.
Describes all aspects of a single test case:
- parameters to generate a test image
- parameters of a ROI that describes where to calculate statistics
- expected statistics results
*/
struct Parameters
{
public:
// XML-Tag <testimage>
/** \brief XML-Tag "image-rows": size of x-dimension */
int m_ImageRows;
/** \brief XML-Tag "image-columns": size of y-dimension */
int m_ImageColumns;
/** \brief XML-Tag "image-slices": size of z-dimension */
int m_ImageSlices;
/** \brief XML-Tag "numberOfGaussians": number of used gauss-functions */
int m_NumberOfGaussian;
/** \brief XML-Tags "spacingX", "spacingY", "spacingZ": spacing of image in every direction */
double m_Spacing[3];
/** \brief XML-Tag "entireHotSpotInImage" */
unsigned int m_EntireHotspotInImage;
// XML-Tag <gaussian>
/**
\brief XML-Tag "centerIndexX: gaussian parameter
\warning This parameter READS the centerIndexX parameter from file and is THEN MISUSED to calculate some position in world coordinates, so we require double.
*/
std::vector<double> m_CenterX;
/** \brief XML-Tag "centerIndexY: gaussian parameter
\warning This parameter READS the centerIndexX parameter from file and is THEN MISUSED to calculate some position in world coordinates, so we require double.
*/
std::vector<double> m_CenterY;
/** \brief XML-Tag "centerIndexZ: gaussian parameter
\warning This parameter READS the centerIndexX parameter from file and is THEN MISUSED to calculate some position in world coordinates, so we require double.
*/
std::vector<double> m_CenterZ;
/** \brief XML-Tag "deviationX: gaussian parameter */
std::vector<double> m_SigmaX;
/** \brief XML-Tag "deviationY: gaussian parameter */
std::vector<double> m_SigmaY;
/** \brief XML-Tag "deviationZ: gaussian parameter */
std::vector<double> m_SigmaZ;
/** \brief XML-Tag "altitude: gaussian parameter */
std::vector<double> m_Altitude;
// XML-Tag <segmentation>
/** \brief XML-Tag "numberOfLabels": number of different labels which appear in the mask */
unsigned int m_NumberOfLabels;
/** \brief XML-Tag "hotspotRadiusInMM": radius of hotspot */
double m_HotspotRadiusInMM;
// XML-Tag <roi>
/** \brief XML-Tag "maximumSizeX": maximum position of ROI in x-dimension */
vnl_vector<int> m_MaxIndexX;
/** \brief XML-Tag "minimumSizeX": minimum position of ROI in x-dimension */
vnl_vector<int> m_MinIndexX;
/** \brief XML-Tag "maximumSizeX": maximum position of ROI in y-dimension */
vnl_vector<int> m_MaxIndexY;
/** \brief XML-Tag "minimumSizeX": minimum position of ROI in y-dimension */
vnl_vector<int> m_MinIndexY;
/** \brief XML-Tag "maximumSizeX": maximum position of ROI in z-dimension */
vnl_vector<int> m_MaxIndexZ;
/** \brief XML-Tag "minimumSizeX": minimum position of ROI in z-dimension */
vnl_vector<int> m_MinIndexZ;
/** \brief XML-Tag "label": value of label */
vnl_vector<unsigned int> m_Label;
//XML-Tag <statistic>
/** \brief XML-Tag "minimum": minimum inside hotspot */
vnl_vector<double> m_HotspotMin;
/** \brief XML-Tag "maximum": maximum inside hotspot */
vnl_vector<double> m_HotspotMax;
/** \brief XML-Tag "mean": mean value of hotspot */
vnl_vector<double> m_HotspotMean;
/** \brief XML-Tag "maximumIndexX": x-coordinate of maximum-location inside hotspot */
vnl_vector<int> m_HotspotMaxIndexX;
/** \brief XML-Tag "maximumIndexX": y-coordinate of maximum-location inside hotspot */
vnl_vector<int> m_HotspotMaxIndexY;
/** \brief XML-Tag "maximumIndexX": z-coordinate of maximum-location inside hotspot */
vnl_vector<int> m_HotspotMaxIndexZ;
/** \brief XML-Tag "maximumIndexX": x-coordinate of maximum-location inside hotspot */
vnl_vector<int> m_HotspotMinIndexX;
/** \brief XML-Tag "maximumIndexX": y-coordinate of maximum-location inside hotspot */
vnl_vector<int> m_HotspotMinIndexY;
/** \brief XML-Tag "maximumIndexX": z-coordinate of maximum-location inside hotspot */
vnl_vector<int> m_HotspotMinIndexZ;
/** \brief XML-Tag "maximumIndexX": x-coordinate of hotspot-location */
vnl_vector<int> m_HotspotIndexX;
/** \brief XML-Tag "maximumIndexX": y-coordinate of hotspot-location */
vnl_vector<int> m_HotspotIndexY;
/** \brief XML-Tag "maximumIndexX": z-coordinate of hotspot-location */
vnl_vector<int> m_HotspotIndexZ;
};
/**
\brief Find/Convert integer attribute in itk::DOMNode.
*/
static int GetIntegerAttribute(itk::DOMNode* domNode, const std::string& tag)
{
assert(domNode);
MITK_TEST_CONDITION_REQUIRED( domNode->HasAttribute(tag), "Tag '" << tag << "' is defined in test parameters" );
std::string attributeValue = domNode->GetAttribute(tag);
int resultValue;
try
{
//MITK_TEST_OUTPUT( << "Converting tag value '" << attributeValue << "' for tag '" << tag << "' to integer");
std::stringstream(attributeValue) >> resultValue;
return resultValue;
}
catch(std::exception& /*e*/)
{
MITK_TEST_CONDITION_REQUIRED(false, "Convert tag value '" << attributeValue << "' for tag '" << tag << "' to integer");
return 0; // just to satisfy compiler
}
}
/**
\brief Find/Convert double attribute in itk::DOMNode.
*/
static double GetDoubleAttribute(itk::DOMNode* domNode, const std::string& tag)
{
assert(domNode);
MITK_TEST_CONDITION_REQUIRED( domNode->HasAttribute(tag), "Tag '" << tag << "' is defined in test parameters" );
std::string attributeValue = domNode->GetAttribute(tag);
double resultValue;
try
{
//MITK_TEST_OUTPUT( << "Converting tag value '" << attributeValue << "' for tag '" << tag << "' to double");
std::stringstream(attributeValue) >> resultValue;
return resultValue;
}
catch(std::exception& /*e*/)
{
MITK_TEST_CONDITION_REQUIRED(false, "Convert tag value '" << attributeValue << "' for tag '" << tag << "' to double");
return 0.0; // just to satisfy compiler
}
}
/**
\brief Read XML file describing the test parameters.
Reads XML file given in first commandline parameter in order
to construct a Parameters structure. The XML file should be
structurs as the following example, i.e. we describe the
three test aspects of Parameters in four different tags,
with all the details described as tag attributes. */
/**
\verbatim
<testcase>
<!--
Test case: multi-label mask
-->
<testimage image-rows="50" image-columns="50" image-slices="20" numberOfGaussians="2" spacingX="1" spacingY="1" spacingZ="1" entireHotSpotInImage="1">
<gaussian centerIndexX="10" centerIndexY="10" centerIndexZ="10" deviationX="5" deviationY="5" deviationZ="5" altitude="200"/>
<gaussian centerIndexX="40" centerIndexY="40" centerIndexZ="10" deviationX="2" deviationY="4" deviationZ="6" altitude="180"/>
</testimage>
<segmentation numberOfLabels="2" hotspotRadiusInMM="6.2035">
<roi label="1" maximumSizeX="20" minimumSizeX="0" maximumSizeY="20" minimumSizeY="0" maximumSizeZ="20" minimumSizeZ="0"/>
<roi label="2" maximumSizeX="50" minimumSizeX="30" maximumSizeY="50" minimumSizeY="30" maximumSizeZ="20" minimumSizeZ="0"/>
</segmentation>
<statistic hotspotIndexX="10" hotspotIndexY="10" hotspotIndexZ="10" mean="122.053" maximumIndexX="10" maximumIndexY="10" maximumIndexZ="10" maximum="200" minimumIndexX="9" minimumIndexY="9" minimumIndexZ="4" minimum="93.5333"/>
<statistic hotspotIndexX="40" hotspotIndexY="40" hotspotIndexZ="10" mean="61.1749" maximumIndexX="40" maximumIndexY="40" maximumIndexZ="10" maximum="180" minimumIndexX="46" minimumIndexY="39" minimumIndexZ="9" minimum="1.91137"/>
</testcase>
\endverbatim
*/
static Parameters ParseParameters(int argc, char* argv[])
{
MITK_TEST_CONDITION_REQUIRED(argc == 2, "Test is invoked with exactly 1 parameter (XML parameters file)");
MITK_INFO << "Reading parameters from file '" << argv[1] << "'";
std::string filename = argv[1];
Parameters result;
itk::DOMNodeXMLReader::Pointer xmlReader = itk::DOMNodeXMLReader::New();
xmlReader->SetFileName( filename );
try
{
xmlReader->Update();
itk::DOMNode::Pointer domRoot = xmlReader->GetOutput();
typedef std::vector<itk::DOMNode*> NodeList;
NodeList testimages;
domRoot->GetChildren("testimage", testimages);
MITK_TEST_CONDITION_REQUIRED( testimages.size() == 1, "One test image defined" )
itk::DOMNode* testimage = testimages[0];
result.m_ImageRows = GetIntegerAttribute( testimage, "image-rows" );
result.m_ImageColumns = GetIntegerAttribute( testimage, "image-columns" );
result.m_ImageSlices = GetIntegerAttribute( testimage, "image-slices" );
result.m_NumberOfGaussian = GetIntegerAttribute( testimage, "numberOfGaussians" );
result.m_Spacing[0] = GetDoubleAttribute(testimage, "spacingX");
result.m_Spacing[1] = GetDoubleAttribute(testimage, "spacingY");
result.m_Spacing[2] = GetDoubleAttribute(testimage, "spacingZ");
result.m_EntireHotspotInImage = GetIntegerAttribute( testimage, "entireHotSpotInImage" );
MITK_TEST_OUTPUT( << "Read size parameters (x,y,z): " << result.m_ImageRows << "," << result.m_ImageColumns << "," << result.m_ImageSlices);
MITK_TEST_OUTPUT( << "Read spacing parameters (x,y,z): " << result.m_Spacing[0] << "," << result.m_Spacing[1] << "," << result.m_Spacing[2]);
NodeList gaussians;
testimage->GetChildren("gaussian", gaussians);
MITK_TEST_CONDITION_REQUIRED( gaussians.size() >= 1, "At least one gaussian is defined" )
result.m_CenterX.resize(result.m_NumberOfGaussian);
result.m_CenterY.resize(result.m_NumberOfGaussian);
result.m_CenterZ.resize(result.m_NumberOfGaussian);
result.m_SigmaX.resize(result.m_NumberOfGaussian);
result.m_SigmaY.resize(result.m_NumberOfGaussian);
result.m_SigmaZ.resize(result.m_NumberOfGaussian);
result.m_Altitude.resize(result.m_NumberOfGaussian);
for(int i = 0; i < result.m_NumberOfGaussian ; ++i)
{
itk::DOMNode* gaussian = gaussians[i];
result.m_CenterX[i] = GetIntegerAttribute(gaussian, "centerIndexX");
result.m_CenterY[i] = GetIntegerAttribute(gaussian, "centerIndexY");
result.m_CenterZ[i] = GetIntegerAttribute(gaussian, "centerIndexZ");
result.m_SigmaX[i] = GetDoubleAttribute(gaussian, "deviationX");
result.m_SigmaY[i] = GetDoubleAttribute(gaussian, "deviationY");
result.m_SigmaZ[i] = GetDoubleAttribute(gaussian, "deviationZ");
result.m_Altitude[i] = GetDoubleAttribute(gaussian, "altitude");
result.m_CenterX[i] = result.m_CenterX[i] * result.m_Spacing[0];
result.m_CenterY[i] = result.m_CenterY[i] * result.m_Spacing[1];
result.m_CenterZ[i] = result.m_CenterZ[i] * result.m_Spacing[2];
result.m_SigmaX[i] = result.m_SigmaX[i] * result.m_Spacing[0];
result.m_SigmaY[i] = result.m_SigmaY[i] * result.m_Spacing[1];
result.m_SigmaZ[i] = result.m_SigmaZ[i] * result.m_Spacing[2];
}
NodeList segmentations;
domRoot->GetChildren("segmentation", segmentations);
MITK_TEST_CONDITION_REQUIRED( segmentations.size() == 1, "One segmentation defined");
itk::DOMNode* segmentation = segmentations[0];
result.m_NumberOfLabels = GetIntegerAttribute(segmentation, "numberOfLabels");
result.m_HotspotRadiusInMM = GetDoubleAttribute(segmentation, "hotspotRadiusInMM");
// read ROI parameters, fill result structure
NodeList rois;
segmentation->GetChildren("roi", rois);
MITK_TEST_CONDITION_REQUIRED( rois.size() >= 1, "At least one ROI defined" )
result.m_MaxIndexX.set_size(result.m_NumberOfLabels);
result.m_MinIndexX.set_size(result.m_NumberOfLabels);
result.m_MaxIndexY.set_size(result.m_NumberOfLabels);
result.m_MinIndexY.set_size(result.m_NumberOfLabels);
result.m_MaxIndexZ.set_size(result.m_NumberOfLabels);
result.m_MinIndexZ.set_size(result.m_NumberOfLabels);
result.m_Label.set_size(result.m_NumberOfLabels);
for(unsigned int i = 0; i < rois.size(); ++i)
{
result.m_MaxIndexX[i] = GetIntegerAttribute(rois[i], "maximumIndexX");
result.m_MinIndexX[i] = GetIntegerAttribute(rois[i], "minimumIndexX");
result.m_MaxIndexY[i] = GetIntegerAttribute(rois[i], "maximumIndexY");
result.m_MinIndexY[i] = GetIntegerAttribute(rois[i], "minimumIndexY");
result.m_MaxIndexZ[i] = GetIntegerAttribute(rois[i], "maximumIndexZ");
result.m_MinIndexZ[i] = GetIntegerAttribute(rois[i], "minimumIndexZ");
result.m_Label[i] = GetIntegerAttribute(rois[i], "label");
}
// read statistic parameters, fill result structure
NodeList statistics;
domRoot->GetChildren("statistic", statistics);
MITK_TEST_CONDITION_REQUIRED( statistics.size() >= 1 , "At least one statistic defined" )
MITK_TEST_CONDITION_REQUIRED( statistics.size() == rois.size(), "Same number of rois and corresponding statistics defined");
result.m_HotspotMin.set_size(statistics.size());
result.m_HotspotMax.set_size(statistics.size());
result.m_HotspotMean.set_size(statistics.size());
result.m_HotspotMinIndexX.set_size(statistics.size());
result.m_HotspotMinIndexY.set_size(statistics.size());
result.m_HotspotMinIndexZ.set_size(statistics.size());
result.m_HotspotMaxIndexX.set_size(statistics.size());
result.m_HotspotMaxIndexY.set_size(statistics.size());
result.m_HotspotMaxIndexZ.set_size(statistics.size());
result.m_HotspotIndexX.set_size(statistics.size());
result.m_HotspotIndexY.set_size(statistics.size());
result.m_HotspotIndexZ.set_size(statistics.size());
for(unsigned int i = 0; i < statistics.size(); ++i)
{
result.m_HotspotMin[i] = GetDoubleAttribute(statistics[i], "minimum");
result.m_HotspotMax[i] = GetDoubleAttribute(statistics[i], "maximum");
result.m_HotspotMean[i] = GetDoubleAttribute(statistics[i], "mean");
result.m_HotspotMinIndexX[i] = GetIntegerAttribute(statistics[i], "minimumIndexX");
result.m_HotspotMinIndexY[i] = GetIntegerAttribute(statistics[i], "minimumIndexY");
result.m_HotspotMinIndexZ[i] = GetIntegerAttribute(statistics[i], "minimumIndexZ");
result.m_HotspotMaxIndexX[i] = GetIntegerAttribute(statistics[i], "maximumIndexX");
result.m_HotspotMaxIndexY[i] = GetIntegerAttribute(statistics[i], "maximumIndexY");
result.m_HotspotMaxIndexZ[i] = GetIntegerAttribute(statistics[i], "maximumIndexZ");
result.m_HotspotIndexX[i] = GetIntegerAttribute(statistics[i], "hotspotIndexX");
result.m_HotspotIndexY[i] = GetIntegerAttribute(statistics[i], "hotspotIndexY");
result.m_HotspotIndexZ[i] = GetIntegerAttribute(statistics[i], "hotspotIndexZ");
}
}
catch (std::exception& e)
{
MITK_TEST_CONDITION_REQUIRED(false, "Reading test parameters from XML file. Error message: " << e.what());
}
return result;
}
/**
\brief Generate an image that contains a couple of 3D gaussian distributions.
Uses the given parameters to produce a test image using class MultiGaussianImageSource.
*/
static mitk::Image::Pointer BuildTestImage(const Parameters& testParameters)
{
- mitk::Image::Pointer result;
-
typedef double PixelType;
const int Dimension = 3;
typedef itk::Image<PixelType, Dimension> ImageType;
- ImageType::Pointer image = ImageType::New();
typedef itk::MultiGaussianImageSource< ImageType > MultiGaussianImageSource;
MultiGaussianImageSource::Pointer gaussianGenerator = MultiGaussianImageSource::New();
ImageType::SizeValueType size[3];
size[0] = testParameters.m_ImageColumns;
size[1] = testParameters.m_ImageRows;
size[2] = testParameters.m_ImageSlices;
itk::MultiGaussianImageSource<ImageType>::VectorType centerXVec, centerYVec, centerZVec, sigmaXVec, sigmaYVec, sigmaZVec, altitudeVec;
for(int i = 0; i < testParameters.m_NumberOfGaussian; ++i)
{
centerXVec.push_back(testParameters.m_CenterX[i]);
centerYVec.push_back(testParameters.m_CenterY[i]);
centerZVec.push_back(testParameters.m_CenterZ[i]);
sigmaXVec.push_back(testParameters.m_SigmaX[i]);
sigmaYVec.push_back(testParameters.m_SigmaY[i]);
sigmaZVec.push_back(testParameters.m_SigmaZ[i]);
altitudeVec.push_back(testParameters.m_Altitude[i]);
}
ImageType::SpacingType spacing;
for( int i = 0; i < Dimension; ++i )
spacing[i] = testParameters.m_Spacing[i];
gaussianGenerator->SetSize( size );
gaussianGenerator->SetSpacing( spacing );
gaussianGenerator->SetRadius(testParameters.m_HotspotRadiusInMM);
gaussianGenerator->SetNumberOfGausssians(testParameters.m_NumberOfGaussian);
gaussianGenerator->AddGaussian(centerXVec, centerYVec, centerZVec,
sigmaXVec, sigmaYVec, sigmaZVec, altitudeVec);
gaussianGenerator->Update();
- image = gaussianGenerator->GetOutput();
-
- mitk::CastToMitkImage(image, result);
-
- return result;
+ return mitk::GrabItkImageMemory(gaussianGenerator->GetOutput(), nullptr, nullptr, false);
}
/**
\brief Calculates hotspot statistics for given test image and ROI parameters.
Uses ImageStatisticsCalculator to find a hotspot in a defined ROI within the given image.
*/
static mitk::ImageStatisticsContainer::ImageStatisticsObject CalculateStatistics(mitk::Image* image, const Parameters& testParameters, unsigned int label)
{
const unsigned int Dimension = 3;
typedef itk::Image<unsigned short, Dimension> MaskImageType;
MaskImageType::Pointer mask = MaskImageType::New();
MaskImageType::SizeType size;
MaskImageType::SpacingType spacing;
MaskImageType::IndexType start;
mitk::ImageStatisticsCalculator::Pointer statisticsCalculator = mitk::ImageStatisticsCalculator::New();
statisticsCalculator->SetInputImage(image);
- mitk::Image::Pointer mitkMaskImage;
if((testParameters.m_MaxIndexX[label] > testParameters.m_MinIndexX[label] && testParameters.m_MinIndexX[label] >= 0) &&
(testParameters.m_MaxIndexY[label] > testParameters.m_MinIndexY[label] && testParameters.m_MinIndexY[label] >= 0) &&
(testParameters.m_MaxIndexZ[label] > testParameters.m_MinIndexZ[label] && testParameters.m_MinIndexZ[label] >= 0))
{
for(unsigned int i = 0; i < Dimension; ++i)
{
start[i] = 0;
spacing[i] = testParameters.m_Spacing[i];
}
size[0] = testParameters.m_ImageColumns;
size[1] = testParameters.m_ImageRows;
size[2] = testParameters.m_ImageSlices;
MaskImageType::RegionType region;
region.SetIndex(start);
region.SetSize(size);
mask->SetSpacing(spacing);
mask->SetRegions(region);
mask->Allocate();
typedef itk::ImageRegionIteratorWithIndex<MaskImageType> MaskImageIteratorType;
MaskImageIteratorType maskIt(mask, region);
for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
{
maskIt.Set(0);
}
for(unsigned int i = 0; i < testParameters.m_NumberOfLabels; ++i)
{
for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
{
MaskImageType::IndexType index = maskIt.GetIndex();
if((index[0] >= testParameters.m_MinIndexX[i] && index[0] <= testParameters.m_MaxIndexX[i] ) &&
(index[1] >= testParameters.m_MinIndexY[i] && index[1] <= testParameters.m_MaxIndexY[i] ) &&
(index[2] >= testParameters.m_MinIndexZ[i] && index[2] <= testParameters.m_MaxIndexZ[i] ))
{
maskIt.Set(testParameters.m_Label[i]);
}
}
}
- mitk::CastToMitkImage(mask, mitkMaskImage);
+ auto mitkMaskImage = mitk::GrabItkImageMemory(mask, nullptr, nullptr, false);
+
mitk::ImageMaskGenerator::Pointer imgMaskGen = mitk::ImageMaskGenerator::New();
imgMaskGen->SetInputImage(image);
imgMaskGen->SetImageMask(mitkMaskImage);
mitk::HotspotMaskGenerator::Pointer hotspotMaskGen = mitk::HotspotMaskGenerator::New();
hotspotMaskGen->SetInputImage(image);
hotspotMaskGen->SetLabel(testParameters.m_Label[label]);
hotspotMaskGen->SetMask(imgMaskGen.GetPointer());
hotspotMaskGen->SetHotspotRadiusInMM(testParameters.m_HotspotRadiusInMM);
if(testParameters.m_EntireHotspotInImage == 1)
{
MITK_INFO << "Hotspot must be completly inside image";
hotspotMaskGen->SetHotspotMustBeCompletelyInsideImage(true);
}
else
{
MITK_INFO << "Hotspot must not be completly inside image";
hotspotMaskGen->SetHotspotMustBeCompletelyInsideImage(false);
}
statisticsCalculator->SetMask(hotspotMaskGen.GetPointer());
MITK_DEBUG << "Masking is set to hotspot+image mask";
}
else
{
mitk::HotspotMaskGenerator::Pointer hotspotMaskGen = mitk::HotspotMaskGenerator::New();
hotspotMaskGen->SetInputImage(image);
hotspotMaskGen->SetHotspotRadiusInMM(testParameters.m_HotspotRadiusInMM);
if(testParameters.m_EntireHotspotInImage == 1)
{
MITK_INFO << "Hotspot must be completly inside image";
hotspotMaskGen->SetHotspotMustBeCompletelyInsideImage(true);
}
else
{
MITK_INFO << "Hotspot must not be completly inside image";
hotspotMaskGen->SetHotspotMustBeCompletelyInsideImage(false);
}
MITK_DEBUG << "Masking is set to hotspot only";
}
return statisticsCalculator->GetStatistics()->GetStatisticsForTimeStep(0);
}
static void ValidateStatisticsItem(const std::string& label, double testvalue, double reference, double tolerance)
{
double diff = ::fabs(reference - testvalue);
MITK_TEST_CONDITION( diff < tolerance, "'" << label << "' value close enough to reference value "
"(value=" << testvalue <<
", reference=" << reference <<
", diff=" << diff << ")" );
}
static void ValidateStatisticsItem(const std::string& label, const vnl_vector<int>& testvalue, const vnl_vector<int>& reference)
{
double diffX = ::fabs(double(testvalue[0] - reference[0]));
double diffY = ::fabs(double(testvalue[1] - reference[1]));
double diffZ = ::fabs(double(testvalue[2] - reference[2]));
std::stringstream testPosition;
testPosition << testvalue[0] << "," << testvalue[1] << "," << testvalue[2];
std::stringstream referencePosition;
referencePosition << reference[0] << "," << reference[1] << "," << reference[2];
MITK_TEST_CONDITION( diffX < mitk::eps && diffY < mitk::eps && diffZ < mitk::eps,
"'" << label << "' close enough to reference value " <<
"(value=[" << testPosition.str() << "]," <<
" reference=[" << referencePosition.str() << "]");
}
/**
\brief Compares calculated against actual statistics values.
Checks validness of all statistics aspects. Lets test fail if any aspect is not sufficiently equal.
*/
static void ValidateStatistics(const mitk::ImageStatisticsContainer::ImageStatisticsObject hotspotStatistics, const Parameters& testParameters, unsigned int label)
{
// check all expected test result against actual results
double eps = 0.25; // value above the largest tested difference
auto mean = hotspotStatistics.GetValueConverted<mitk::ImageStatisticsContainer::RealType>(mitk::ImageStatisticsConstants::MEAN());
auto max = hotspotStatistics.GetValueConverted<mitk::ImageStatisticsContainer::RealType>(mitk::ImageStatisticsConstants::MAXIMUM());
auto min = hotspotStatistics.GetValueConverted<mitk::ImageStatisticsContainer::RealType>(mitk::ImageStatisticsConstants::MINIMUM());
ValidateStatisticsItem("Hotspot mean", mean, testParameters.m_HotspotMean[label], eps);
ValidateStatisticsItem("Hotspot maximum", max, testParameters.m_HotspotMax[label], eps);
ValidateStatisticsItem("Hotspot minimum", min, testParameters.m_HotspotMin[label], eps);
vnl_vector<int> referenceHotspotCenterIndex; referenceHotspotCenterIndex.set_size(3);
referenceHotspotCenterIndex[0] = testParameters.m_HotspotIndexX[label];
referenceHotspotCenterIndex[1] = testParameters.m_HotspotIndexY[label];
referenceHotspotCenterIndex[2] = testParameters.m_HotspotIndexZ[label];
// ValidateStatisticsItem("Hotspot center position", statistics.GetHotspotStatistics().GetHotspotIndex(), referenceHotspotCenterIndex); TODO: new image statistics calculator does not give hotspot position
// TODO we do not test minimum/maximum positions within the peak/hotspot region, because
// these positions are not unique, i.e. there are multiple valid minima/maxima positions.
// One solution would be to modify the test cases in order to achive clear positions.
// The BETTER/CORRECT solution would be to change the singular position into a set of positions / a region
}
};
/**
\brief Verifies that hotspot statistics part of ImageStatisticsCalculator.
The test reads parameters from an XML-file to generate a test-image, calculates the hotspot statistics of the image
and checks if the calculated statistics are the same as the specified values of the XML-file.
*/
int mitkImageStatisticsHotspotTest(int argc, char* argv[])
{
MITK_TEST_BEGIN("mitkImageStatisticsHotspotTest")
try {
mitkImageStatisticsHotspotTestClass::Parameters parameters = mitkImageStatisticsHotspotTestClass::ParseParameters(argc,argv);
mitk::Image::Pointer image = mitkImageStatisticsHotspotTestClass::BuildTestImage(parameters);
MITK_TEST_CONDITION_REQUIRED( image.IsNotNull(), "Generate test image" );
for(unsigned int label = 0; label < parameters.m_NumberOfLabels; ++label)
{
mitk::ImageStatisticsContainer::ImageStatisticsObject statistics = mitkImageStatisticsHotspotTestClass::CalculateStatistics(image, parameters, label);
mitkImageStatisticsHotspotTestClass::ValidateStatistics(statistics, parameters, label);
std::cout << std::endl;
}
}
catch (std::exception& e)
{
std::cout << "Error: " << e.what() << std::endl;
MITK_TEST_CONDITION_REQUIRED( false, "Exception occurred during test execution: " << e.what() );
}
catch(...)
{
MITK_TEST_CONDITION_REQUIRED( false, "Exception occurred during test execution." );
}
MITK_TEST_END()
}
diff --git a/Modules/ImageStatistics/mitkHotspotMaskGenerator.cpp b/Modules/ImageStatistics/mitkHotspotMaskGenerator.cpp
index 35d4a30a8e..e36b93dce5 100644
--- a/Modules/ImageStatistics/mitkHotspotMaskGenerator.cpp
+++ b/Modules/ImageStatistics/mitkHotspotMaskGenerator.cpp
@@ -1,618 +1,621 @@
/*============================================================================
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 <mitkHotspotMaskGenerator.h>
#include <mitkImageTimeSelector.h>
#include <mitkImageCast.h>
#include <mitkPoint.h>
#include <itkImageRegionIterator.h>
#include "mitkImageAccessByItk.h"
#include <itkImageDuplicator.h>
#include <itkFFTConvolutionImageFilter.h>
+#include <itkVnlFFTImageFilterInitFactory.h>
#include <mitkITKImageImport.h>
namespace mitk
{
HotspotMaskGenerator::HotspotMaskGenerator():
m_HotspotRadiusinMM(6.2035049089940), // radius of a 1cm3 sphere in mm
m_HotspotMustBeCompletelyInsideImage(true),
m_Label(1)
{
m_TimeStep = 0;
m_InternalMask = mitk::Image::New();
m_InternalMaskUpdateTime = 0;
}
void HotspotMaskGenerator::SetInputImage(mitk::Image::Pointer inputImage)
{
if (inputImage != m_inputImage)
{
m_inputImage = inputImage;
m_ConvolutionImageMaxIndex.set_size(inputImage->GetDimension());
m_ConvolutionImageMinIndex.set_size(inputImage->GetDimension());
this->Modified();
}
}
void HotspotMaskGenerator::SetMask(MaskGenerator::Pointer mask)
{
if (mask != m_Mask)
{
m_Mask = mask;
this->Modified();
}
}
HotspotMaskGenerator::~HotspotMaskGenerator()
{
}
void HotspotMaskGenerator::SetHotspotRadiusInMM(double radiusInMillimeter)
{
if(radiusInMillimeter != m_HotspotRadiusinMM)
{
m_HotspotRadiusinMM = radiusInMillimeter;
this->Modified();
}
}
const double& HotspotMaskGenerator::GetHotspotRadiusinMM() const
{
return m_HotspotRadiusinMM;
}
bool HotspotMaskGenerator::GetHotspotMustBeCompletelyInsideImage() const
{
return m_HotspotMustBeCompletelyInsideImage;
}
void HotspotMaskGenerator::SetHotspotMustBeCompletelyInsideImage(bool mustBeCompletelyInImage)
{
if (m_HotspotMustBeCompletelyInsideImage != mustBeCompletelyInImage)
{
m_HotspotMustBeCompletelyInsideImage = mustBeCompletelyInImage;
this->Modified();
}
}
mitk::Image::ConstPointer HotspotMaskGenerator::GetMask()
{
if (IsUpdateRequired())
{
if ( m_inputImage.IsNull() )
{
throw std::runtime_error( "Error: image empty!" );
}
if ( m_TimeStep >= m_inputImage->GetTimeSteps() )
{
throw std::runtime_error( "Error: invalid time step!" );
}
mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New();
imageTimeSelector->SetInput( m_inputImage );
imageTimeSelector->SetTimeNr( m_TimeStep );
imageTimeSelector->UpdateLargestPossibleRegion();
mitk::Image::Pointer timeSliceImage = imageTimeSelector->GetOutput();
m_internalImage = timeSliceImage;
m_internalMask2D = nullptr; // is this correct when this variable holds a smart pointer?
m_internalMask3D = nullptr;
if ( m_Mask != nullptr )
{
m_Mask->SetTimeStep(m_TimeStep);
mitk::Image::ConstPointer timeSliceMask = m_Mask->GetMask();
if ( m_internalImage->GetDimension() == 3 )
{
itk::Image<unsigned short, 3>::Pointer noneConstMaskImage; //needed to work arround the fact that CastToItkImage currently does not support const itk images.
CastToItkImage(timeSliceMask, noneConstMaskImage);
m_internalMask3D = noneConstMaskImage;
AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 3, m_internalMask3D.GetPointer(), m_Label);
}
else if ( m_internalImage->GetDimension() == 2 )
{
itk::Image<unsigned short, 2>::Pointer noneConstMaskImage; //needed to work arround the fact that CastToItkImage currently does not support const itk images.
CastToItkImage(timeSliceMask, noneConstMaskImage);
m_internalMask2D = noneConstMaskImage;
AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 2, m_internalMask2D.GetPointer(), m_Label);
}
else
{
throw std::runtime_error( "Error: invalid image dimension" );
}
}
else
{
if ( m_internalImage->GetDimension() == 3 )
{
AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 3, m_internalMask3D.GetPointer(), m_Label);
}
else if ( m_internalImage->GetDimension() == 2 )
{
AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 2, m_internalMask2D.GetPointer(), m_Label);
}
else
{
throw std::runtime_error( "Error: invalid image dimension" );
}
}
this->Modified();
}
m_InternalMaskUpdateTime = m_InternalMask->GetMTime();
return m_InternalMask;
}
void HotspotMaskGenerator::SetTimeStep(unsigned int timeStep)
{
if (m_TimeStep != timeStep)
{
m_TimeStep = timeStep;
}
}
void HotspotMaskGenerator::SetLabel(unsigned short label)
{
if (label != m_Label)
{
m_Label = label;
this->Modified();
}
}
vnl_vector<int> HotspotMaskGenerator::GetConvolutionImageMinIndex()
{
this->GetMask(); // make sure we are up to date
return m_ConvolutionImageMinIndex;
}
vnl_vector<int> HotspotMaskGenerator::GetHotspotIndex()
{
this->GetMask(); // make sure we are up to date
return m_ConvolutionImageMaxIndex;
}
template <typename TPixel, unsigned int VImageDimension >
HotspotMaskGenerator::ImageExtrema
HotspotMaskGenerator::CalculateExtremaWorld( const itk::Image<TPixel, VImageDimension>* inputImage,
const itk::Image<unsigned short, VImageDimension>* maskImage,
double neccessaryDistanceToImageBorderInMM,
unsigned int label )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned short, VImageDimension > MaskImageType;
typedef itk::ImageRegionConstIteratorWithIndex<MaskImageType> MaskImageIteratorType;
typedef itk::ImageRegionConstIteratorWithIndex<ImageType> InputImageIndexIteratorType;
typename ImageType::SpacingType spacing = inputImage->GetSpacing();
ImageExtrema minMax;
minMax.Defined = false;
minMax.MaxIndex.set_size(VImageDimension);
minMax.MaxIndex.set_size(VImageDimension);
typename ImageType::RegionType allowedExtremaRegion = inputImage->GetLargestPossibleRegion();
bool keepDistanceToImageBorders( neccessaryDistanceToImageBorderInMM > 0 );
if (keepDistanceToImageBorders)
{
itk::IndexValueType distanceInPixels[VImageDimension];
for(unsigned short dimension = 0; dimension < VImageDimension; ++dimension)
{
// To confirm that the whole hotspot is inside the image we have to keep a specific distance to the image-borders, which is as long as
// the radius. To get the amount of indices we divide the radius by spacing and add 0.5 because voxels are center based:
// For example with a radius of 2.2 and a spacing of 1 two indices are enough because 2.2 / 1 + 0.5 = 2.7 => 2.
// But with a radius of 2.7 we need 3 indices because 2.7 / 1 + 0.5 = 3.2 => 3
distanceInPixels[dimension] = int( neccessaryDistanceToImageBorderInMM / spacing[dimension] + 0.5);
}
allowedExtremaRegion.ShrinkByRadius(distanceInPixels);
}
InputImageIndexIteratorType imageIndexIt(inputImage, allowedExtremaRegion);
float maxValue = itk::NumericTraits<float>::min();
float minValue = itk::NumericTraits<float>::max();
typename ImageType::IndexType maxIndex;
typename ImageType::IndexType minIndex;
for(unsigned short i = 0; i < VImageDimension; ++i)
{
maxIndex[i] = 0;
minIndex[i] = 0;
}
if (maskImage != nullptr)
{
MaskImageIteratorType maskIt(maskImage, maskImage->GetLargestPossibleRegion());
typename ImageType::IndexType imageIndex;
typename ImageType::IndexType maskIndex;
for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
{
imageIndex = maskIndex = maskIt.GetIndex();
if(maskIt.Get() == label)
{
if( allowedExtremaRegion.IsInside(imageIndex) )
{
imageIndexIt.SetIndex( imageIndex );
double value = imageIndexIt.Get();
minMax.Defined = true;
//Calculate minimum, maximum and corresponding index-values
if( value > maxValue )
{
maxIndex = imageIndexIt.GetIndex();
maxValue = value;
}
if(value < minValue )
{
minIndex = imageIndexIt.GetIndex();
minValue = value;
}
}
}
}
}
else
{
for(imageIndexIt.GoToBegin(); !imageIndexIt.IsAtEnd(); ++imageIndexIt)
{
double value = imageIndexIt.Get();
minMax.Defined = true;
//Calculate minimum, maximum and corresponding index-values
if( value > maxValue )
{
maxIndex = imageIndexIt.GetIndex();
maxValue = value;
}
if(value < minValue )
{
minIndex = imageIndexIt.GetIndex();
minValue = value;
}
}
}
minMax.MaxIndex.set_size(VImageDimension);
minMax.MinIndex.set_size(VImageDimension);
for(unsigned int i = 0; i < minMax.MaxIndex.size(); ++i)
{
minMax.MaxIndex[i] = maxIndex[i];
}
for(unsigned int i = 0; i < minMax.MinIndex.size(); ++i)
{
minMax.MinIndex[i] = minIndex[i];
}
minMax.Max = maxValue;
minMax.Min = minValue;
return minMax;
}
template <unsigned int VImageDimension>
itk::Size<VImageDimension>
HotspotMaskGenerator::CalculateConvolutionKernelSize( double spacing[VImageDimension],
double radiusInMM )
{
typedef itk::Image< float, VImageDimension > KernelImageType;
typedef typename KernelImageType::SizeType SizeType;
SizeType maskSize;
for(unsigned int i = 0; i < VImageDimension; ++i)
{
maskSize[i] = static_cast<int>( 2 * radiusInMM / spacing[i]);
// We always want an uneven size to have a clear center point in the convolution mask
if(maskSize[i] % 2 == 0 )
{
++maskSize[i];
}
}
return maskSize;
}
template <unsigned int VImageDimension>
itk::SmartPointer< itk::Image<float, VImageDimension> >
HotspotMaskGenerator::GenerateHotspotSearchConvolutionKernel(double mmPerPixel[VImageDimension],
double radiusInMM )
{
std::stringstream ss;
for (unsigned int i = 0; i < VImageDimension; ++i)
{
ss << mmPerPixel[i];
if (i < VImageDimension -1)
ss << ",";
}
MITK_DEBUG << "Update convolution kernel for spacing (" << ss.str() << ") and radius " << radiusInMM << "mm";
double radiusInMMSquared = radiusInMM * radiusInMM;
typedef itk::Image< float, VImageDimension > KernelImageType;
typename KernelImageType::Pointer convolutionKernel = KernelImageType::New();
// Calculate size and allocate mask image
typedef typename KernelImageType::SizeType SizeType;
SizeType maskSize = this->CalculateConvolutionKernelSize<VImageDimension>(mmPerPixel, radiusInMM);
mitk::Point3D convolutionMaskCenterIndex;
convolutionMaskCenterIndex.Fill(0.0);
for(unsigned int i = 0; i < VImageDimension; ++i)
{
convolutionMaskCenterIndex[i] = 0.5 * (double)(maskSize[i]-1);
}
typedef typename KernelImageType::IndexType IndexType;
IndexType maskIndex;
maskIndex.Fill(0);
typedef typename KernelImageType::RegionType RegionType;
RegionType maskRegion;
maskRegion.SetSize(maskSize);
maskRegion.SetIndex(maskIndex);
convolutionKernel->SetRegions(maskRegion);
convolutionKernel->SetSpacing(mmPerPixel);
convolutionKernel->Allocate();
// Fill mask image values by subsampling the image grid
typedef itk::ImageRegionIteratorWithIndex<KernelImageType> MaskIteratorType;
MaskIteratorType maskIt(convolutionKernel,maskRegion);
int numberOfSubVoxelsPerDimension = 2; // per dimension!
int numberOfSubVoxels = ::pow( static_cast<float>(numberOfSubVoxelsPerDimension), static_cast<float>(VImageDimension) );
double subVoxelSizeInPixels = 1.0 / (double)numberOfSubVoxelsPerDimension;
double valueOfOneSubVoxel = 1.0 / (double)numberOfSubVoxels;
mitk::Point3D subVoxelIndexPosition;
double distanceSquared = 0.0;
typedef itk::ContinuousIndex<double, VImageDimension> ContinuousIndexType;
for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
{
ContinuousIndexType indexPoint(maskIt.GetIndex());
mitk::Point3D voxelPosition;
for (unsigned int dimension = 0; dimension < VImageDimension; ++dimension)
{
voxelPosition[dimension] = indexPoint[dimension];
}
double maskValue = 0.0;
mitk::Vector3D subVoxelOffset; subVoxelOffset.Fill(0.0);
// iterate sub-voxels by iterating all possible offsets
for (subVoxelOffset[0] = -0.5 + subVoxelSizeInPixels / 2.0;
subVoxelOffset[0] < +0.5;
subVoxelOffset[0] += subVoxelSizeInPixels)
{
for (subVoxelOffset[1] = -0.5 + subVoxelSizeInPixels / 2.0;
subVoxelOffset[1] < +0.5;
subVoxelOffset[1] += subVoxelSizeInPixels)
{
for (subVoxelOffset[2] = -0.5 + subVoxelSizeInPixels / 2.0;
subVoxelOffset[2] < +0.5;
subVoxelOffset[2] += subVoxelSizeInPixels)
{
subVoxelIndexPosition = voxelPosition + subVoxelOffset; // this COULD be integrated into the for-loops if neccessary (add voxelPosition to initializer and end condition)
distanceSquared =
(subVoxelIndexPosition[0]-convolutionMaskCenterIndex[0]) * mmPerPixel[0] * (subVoxelIndexPosition[0]-convolutionMaskCenterIndex[0]) * mmPerPixel[0]
+ (subVoxelIndexPosition[1]-convolutionMaskCenterIndex[1]) * mmPerPixel[1] * (subVoxelIndexPosition[1]-convolutionMaskCenterIndex[1]) * mmPerPixel[1]
+ (subVoxelIndexPosition[2]-convolutionMaskCenterIndex[2]) * mmPerPixel[2] * (subVoxelIndexPosition[2]-convolutionMaskCenterIndex[2]) * mmPerPixel[2];
if (distanceSquared <= radiusInMMSquared)
{
maskValue += valueOfOneSubVoxel;
}
}
}
}
maskIt.Set( maskValue );
}
return convolutionKernel;
}
template <typename TPixel, unsigned int VImageDimension>
itk::SmartPointer<itk::Image<TPixel, VImageDimension> >
HotspotMaskGenerator::GenerateConvolutionImage( const itk::Image<TPixel, VImageDimension>* inputImage )
{
double mmPerPixel[VImageDimension];
for (unsigned int dimension = 0; dimension < VImageDimension; ++dimension)
{
mmPerPixel[dimension] = inputImage->GetSpacing()[dimension];
}
// update convolution kernel
typedef itk::Image< float, VImageDimension > KernelImageType;
typename KernelImageType::Pointer convolutionKernel = this->GenerateHotspotSearchConvolutionKernel<VImageDimension>(mmPerPixel, m_HotspotRadiusinMM);
// update convolution image
typedef itk::Image< TPixel, VImageDimension > InputImageType;
typedef itk::Image< TPixel, VImageDimension > ConvolutionImageType;
typedef itk::FFTConvolutionImageFilter<InputImageType,
KernelImageType,
ConvolutionImageType> ConvolutionFilterType;
+ itk::VnlFFTImageFilterInitFactory::RegisterFactories();
+
typename ConvolutionFilterType::Pointer convolutionFilter = ConvolutionFilterType::New();
typedef itk::ConstantBoundaryCondition<InputImageType, InputImageType> BoundaryConditionType;
BoundaryConditionType boundaryCondition;
boundaryCondition.SetConstant(0.0);
if (m_HotspotMustBeCompletelyInsideImage)
{
// overwrite default boundary condition
convolutionFilter->SetBoundaryCondition(&boundaryCondition);
}
convolutionFilter->SetInput(inputImage);
convolutionFilter->SetKernelImage(convolutionKernel);
convolutionFilter->SetNormalize(true);
MITK_DEBUG << "Update Convolution image for hotspot search";
convolutionFilter->UpdateLargestPossibleRegion();
typename ConvolutionImageType::Pointer convolutionImage = convolutionFilter->GetOutput();
convolutionImage->SetSpacing( inputImage->GetSpacing() ); // only workaround because convolution filter seems to ignore spacing of input image
return convolutionImage;
}
template < typename TPixel, unsigned int VImageDimension>
void
HotspotMaskGenerator::FillHotspotMaskPixels( itk::Image<TPixel, VImageDimension>* maskImage,
itk::Point<double, VImageDimension> sphereCenter,
double sphereRadiusInMM )
{
typedef itk::Image< TPixel, VImageDimension > MaskImageType;
typedef itk::ImageRegionIteratorWithIndex<MaskImageType> MaskImageIteratorType;
MaskImageIteratorType maskIt(maskImage, maskImage->GetLargestPossibleRegion());
typename MaskImageType::IndexType maskIndex;
typename MaskImageType::PointType worldPosition;
// this is not very smart. I would rather use a 0 initialized mask (not the case here -> blame CalculateHotspotMask) and find the region where I need to iterate over, then iterate only over the small region
for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
{
maskIndex = maskIt.GetIndex();
maskImage->TransformIndexToPhysicalPoint(maskIndex, worldPosition);
maskIt.Set( worldPosition.EuclideanDistanceTo(sphereCenter) <= sphereRadiusInMM ? 1 : 0 );
}
}
template <typename TPixel, unsigned int VImageDimension>
void
HotspotMaskGenerator::CalculateHotspotMask(itk::Image<TPixel, VImageDimension>* inputImage,
const itk::Image<unsigned short, VImageDimension>* maskImage,
unsigned int label)
{
typedef itk::Image< TPixel, VImageDimension > InputImageType;
typedef itk::Image< TPixel, VImageDimension > ConvolutionImageType;
typedef itk::Image< unsigned short, VImageDimension > MaskImageType;
typename ConvolutionImageType::Pointer convolutionImage = this->GenerateConvolutionImage(inputImage);
if (convolutionImage.IsNull())
{
MITK_ERROR << "Empty convolution image in CalculateHotspotStatistics(). We should never reach this state (logic error).";
throw std::logic_error("Empty convolution image in CalculateHotspotStatistics()");
}
typename MaskImageType::ConstPointer usedMask = maskImage;
// if mask image is not defined, create an image of the same size as inputImage and fill it with 1's
// there is maybe a better way to do this!?
if (maskImage == nullptr)
{
auto defaultMask = MaskImageType::New();
typename MaskImageType::RegionType maskRegion = inputImage->GetLargestPossibleRegion();
typename MaskImageType::SpacingType maskSpacing = inputImage->GetSpacing();
typename MaskImageType::PointType maskOrigin = inputImage->GetOrigin();
typename MaskImageType::DirectionType maskDirection = inputImage->GetDirection();
defaultMask->SetRegions(maskRegion);
defaultMask->Allocate();
defaultMask->SetOrigin(maskOrigin);
defaultMask->SetSpacing(maskSpacing);
defaultMask->SetDirection(maskDirection);
defaultMask->FillBuffer(1);
usedMask = defaultMask;
label = 1;
}
// find maximum in convolution image, given the current mask
double requiredDistanceToBorder = m_HotspotMustBeCompletelyInsideImage ? m_HotspotRadiusinMM : -1.0;
ImageExtrema convolutionImageInformation = CalculateExtremaWorld(convolutionImage.GetPointer(), usedMask.GetPointer(), requiredDistanceToBorder, label);
bool isHotspotDefined = convolutionImageInformation.Defined;
if (!isHotspotDefined)
{
MITK_ERROR << "No origin of hotspot-sphere was calculated!";
m_InternalMask = nullptr;
}
else
{
// create a binary mask around the "hotspot" region, fill the shape of a sphere around our hotspot center
// typename DuplicatorType::Pointer copyMachine = DuplicatorType::New();
// copyMachine->SetInputImage(inputImage);
// copyMachine->Update();
// typename CastFilterType::Pointer caster = CastFilterType::New();
// caster->SetInput( copyMachine->GetOutput() );
// caster->Update();
typename MaskImageType::Pointer hotspotMaskITK = MaskImageType::New();
hotspotMaskITK->SetOrigin(inputImage->GetOrigin());
hotspotMaskITK->SetSpacing(inputImage->GetSpacing());
hotspotMaskITK->SetLargestPossibleRegion(inputImage->GetLargestPossibleRegion());
hotspotMaskITK->SetBufferedRegion(inputImage->GetBufferedRegion());
hotspotMaskITK->SetDirection(inputImage->GetDirection());
hotspotMaskITK->SetNumberOfComponentsPerPixel(inputImage->GetNumberOfComponentsPerPixel());
hotspotMaskITK->Allocate();
hotspotMaskITK->FillBuffer(1);
typedef typename InputImageType::IndexType IndexType;
IndexType maskCenterIndex;
for (unsigned int d =0; d< VImageDimension;++d)
{
maskCenterIndex[d]=convolutionImageInformation.MaxIndex[d];
}
typename ConvolutionImageType::PointType maskCenter;
inputImage->TransformIndexToPhysicalPoint(maskCenterIndex,maskCenter);
FillHotspotMaskPixels(hotspotMaskITK.GetPointer(), maskCenter, m_HotspotRadiusinMM);
//obtain mitk::Image::Pointer from itk::Image
mitk::Image::Pointer hotspotMaskAsMITKImage = mitk::GrabItkImageMemory(hotspotMaskITK);
m_InternalMask = hotspotMaskAsMITKImage;
m_ConvolutionImageMaxIndex = convolutionImageInformation.MaxIndex;
m_ConvolutionImageMinIndex = convolutionImageInformation.MinIndex;
}
}
bool HotspotMaskGenerator::IsUpdateRequired() const
{
unsigned long thisClassTimeStamp = this->GetMTime();
unsigned long internalMaskTimeStamp = m_InternalMask->GetMTime();
unsigned long maskGeneratorTimeStamp = m_Mask->GetMTime();
unsigned long inputImageTimeStamp = m_inputImage->GetMTime();
if (thisClassTimeStamp > m_InternalMaskUpdateTime) // inputs have changed
{
return true;
}
if (m_InternalMaskUpdateTime < maskGeneratorTimeStamp || m_InternalMaskUpdateTime < inputImageTimeStamp) // mask image has changed outside of this class
{
return true;
}
if (internalMaskTimeStamp > m_InternalMaskUpdateTime) // internal mask has been changed outside of this class
{
return true;
}
return false;
}
}
diff --git a/Modules/ImageStatistics/mitkMaskUtilities.tpp b/Modules/ImageStatistics/mitkMaskUtilities.tpp
index f1d52ea2aa..ab740cb9f7 100644
--- a/Modules/ImageStatistics/mitkMaskUtilities.tpp
+++ b/Modules/ImageStatistics/mitkMaskUtilities.tpp
@@ -1,194 +1,194 @@
/*============================================================================
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 MITKMASKUTIL_TPP
#define MITKMASKUTIL_TPP
#include <mitkMaskUtilities.h>
#include <mitkImageAccessByItk.h>
#include <itkExtractImageFilter.h>
#include <itkChangeInformationImageFilter.h>
#include <mitkITKImageImport.h>
namespace mitk
{
template <class TPixel, unsigned int VImageDimension>
void MaskUtilities<TPixel, VImageDimension>::SetImage(const ImageType* image)
{
if (image != m_Image)
{
m_Image = image;
}
}
template <class TPixel, unsigned int VImageDimension>
void MaskUtilities<TPixel, VImageDimension>::SetMask(const MaskType* mask)
{
if (mask != m_Mask)
{
m_Mask = mask;
}
}
template <class TPixel, unsigned int VImageDimension>
bool MaskUtilities<TPixel, VImageDimension>::CheckMaskSanity()
{
if (m_Mask==nullptr || m_Image==nullptr)
{
MITK_ERROR << "Set an image and a mask first";
}
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef typename ImageType::PointType PointType;
typedef typename ImageType::DirectionType DirectionType;
bool maskSanity = true;
if (m_Mask==nullptr)
{
MITK_ERROR << "Something went wrong when casting the mitk mask image to an itk mask image. Do the mask and the input image have the same dimension?";
// note to self: We could try to convert say a 2d mask to a 3d mask if the image is 3d. (mask and image dimension have to match.)
}
// check direction
DirectionType imageDirection = m_Image->GetDirection();
DirectionType maskDirection = m_Mask->GetDirection();
for(unsigned int i = 0; i < imageDirection.ColumnDimensions; ++i )
{
for(unsigned int j = 0; j < imageDirection.ColumnDimensions; ++j )
{
double differenceDirection = imageDirection[i][j] - maskDirection[i][j];
if (fabs(differenceDirection) > MASK_SUITABILITY_TOLERANCE_DIRECTION)
{
maskSanity = false;
MITK_INFO << "Mask needs to have same direction as image! (Image direction: " << imageDirection << "; Mask direction: " << maskDirection << ")";
}
}
}
// check spacing
- PointType imageSpacing = m_Image->GetSpacing();
- PointType maskSpacing = m_Mask->GetSpacing();
+ PointType imageSpacing(m_Image->GetSpacing().GetDataPointer());
+ PointType maskSpacing(m_Mask->GetSpacing().GetDataPointer());
for (unsigned int i = 0; i < VImageDimension; i++)
{
if ( fabs( maskSpacing[i] - imageSpacing[i] ) > MASK_SUITABILITY_TOLERANCE_COORDINATE )
{
maskSanity = false;
MITK_INFO << "Spacing of mask and image is not equal. Mask: " << maskSpacing << " image: " << imageSpacing;
}
}
// check alignment
// Make sure that the voxels of mask and image are correctly "aligned", i.e., voxel boundaries are the same in both images
PointType imageOrigin = m_Image->GetOrigin();
PointType maskOrigin = m_Mask->GetOrigin();
typedef itk::ContinuousIndex<double, VImageDimension> ContinousIndexType;
ContinousIndexType maskOriginContinousIndex, imageOriginContinousIndex;
m_Image->TransformPhysicalPointToContinuousIndex(maskOrigin, maskOriginContinousIndex);
m_Image->TransformPhysicalPointToContinuousIndex(imageOrigin, imageOriginContinousIndex);
for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i )
{
double misalignment = maskOriginContinousIndex[i] - floor( maskOriginContinousIndex[i] + 0.5 );
// misalignment must be a multiple (int) of spacing in that direction
if ( fmod(misalignment,imageSpacing[i]) > MASK_SUITABILITY_TOLERANCE_COORDINATE)
{
maskSanity = false;
MITK_INFO << "Pixels/voxels of mask and image are not sufficiently aligned! (Misalignment: " << fmod(misalignment,imageSpacing[i]) << ")";
}
}
// mask must be completely inside image region
// Make sure that mask region is contained within image region
if ( m_Mask!=nullptr &&
!m_Image->GetLargestPossibleRegion().IsInside( m_Mask->GetLargestPossibleRegion() ) )
{
maskSanity = false;
MITK_INFO << "Mask region needs to be inside of image region! (Image region: "
<< m_Image->GetLargestPossibleRegion() << "; Mask region: " << m_Mask->GetLargestPossibleRegion() << ")";
}
return maskSanity;
}
template <class TPixel, unsigned int VImageDimension>
typename MaskUtilities<TPixel, VImageDimension >::ImageType::ConstPointer MaskUtilities<TPixel, VImageDimension>::ExtractMaskImageRegion()
{
if (m_Mask==nullptr || m_Image==nullptr)
{
MITK_ERROR << "Set an image and a mask first";
}
bool maskSanity = CheckMaskSanity();
if (!maskSanity)
{
MITK_ERROR << "Mask and image are not compatible";
}
typedef itk::ExtractImageFilter< ImageType, ImageType > ExtractImageFilterType;
typename ImageType::SizeType imageSize = m_Image->GetBufferedRegion().GetSize();
typename ImageType::SizeType maskSize = m_Mask->GetBufferedRegion().GetSize();
typename itk::Image<TPixel, VImageDimension>::ConstPointer resultImg;
bool maskSmallerImage = false;
for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i )
{
if ( maskSize[i] < imageSize[i] )
{
maskSmallerImage = true;
}
}
if ( maskSmallerImage )
{
typename ExtractImageFilterType::Pointer extractImageFilter = ExtractImageFilterType::New();
typename MaskType::PointType maskOrigin = m_Mask->GetOrigin();
typename ImageType::PointType imageOrigin = m_Image->GetOrigin();
typename MaskType::SpacingType maskSpacing = m_Mask->GetSpacing();
typename ImageType::RegionType extractionRegion;
typename ImageType::IndexType extractionRegionIndex;
for (unsigned int i=0; i < maskOrigin.GetPointDimension(); i++)
{
extractionRegionIndex[i] = (maskOrigin[i] - imageOrigin[i]) / maskSpacing[i];
}
extractionRegion.SetIndex(extractionRegionIndex);
extractionRegion.SetSize(m_Mask->GetLargestPossibleRegion().GetSize());
extractImageFilter->SetInput( m_Image );
extractImageFilter->SetExtractionRegion( extractionRegion );
extractImageFilter->SetCoordinateTolerance(MASK_SUITABILITY_TOLERANCE_COORDINATE);
extractImageFilter->SetDirectionTolerance(MASK_SUITABILITY_TOLERANCE_DIRECTION);
extractImageFilter->Update();
auto extractedImg = extractImageFilter->GetOutput();
extractedImg->SetOrigin(m_Mask->GetOrigin());
extractedImg->SetLargestPossibleRegion(m_Mask->GetLargestPossibleRegion());
extractedImg->SetBufferedRegion(m_Mask->GetBufferedRegion());
resultImg = extractedImg;
}
else
{
resultImg = m_Image;
}
return resultImg;
}
}
#endif
diff --git a/Modules/Log/CMakeLists.txt b/Modules/Log/CMakeLists.txt
new file mode 100644
index 0000000000..c741c77506
--- /dev/null
+++ b/Modules/Log/CMakeLists.txt
@@ -0,0 +1,11 @@
+option(MITK_ENABLE_DEBUG_MESSAGES "Enable extra debug log output" OFF)
+mark_as_advanced(MITK_ENABLE_DEBUG_MESSAGES)
+
+configure_file(
+ mitkLogConfig.h.in
+ mitkLogConfig.h
+)
+
+mitk_create_module(
+ NO_INIT
+)
diff --git a/Modules/Log/files.cmake b/Modules/Log/files.cmake
new file mode 100644
index 0000000000..17af6cbac0
--- /dev/null
+++ b/Modules/Log/files.cmake
@@ -0,0 +1,16 @@
+set(H_FILES
+ include/mitkLog.h
+ include/mitkLogBackendBase.h
+ include/mitkLogBackendText.h
+ include/mitkLogBackendCout.h
+ include/mitkLogLevel.h
+ include/mitkLogMessage.h
+)
+
+set(CPP_FILES
+ mitkLog.cpp
+ mitkLogBackendBase.cpp
+ mitkLogBackendText.cpp
+ mitkLogBackendCout.cpp
+ mitkLogMessage.cpp
+)
diff --git a/Modules/Log/include/mitkLog.h b/Modules/Log/include/mitkLog.h
new file mode 100644
index 0000000000..37b44c2ca7
--- /dev/null
+++ b/Modules/Log/include/mitkLog.h
@@ -0,0 +1,220 @@
+/*============================================================================
+
+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 mitkLog_h
+#define mitkLog_h
+
+#include <mitkLogBackendBase.h>
+
+#include <sstream>
+
+#include <MitkLogExports.h>
+
+#ifndef MITKLOG_MODULENAME
+# if defined(US_MODULE_NAME)
+# define MITKLOG_STR_(x) #x
+# define MITKLOG_STR(x) MITKLOG_STR_(x)
+# define MITKLOG_MODULENAME MITKLOG_STR(US_MODULE_NAME)
+# else
+# define MITKLOG_MODULENAME "n/a"
+# endif
+#endif
+
+namespace mitk
+{
+ /** \brief Register a backend in the MITK log mechanism.
+ *
+ * If a backend is registered here, all log messages are relayed to this backend through the method ProcessMessage.
+ * If no backend is registered, the default backend is used.
+ */
+ void MITKLOG_EXPORT RegisterBackend(LogBackendBase* backend);
+
+ /** \brief Unregister a backend.
+ */
+ void MITKLOG_EXPORT UnregisterBackend(LogBackendBase* backend);
+
+ /** \brief Distribute the given message to all registered backends.
+ *
+ * Should only be called by PseudoLogStream objects.
+ */
+ void MITKLOG_EXPORT DistributeToBackends(LogMessage& message);
+
+ /** \brief Enable the output of a backend.
+ */
+ void MITKLOG_EXPORT EnableBackends(LogBackendBase::OutputType type);
+
+ /** \brief Disable the output of a backend.
+ */
+ void MITKLOG_EXPORT DisableBackends(LogBackendBase::OutputType type);
+
+ /** \brief Check wether the output of this backend is enabled.
+ */
+ bool MITKLOG_EXPORT IsBackendEnabled(LogBackendBase::OutputType type);
+
+ /** \brief Simulates a std::cout stream.
+ *
+ * Should only be used by the macros defined in the file mitkLog.h.
+ */
+ class MITKLOG_EXPORT PseudoLogStream
+ {
+ public:
+ PseudoLogStream(LogLevel level, const std::string& filePath, int lineNumber, const std::string& functionName)
+ : m_Disabled(false),
+ m_Message(level, filePath, lineNumber, functionName),
+ m_Stream(std::stringstream::out)
+ {
+ }
+
+ /** \brief The encapsulated message is written to the backend.
+ */
+ ~PseudoLogStream()
+ {
+ if (!m_Disabled)
+ {
+ m_Message.Message = m_Stream.str();
+ m_Message.ModuleName = MITKLOG_MODULENAME;
+ DistributeToBackends(m_Message);
+ }
+ }
+
+ template <class T>
+ PseudoLogStream& operator<<(const T& data)
+ {
+ if (!m_Disabled)
+ {
+ std::locale C("C");
+ std::locale originalLocale = m_Stream.getloc();
+ m_Stream.imbue(C);
+
+ m_Stream << data;
+
+ m_Stream.imbue(originalLocale);
+ }
+
+ return *this;
+ }
+
+ template <class T>
+ PseudoLogStream& operator<<(T& data)
+ {
+ if (!m_Disabled)
+ {
+ std::locale C("C");
+ std::locale originalLocale = m_Stream.getloc();
+ m_Stream.imbue(C);
+
+ m_Stream << data;
+
+ m_Stream.imbue(originalLocale);
+ }
+
+ return *this;
+ }
+
+ PseudoLogStream& operator<<(std::ostream& (*func)(std::ostream&))
+ {
+ if (!m_Disabled)
+ {
+ std::locale C("C");
+ std::locale originalLocale = m_Stream.getloc();
+ m_Stream.imbue(C);
+
+ m_Stream << func;
+
+ m_Stream.imbue(originalLocale);
+ }
+
+ return *this;
+ }
+
+ /** \brief Sets the category of this PseudoLogStream object.
+ *
+ * If there is already a category it is appended, seperated by a dot.
+ */
+ PseudoLogStream& operator()(const std::string& category)
+ {
+ if (!m_Disabled)
+ {
+ if (m_Message.Category.length())
+ m_Message.Category += ".";
+
+ m_Message.Category += category;
+ }
+
+ return *this;
+ }
+
+ /** \brief Enables/disables the PseudoLogStream.
+ *
+ * If set to false, parsing and output is suppressed.
+ */
+ PseudoLogStream& operator()(bool enabled)
+ {
+ m_Disabled |= !enabled;
+ return *this;
+ }
+
+ protected:
+ bool m_Disabled;
+ LogMessage m_Message;
+ std::stringstream m_Stream;
+ };
+
+ /**
+ * \brief Simulates a std::cout stream but does nothing.
+ *
+ * Should only be used by the macros defined in the file mitkLog.h.
+ */
+ class MITKLOG_EXPORT NullLogStream
+ {
+ public:
+ template <class T>
+ NullLogStream& operator<<(const T&)
+ {
+ return *this;
+ }
+
+ template <class T>
+ NullLogStream& operator<<(T&)
+ {
+ return *this;
+ }
+
+ NullLogStream& operator<<(std::ostream &(*)(std::ostream &))
+ {
+ return *this;
+ }
+
+ NullLogStream& operator()(const char*)
+ {
+ return *this;
+ }
+
+ NullLogStream& operator()(bool)
+ {
+ return *this;
+ }
+ };
+}
+
+#define MITK_INFO mitk::PseudoLogStream(mitk::LogLevel::Info, __FILE__, __LINE__, __FUNCTION__)
+#define MITK_WARN mitk::PseudoLogStream(mitk::LogLevel::Warn, __FILE__, __LINE__, __FUNCTION__)
+#define MITK_ERROR mitk::PseudoLogStream(mitk::LogLevel::Error, __FILE__, __LINE__, __FUNCTION__)
+#define MITK_FATAL mitk::PseudoLogStream(mitk::LogLevel::Fatal, __FILE__, __LINE__, __FUNCTION__)
+
+#ifdef MITK_ENABLE_DEBUG_MESSAGES
+#define MITK_DEBUG mitk::PseudoLogStream(mitk::LogLevel::Debug, __FILE__, __LINE__, __FUNCTION__)
+#else
+#define MITK_DEBUG true ? mitk::NullLogStream() : mitk::NullLogStream()
+#endif
+
+#endif
diff --git a/Modules/Log/include/mitkLogBackendBase.h b/Modules/Log/include/mitkLogBackendBase.h
new file mode 100644
index 0000000000..3f7c11cbc1
--- /dev/null
+++ b/Modules/Log/include/mitkLogBackendBase.h
@@ -0,0 +1,50 @@
+/*============================================================================
+
+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 mitkLogBackendBase_h
+#define mitkLogBackendBase_h
+
+#include <mitkLogMessage.h>
+#include <MitkLogExports.h>
+
+namespace mitk
+{
+ /** \brief Interface for log backends that can be registered in the MITK log mechanism.
+ */
+ class MITKLOG_EXPORT LogBackendBase
+ {
+ public:
+ /** Type of the output of a backend.
+ */
+ enum class OutputType
+ {
+ Console,
+ File,
+ Other = 100
+ };
+
+ virtual ~LogBackendBase();
+
+ /** \brief Called by the MITK log mechanism if the object is registered and a log message is emitted.
+ *
+ * \param message Logging message which was emitted.
+ */
+ virtual void ProcessMessage(const LogMessage& message) = 0;
+
+ /**
+ * \return The type of this backend.
+ */
+ virtual OutputType GetOutputType() const = 0;
+ };
+}
+
+#endif
diff --git a/Modules/Log/include/mitkLogBackendCout.h b/Modules/Log/include/mitkLogBackendCout.h
new file mode 100644
index 0000000000..6da2258489
--- /dev/null
+++ b/Modules/Log/include/mitkLogBackendCout.h
@@ -0,0 +1,47 @@
+/*============================================================================
+
+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 mitkLogBackendCout_h
+#define mitkLogBackendCout_h
+
+#include <mitkLogBackendText.h>
+
+namespace mitk
+{
+ /** \brief Default backend of the MITK log mechanism.
+ *
+ * This backend is used if no other backend is registered. The backend formats the log messages to a normal string
+ * and writes them to std::cout.
+ */
+ class MITKLOG_EXPORT LogBackendCout : public LogBackendText
+ {
+ public:
+ LogBackendCout();
+ ~LogBackendCout() override;
+
+ void ProcessMessage(const LogMessage &message) override;
+
+ /** \brief Sets the formatting mode.
+ *
+ * If true, long messages will be displayed. Default is false (short/smart messages). Long messages provide all
+ * information and are capable to be postprocessed (e.g. in a web viewer).
+ */
+ void SetFull(bool full);
+
+ OutputType GetOutputType() const override;
+
+ private:
+ bool m_UseFullOutput;
+ };
+}
+
+#endif
diff --git a/Modules/Log/include/mitkLogBackendText.h b/Modules/Log/include/mitkLogBackendText.h
new file mode 100644
index 0000000000..5917219c9a
--- /dev/null
+++ b/Modules/Log/include/mitkLogBackendText.h
@@ -0,0 +1,73 @@
+/*============================================================================
+
+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 mitkLogBackendText_h
+#define mitkLogBackendText_h
+
+#include <mitkLogBackendBase.h>
+
+namespace mitk
+{
+ /** \brief Abstract superclass for text-based log backends.
+ *
+ * Adds string formatting methods to the interface LogBackendBase. Backends that inherit from this class can be
+ * registered by the MITK log mechanism.
+ */
+ class MITKLOG_EXPORT LogBackendText : public LogBackendBase
+ {
+ public:
+ ~LogBackendText() override;
+
+ void ProcessMessage(const LogMessage& message) override = 0;
+
+ protected:
+ /** \brief Format the given message in the smart/short format and writes it to std::cout.
+ *
+ * \param message
+ * \param threadID Can be set to the thread id where the log message was emitted. 0 by default.
+ */
+ void FormatSmart(const LogMessage& message, int threadID = 0);
+
+ /** \brief Format the given message in the full/long format and writes it to std::cout.
+ *
+ * \param message
+ * \param threadID Can be set to the thread id where the log message was emitted. 0 by default.
+ */
+ void FormatFull(const LogMessage& message, int threadID = 0);
+
+ /** \brief Format the given message in the smart/short format and writes it to the given std::ostream.
+ *
+ * \param out
+ * \param message
+ * \param threadID Can be set to the thread id where the log message was emitted. 0 by default.
+ */
+ void FormatSmart(std::ostream& out, const LogMessage& message, int threadID = 0);
+
+ /** \brief Format the given message in the full/long format and writes it to the given std::ostream.
+ *
+ * \param out
+ * \param message
+ * \param threadID Can be set to the thread id where the log message was emitted. 0 by default.
+ */
+ void FormatFull(std::ostream& out, const LogMessage& message, int threadID = 0);
+
+ /** \brief Write system time to the given stream.
+ */
+ void AppendTimeStamp(std::ostream& out);
+
+ /** \brief Special variant of method FormatSmart which uses colored messages (only for Windows).
+ */
+ void FormatSmartWindows(const LogMessage& message, int /*threadID*/);
+ };
+}
+
+#endif
diff --git a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkAdditionalRFData.cpp b/Modules/Log/include/mitkLogLevel.h
similarity index 63%
rename from Modules/Classification/CLVigraRandomForest/src/Splitter/mitkAdditionalRFData.cpp
rename to Modules/Log/include/mitkLogLevel.h
index e09b9ad06f..ae96189eff 100644
--- a/Modules/Classification/CLVigraRandomForest/src/Splitter/mitkAdditionalRFData.cpp
+++ b/Modules/Log/include/mitkLogLevel.h
@@ -1,18 +1,30 @@
/*============================================================================
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 <mitkAdditionalRFData.h>
+#ifndef mitkLogLevel_h
+#define mitkLogLevel_h
-void mitk::PURFData::NoFunction()
+namespace mitk
{
- return;
+ /** \brief Message/event levels of the MITK log mechanism.
+ */
+ enum class LogLevel
+ {
+ Info,
+ Warn,
+ Error,
+ Fatal,
+ Debug
+ };
}
+
+#endif
diff --git a/Modules/Log/include/mitkLogMessage.h b/Modules/Log/include/mitkLogMessage.h
new file mode 100644
index 0000000000..02dc2cd839
--- /dev/null
+++ b/Modules/Log/include/mitkLogMessage.h
@@ -0,0 +1,64 @@
+/*============================================================================
+
+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 mitkLogMessage_h
+#define mitkLogMessage_h
+
+#include <mitkLogLevel.h>
+
+#include <string>
+
+#include <MitkLogExports.h>
+
+namespace mitk
+{
+ /** \brief A single log message (log event) of the MITK log mechanism.
+ *
+ * Logging messages should only be generated by the macros provided by mitkLog.h
+ */
+
+ struct MITKLOG_EXPORT LogMessage
+ {
+ public:
+ LogMessage(const LogLevel level, const std::string& filePath, const int lineNumber, const std::string& functionName);
+
+ /** \brief Log level of the emitted log message.
+ */
+ const LogLevel Level;
+
+ /** \brief File name of the source file where the log message was emitted.
+ */
+ const std::string FilePath;
+
+ /** \brief Line of the source source file where the log message was emitted.
+ */
+ const int LineNumber;
+
+ /** \brief Name of the method where the log message was emitted.
+ */
+ const std::string FunctionName;
+
+ /** \brief Name of the module where the log message was emitted.
+ */
+ std::string ModuleName;
+
+ /** \brief Category of the log event, which was defined by the user.
+ */
+ std::string Category;
+
+ /** \brief The actual log message.
+ */
+ std::string Message;
+ };
+}
+
+#endif
diff --git a/Utilities/mbilog/mbilogLogMessage.cpp b/Modules/Log/mitkLogConfig.h.in
similarity index 80%
rename from Utilities/mbilog/mbilogLogMessage.cpp
rename to Modules/Log/mitkLogConfig.h.in
index 1611c21945..1191fd7846 100644
--- a/Utilities/mbilog/mbilogLogMessage.cpp
+++ b/Modules/Log/mitkLogConfig.h.in
@@ -1,15 +1,18 @@
/*============================================================================
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 "mbilogLogMessage.h"
+#ifndef mitkLogConfig_h
+#define mitkLogConfig_h
-// TODO: delete?
+#cmakedefine MITK_ENABLE_DEBUG_MESSAGES
+
+#endif
diff --git a/Utilities/mbilog/mbilog.cpp b/Modules/Log/src/mitkLog.cpp
similarity index 52%
rename from Utilities/mbilog/mbilog.cpp
rename to Modules/Log/src/mitkLog.cpp
index bcdba45ee7..940ee0b4f1 100644
--- a/Utilities/mbilog/mbilog.cpp
+++ b/Modules/Log/src/mitkLog.cpp
@@ -1,83 +1,80 @@
/*============================================================================
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 <mitkLog.h>
+#include <mitkLogBackendCout.h>
+
#include <list>
#include <set>
-#include "mbilog.h"
-
-static std::list<mbilog::BackendBase *> backends;
-static std::set<mbilog::OutputType> disabledBackendTypes;
-
-namespace mbilog
-{
- static const std::string NA_STRING = "n/a";
-}
+static std::list<mitk::LogBackendBase*> backends;
+static std::set<mitk::LogBackendBase::OutputType> disabledBackendTypes;
-void mbilog::RegisterBackend(mbilog::BackendBase *backend)
+void mitk::RegisterBackend(LogBackendBase* backend)
{
backends.push_back(backend);
}
-void mbilog::UnregisterBackend(mbilog::BackendBase *backend)
+void mitk::UnregisterBackend(LogBackendBase* backend)
{
backends.remove(backend);
}
-void mbilog::DistributeToBackends(mbilog::LogMessage &l)
+void mitk::DistributeToBackends(LogMessage& message)
{
// Crop Message
{
- std::string::size_type i = l.message.find_last_not_of(" \t\f\v\n\r");
- l.message = (i != std::string::npos) ? l.message.substr(0, i + 1) : "";
+ std::string::size_type i = message.Message.find_last_not_of(" \t\f\v\n\r");
+
+ message.Message = i != std::string::npos
+ ? message.Message.substr(0, i + 1)
+ : "";
}
// create dummy backend if there is no backend registered (so we have an output anyway)
- static mbilog::BackendCout *dummyBackend = nullptr;
+ static LogBackendCout* dummyBackend = nullptr;
- if (backends.empty() && (dummyBackend == nullptr))
+ if (backends.empty() && dummyBackend == nullptr)
{
- dummyBackend = new mbilog::BackendCout();
- dummyBackend->SetFull(false);
+ dummyBackend = new LogBackendCout;
RegisterBackend(dummyBackend);
}
- else if ((backends.size() > 1) && (dummyBackend != nullptr))
+ else if (backends.size() > 1 && dummyBackend != nullptr)
{
// if there was added another backend remove the dummy backend and delete it
UnregisterBackend(dummyBackend);
delete dummyBackend;
dummyBackend = nullptr;
}
// iterate through all registered images and call the ProcessMessage() methods of the backends
- std::list<mbilog::BackendBase *>::iterator i;
- for (i = backends.begin(); i != backends.end(); i++)
+ for (auto i = backends.begin(); i != backends.end(); ++i)
{
if (IsBackendEnabled((*i)->GetOutputType()))
- (*i)->ProcessMessage(l);
+ (*i)->ProcessMessage(message);
}
}
-void mbilog::EnableBackends(OutputType type)
+void mitk::EnableBackends(LogBackendBase::OutputType type)
{
disabledBackendTypes.erase(type);
}
-void mbilog::DisableBackends(OutputType type)
+void mitk::DisableBackends(LogBackendBase::OutputType type)
{
disabledBackendTypes.insert(type);
}
-bool mbilog::IsBackendEnabled(OutputType type)
+bool mitk::IsBackendEnabled(LogBackendBase::OutputType type)
{
return disabledBackendTypes.find(type) == disabledBackendTypes.end();
}
diff --git a/Utilities/mbilog/mbilogBackendBase.cpp b/Modules/Log/src/mitkLogBackendBase.cpp
similarity index 84%
rename from Utilities/mbilog/mbilogBackendBase.cpp
rename to Modules/Log/src/mitkLogBackendBase.cpp
index 3ac534e66a..8d4ea0e874 100644
--- a/Utilities/mbilog/mbilogBackendBase.cpp
+++ b/Modules/Log/src/mitkLogBackendBase.cpp
@@ -1,17 +1,17 @@
/*============================================================================
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 "mbilogBackendBase.h"
+#include <mitkLogBackendBase.h>
-mbilog::BackendBase::~BackendBase()
+mitk::LogBackendBase::~LogBackendBase()
{
}
diff --git a/Modules/Log/src/mitkLogBackendCout.cpp b/Modules/Log/src/mitkLogBackendCout.cpp
new file mode 100644
index 0000000000..9d123061a8
--- /dev/null
+++ b/Modules/Log/src/mitkLogBackendCout.cpp
@@ -0,0 +1,44 @@
+/*============================================================================
+
+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 <mitkLogBackendCout.h>
+
+mitk::LogBackendCout::LogBackendCout()
+ : m_UseFullOutput(false)
+{
+}
+
+mitk::LogBackendCout::~LogBackendCout()
+{
+}
+
+void mitk::LogBackendCout::SetFull(bool full)
+{
+ m_UseFullOutput = full;
+}
+
+void mitk::LogBackendCout::ProcessMessage(const LogMessage& message)
+{
+ if (m_UseFullOutput)
+ {
+ this->FormatFull(message);
+ }
+ else
+ {
+ this->FormatSmart(message);
+ }
+}
+
+mitk::LogBackendCout::OutputType mitk::LogBackendCout::GetOutputType() const
+{
+ return OutputType::Console;
+}
diff --git a/Utilities/mbilog/mbilogTextBackendBase.cpp b/Modules/Log/src/mitkLogBackendText.cpp
similarity index 80%
rename from Utilities/mbilog/mbilogTextBackendBase.cpp
rename to Modules/Log/src/mitkLogBackendText.cpp
index 1d33c1cd7a..1a49f3f7f7 100644
--- a/Utilities/mbilog/mbilogTextBackendBase.cpp
+++ b/Modules/Log/src/mitkLogBackendText.cpp
@@ -1,623 +1,610 @@
/*============================================================================
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 "mbilogTextBackendBase.h"
-#include "mbilogLoggingTypes.h"
+#include <mitkLogBackendText.h>
+#include <mitkLogLevel.h>
+
#include <ctime>
#include <iomanip>
#include <iostream>
#include <vector>
#ifdef _WIN32
-#define USE_WIN32COLOREDCONSOLE
-#include <windows.h>
-#include "mbilogTextDictionary.h"
+#define MITK_WIN32_CONSOLE_COLOR
+#include <Windows.h>
+#include "mitkLogDictionary.h"
#endif
static bool g_init = false;
-mbilog::TextBackendBase::~TextBackendBase()
+mitk::LogBackendText::~LogBackendText()
{
}
-#ifdef USE_WIN32COLOREDCONSOLE
+#ifdef MITK_WIN32_CONSOLE_COLOR
static HANDLE g_hConsole;
class AutoCategorize
{
protected:
std::vector<std::string> path;
std::string current, category;
int pos;
void flush()
{
if (current.size() > 0)
{
if (current.compare("..") == 0)
{
if (path.size() > 0)
path.pop_back();
}
else
{
path.push_back(current);
}
current = "";
}
}
std::string simplify(std::string x)
{
bool redo;
std::string lft(""), rgt("");
do
{
redo = false;
- for (int r = 0; r < sizeof(mbilog::replace) / sizeof(char *); r += 2)
+ for (int r = 0; r < sizeof(mitk::replace) / sizeof(char *); r += 2)
{
- int s = static_cast<int>(strlen(mbilog::replace[r]));
+ int s = static_cast<int>(strlen(mitk::replace[r]));
int xs = static_cast<int>(x.size());
if (xs == s)
{
- if (mbilog::replace[r + 1][0] || !lft.empty() || !rgt.empty())
- if (x.compare(mbilog::replace[r]) == 0)
- x = mbilog::replace[r + 1];
+ if (mitk::replace[r + 1][0] || !lft.empty() || !rgt.empty())
+ if (x.compare(mitk::replace[r]) == 0)
+ x = mitk::replace[r + 1];
}
else if (xs > s)
{
- if (strncmp(mbilog::replace[r], &x.c_str()[xs - s], s) == 0)
+ if (strncmp(mitk::replace[r], &x.c_str()[xs - s], s) == 0)
{
- std::string rp = mbilog::replace[r + 1];
+ std::string rp = mitk::replace[r + 1];
if (!rp.empty())
rp[0] = toupper(rp[0]);
x = x.substr(0, xs - s);
rgt = rp + rgt;
redo = true;
}
- else if (strncmp(mbilog::replace[r], x.c_str(), s) == 0)
+ else if (strncmp(mitk::replace[r], x.c_str(), s) == 0)
{
- std::string rp = mbilog::replace[r + 1];
+ std::string rp = mitk::replace[r + 1];
if (!rp.empty())
rp[0] = toupper(rp[0]);
x = x.substr(s, xs - s);
lft = lft + rp;
redo = true;
}
}
}
} while (redo);
x[0] = toupper(x[0]);
x = lft + x + rgt;
x[0] = tolower(x[0]);
return x;
}
std::string concat(std::string a, std::string b, bool opt)
{
int as = static_cast<int>(a.size());
int bs = static_cast<int>(b.size());
if (opt && as <= bs)
{
if (as == bs && a.compare(b) == 0)
return a;
if (strncmp(a.c_str(), b.c_str(), as) == 0)
{
b = b.substr(as, bs - as);
b[0] = tolower(b[0]);
}
}
return a + "." + b;
}
bool search2p2(char *a, char *b, bool optimize = true)
{
int size = static_cast<int>(path.size()) - 3;
for (int r = 0; r < size; r++)
if (path[r].compare(a) == 0 && path[r + 1].compare(b) == 0)
{
pos = r + 2;
category = concat(simplify(path[pos]), simplify(path[path.size() - 1]), optimize);
return true;
}
return false;
}
bool search2p1(char *a, char *b)
{
int size = static_cast<int>(path.size()) - 2;
for (int r = 0; r < size; r++)
if (path[r].compare(a) == 0 && path[r + 1].compare(b) == 0)
{
pos = r + 2;
category = simplify(path[path.size() - 1]);
return true;
}
return false;
}
bool search1p2(char *a, bool optimize = true)
{
int size = static_cast<int>(path.size()) - 2;
for (int r = 0; r < size; r++)
if (path[r].compare(a) == 0)
{
pos = r + 1;
category = concat(simplify(path[pos]), simplify(path[path.size() - 1]), optimize);
return true;
}
return false;
}
public:
- AutoCategorize(const mbilog::LogMessage &l)
+ AutoCategorize(const mitk::LogMessage &message)
{
- int size = static_cast<int>(strlen(l.filePath));
+ int size = static_cast<int>(message.FilePath.length());
current = "";
for (int r = 0; r < size; r++)
{
- char c = l.filePath[r];
+ char c = message.FilePath[r];
if (c == '\\' || c == '/')
flush();
else
current += tolower(c);
}
flush();
}
std::string GetPrefix()
{
category = "";
if (search2p2("mbi-sb", "core", false))
return "sb.";
if (search2p1("mbi-sb", "q4mitk"))
return "sb.ui.";
if (search2p2("mbi", "applications"))
return "sb.app.";
if (search2p2("mbi-sb", "q4applications"))
return "sb.app.";
if (search2p2("mbi-sb", "utilities"))
return "sb.util.";
if (search2p2("mbi-sb", "bundles"))
return "sb.bun.";
if (search2p2("mbi-sb", "bundlesqt"))
return "sb.bun.";
if (search2p2("mbi", "modules"))
return "sb.mod.";
if (search2p2("mbi-qm", "core", false))
return "qm.";
if (search2p2("mbi-qm", "utilities"))
return "qm.util.";
if (search2p2("modules", "mitkext", false))
return "ext.";
if (search2p1("modules", "qmitkext"))
return "ext.ui.";
if (search2p2("modules", "bundles"))
return "ext.bun.";
if (search2p2("blueberry", "bundles"))
return "blueberry.";
if (search2p2("core", "code", false))
return "core.";
if (search2p1("coreui", "qmitk"))
return "core.ui.";
if (search2p2("coreui", "bundles"))
return "core.bun.";
// following must come last:
if (search1p2("modules"))
return "core.mod.";
if (search1p2("utilities"))
return "core.util.";
if (search1p2("applications"))
return "core.app.";
return "";
}
std::string GetCategory() { return category; }
};
#endif
-void mbilog::TextBackendBase::FormatSmart(std::ostream &out, const LogMessage &l, int /*threadID*/)
+void mitk::LogBackendText::FormatSmart(std::ostream &out, const LogMessage &message, int /*threadID*/)
{
char c_open = '[';
char c_close = ']';
- switch (l.level)
+ switch (message.Level)
{
- case mbilog::Info:
+ case mitk::LogLevel::Info:
break;
- case mbilog::Warn:
+ case mitk::LogLevel::Warn:
c_open = '!';
c_close = '!';
break;
- case mbilog::Error:
+ case mitk::LogLevel::Error:
c_open = '#';
c_close = '#';
break;
- case mbilog::Fatal:
+ case mitk::LogLevel::Fatal:
c_open = '*';
c_close = '*';
break;
- case mbilog::Debug:
+ case mitk::LogLevel::Debug:
c_open = '{';
c_close = '}';
break;
}
out << c_open;
if (!g_init)
{
g_init = true;
AppendTimeStamp(out);
out << std::endl;
}
std::locale C("C");
std::locale originalLocale = out.getloc();
out.imbue(C);
out << std::fixed << std::setprecision(3) << ((double)std::clock()) / CLOCKS_PER_SEC;
out.imbue(originalLocale);
out << c_close << " ";
- if (!l.category.empty())
+ if (!message.Category.empty())
{
- out << "[" << l.category << "] ";
+ out << "[" << message.Category << "] ";
}
- switch (l.level)
+ switch (message.Level)
{
- case mbilog::Info:
+ case mitk::LogLevel::Info:
break;
- case mbilog::Warn:
+ case mitk::LogLevel::Warn:
out << "WARNING: ";
break;
- case mbilog::Error:
+ case mitk::LogLevel::Error:
out << "ERROR: ";
break;
- case mbilog::Fatal:
+ case mitk::LogLevel::Fatal:
out << "FATAL: ";
break;
- case mbilog::Debug:
+ case mitk::LogLevel::Debug:
out << "DEBUG: ";
break;
}
- out << l.message << std::endl;
+ out << message.Message << std::endl;
}
-void mbilog::TextBackendBase::FormatFull(std::ostream &out, const LogMessage &l, int threadID)
+void mitk::LogBackendText::FormatFull(std::ostream &out, const LogMessage &message, int threadID)
{
- switch (l.level)
+ switch (message.Level)
{
- case mbilog::Info:
+ case mitk::LogLevel::Info:
out << "INFO";
break;
- case mbilog::Warn:
+ case mitk::LogLevel::Warn:
out << "WARN";
break;
- case mbilog::Error:
+ case mitk::LogLevel::Error:
out << "ERROR";
break;
- case mbilog::Fatal:
+ case mitk::LogLevel::Fatal:
out << "FATAL";
break;
- case mbilog::Debug:
+ case mitk::LogLevel::Debug:
out << "DEBUG";
break;
}
out << "|";
AppendTimeStamp(out);
out << "|";
+ out << "|" << message.FilePath << "(" << message.LineNumber << ")";
+ out << "|" << message.FunctionName;
+ out << "|" << std::hex << threadID;
+ out << "|" << message.ModuleName;
+ out << "|" << message.Category;
- out << "|" << std::string(l.filePath) << "(" << l.lineNumber << ")";
-
- out << "|" << std::string(l.functionName);
-
- // if(threadID)
- {
- out << "|" << std::hex << threadID;
- }
-
- // if(NA_STRING != l.moduleName)
- {
- out << "|" << std::string(l.moduleName);
- }
-
- // if(!l.category.empty())
- {
- out << "|" << l.category;
- }
-
- out << l.message << std::endl;
+ out << message.Message << std::endl;
}
-void mbilog::TextBackendBase::FormatSmart(const LogMessage &l, int threadID)
+void mitk::LogBackendText::FormatSmart(const LogMessage &l, int threadID)
{
-#ifdef USE_WIN32COLOREDCONSOLE
+#ifdef MITK_WIN32_CONSOLE_COLOR
FormatSmartWindows(l, threadID);
#else
FormatSmart(std::cout, l, threadID);
#endif
}
-void mbilog::TextBackendBase::FormatFull(const LogMessage &l, int threadID)
+void mitk::LogBackendText::FormatFull(const LogMessage &l, int threadID)
{
FormatFull(std::cout, l, threadID);
}
-void mbilog::TextBackendBase::AppendTimeStamp(std::ostream &out)
+void mitk::LogBackendText::AppendTimeStamp(std::ostream &out)
{
time_t rawtime = time(nullptr);
std::string timestring(ctime(&rawtime));
timestring.replace(timestring.length() - 1,
1,
" "); // replace \n by " " (separates date/time from following output of relative time since start)
std::locale C("C");
std::locale originalLocale = out.getloc();
out.imbue(C);
out << timestring;
out.imbue(originalLocale);
}
-#ifdef USE_WIN32COLOREDCONSOLE
+#ifdef MITK_WIN32_CONSOLE_COLOR
// Get the horizontal and vertical screen sizes in pixel
void GetDesktopResolution(int& horizontal, int& vertical)
{
RECT desktop;
// Get a handle to the desktop window
const HWND hDesktop = GetDesktopWindow();
// Get the size of screen to the variable desktop
GetWindowRect(hDesktop, &desktop);
// The top left corner will have coordinates (0,0)
// and the bottom right corner will have coordinates
// (horizontal, vertical)
horizontal = desktop.right;
vertical = desktop.bottom;
}
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
int *Count = (int*)dwData;
(*Count)++;
return TRUE;
}
int GetMonitorCount()
{
int Count = 0;
if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count))
return Count;
return -1;//signals an error
}
-void mbilog::TextBackendBase::FormatSmartWindows(const mbilog::LogMessage &l, int /*threadID*/)
+void mitk::LogBackendText::FormatSmartWindows(const LogMessage &message, int /*threadID*/)
{
int colorNormal = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
int lastColor = colorNormal;
#define ChangeColor(_col) \
{ \
int col = (_col); \
if (lastColor != (col)) \
{ \
SetConsoleTextAttribute(g_hConsole, (col)); \
lastColor = (col); \
} \
}
int colorTime = FOREGROUND_GREEN;
int colorText = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
int colorCat = FOREGROUND_BLUE | FOREGROUND_RED;
bool showColon = true;
bool forceCat = false;
if (!g_init)
{
g_hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
g_init = true;
- std::string title = "mbilog";
+ std::string title = "MITK Log";
SetConsoleTitle(title.c_str());
/* Title rendering
ChangeColor( FOREGROUND_GREEN|FOREGROUND_BLUE|BACKGROUND_BLUE );
std::cout << " <<< " << std::flush;
ChangeColor( FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_BLUE );
std::cout << title << std::flush;
ChangeColor( FOREGROUND_GREEN|FOREGROUND_BLUE|BACKGROUND_BLUE );
std::cout << " >>> " << std::flush;
ChangeColor( colorNormal );
std::cout << std::endl;
*/
// Give out start time
ChangeColor(colorTime);
AppendTimeStamp(std::cout);
std::cout << std::endl;
}
- switch (l.level)
+ switch (message.Level)
{
- case mbilog::Info:
+ case mitk::LogLevel::Info:
break;
- case mbilog::Warn:
+ case mitk::LogLevel::Warn:
colorTime = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
// colorText = FOREGROUND_RED|FOREGROUND_GREEN;
colorCat = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
showColon = false;
forceCat = true;
break;
- case mbilog::Error:
+ case mitk::LogLevel::Error:
colorTime = FOREGROUND_RED | FOREGROUND_INTENSITY;
// colorText = FOREGROUND_RED;
colorCat = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
showColon = false;
forceCat = true;
break;
- case mbilog::Fatal:
+ case mitk::LogLevel::Fatal:
colorTime = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
// colorText = FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_INTENSITY;
colorCat = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
showColon = false;
forceCat = true;
break;
- case mbilog::Debug:
+ case mitk::LogLevel::Debug:
colorTime = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
// colorText |= FOREGROUND_INTENSITY;
showColon = false;
break;
}
ChangeColor(colorTime);
std::locale C("C");
std::locale originalLocale = std::cout.getloc();
std::cout.imbue(C);
std::cout << std::fixed << std::setprecision(2) << ((double)std::clock()) / CLOCKS_PER_SEC << " ";
std::cout.imbue(originalLocale);
// category
{
- AutoCategorize ac(l);
+ AutoCategorize ac(message);
std::string pre = ac.GetPrefix();
std::string cat = ac.GetCategory();
cat = pre + cat;
if (cat.empty())
- cat = l.category;
+ cat = message.Category;
if (!cat.empty())
{
ChangeColor(colorCat);
// static std::string lastCat;
// if(forceCat||lastCat.compare(cat))
{
std::cout << cat << std::flush;
// lastCat = cat;
}
// else
// std::cout << "..." << std::flush;
if (showColon)
{
ChangeColor(FOREGROUND_BLUE | FOREGROUND_INTENSITY);
std::cout << ": " << std::flush;
}
else
std::cout << " ";
}
}
- switch (l.level)
+ switch (message.Level)
{
- case mbilog::Info:
+ case mitk::LogLevel::Info:
break;
- case mbilog::Warn:
+ case mitk::LogLevel::Warn:
ChangeColor(colorTime);
std::cout << "WARNING" << std::flush;
ChangeColor(FOREGROUND_BLUE | FOREGROUND_INTENSITY);
std::cout << ": " << std::flush;
break;
- case mbilog::Error:
+ case mitk::LogLevel::Error:
ChangeColor(colorTime);
std::cout << "ERROR" << std::flush;
ChangeColor(FOREGROUND_BLUE | FOREGROUND_INTENSITY);
std::cout << ": " << std::flush;
break;
- case mbilog::Fatal:
+ case mitk::LogLevel::Fatal:
ChangeColor(colorTime);
std::cout << "FATAL" << std::flush;
ChangeColor(FOREGROUND_BLUE | FOREGROUND_INTENSITY);
std::cout << ": " << std::flush;
break;
- case mbilog::Debug:
+ case mitk::LogLevel::Debug:
ChangeColor(colorTime);
std::cout << "DBG" << std::flush;
ChangeColor(FOREGROUND_BLUE | FOREGROUND_INTENSITY);
std::cout << ": " << std::flush;
break;
}
ChangeColor(colorText);
- std::cout << l.message << std::endl;
+ std::cout << message.Message << std::endl;
ChangeColor(colorNormal);
int monitorCount = GetMonitorCount();
if (monitorCount > 1) {
HWND consoleWindow = GetConsoleWindow();
int horizontal = 0, vertical = 0;
const int verticalSizeOfConsoleWindow = 300;
GetDesktopResolution(horizontal, vertical);
SetWindowPos(consoleWindow, 0, horizontal, vertical/2 - verticalSizeOfConsoleWindow, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
}
#endif
diff --git a/Utilities/mbilog/mbilogTextDictionary.h b/Modules/Log/src/mitkLogDictionary.h
similarity index 99%
rename from Utilities/mbilog/mbilogTextDictionary.h
rename to Modules/Log/src/mitkLogDictionary.h
index f02953ec61..8f9fd206a5 100644
--- a/Utilities/mbilog/mbilogTextDictionary.h
+++ b/Modules/Log/src/mitkLogDictionary.h
@@ -1,416 +1,416 @@
/*============================================================================
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 _MBILOG_TEXTDICTIONARY_H_
-#define _MBILOG_TEXTDICTIONARY_H_
+#ifndef mitkLogDictionary_h
+#define mitkLogDictionary_h
-namespace mbilog
+namespace mitk
{
/** \brief This is a dictionary to replace long names of classes,
* modules, etc. to shorter versions in the console output. */
static const char *replace[] = {".cpp",
"",
".cxx",
"",
".txx",
"",
".h",
"",
".hpp",
"",
".hxx",
"",
".c",
"",
"org.blueberry.",
"",
"org.mitk.gui.qt.",
"",
"org.mitk.",
"",
"qmitk",
"",
"mitk",
"",
"berry",
"",
"itk",
"",
"vtk",
"",
"qt",
"",
"object",
"obj",
"factory",
"fac",
"classes",
"cls",
"plugin",
"plg",
"widget",
"wdgt",
"interface",
"itf",
"service",
"svc",
"register",
"reg",
"perspective",
"prs",
"assessor",
"ase",
"atrophy",
"atr",
"bias",
"bias",
"field",
"fld",
"multi",
"mlt",
"contour",
"cntr",
"tools",
"tls",
"tool",
"tl",
"application",
"app",
"calculate",
"calc",
"subtract",
"sub",
"region",
"reg",
"tumor",
"tum",
"growing",
"grow",
"segmentation",
"seg",
"statistics",
"stat",
"imaging",
"img",
"image",
"img",
"registration",
"reg",
"navigation",
"nav",
"generation",
"gen",
"generator",
"gen",
"vector",
"vec",
"gradient",
"grad",
"flow",
"flow",
"paint",
"pnt",
"brush",
"brsh",
"volumetry",
"vol",
"volume",
"vol",
"mapper",
"map",
"filter",
"flt",
"surface",
"sfc",
"point",
"pnt",
"organ",
"org",
"multiple",
"mlt",
"corrector",
"cor",
"correction",
"cor",
"batch",
"bat",
"window",
"wnd",
"advisor",
"adv",
"editor",
"edt",
"material",
"mat",
"visualization",
"vis",
"measurement",
"mes",
"scene",
"scn",
"serialization",
"ser",
"deserializer",
"dser",
"serializer",
"ser",
"sandbox",
"sb",
"texture",
"tex",
"opengl",
"ogl",
"vessel",
"vsl",
"value",
"val",
"analysis",
"ana",
"patient",
"pat",
"body",
"body",
"diagnosis",
"diag",
"mesh",
"mesh",
"radial",
"rad",
"simple",
"smp",
"algorithms",
"alg",
"controllers",
"con",
"control",
"con",
"interactive",
"ia",
"interactions",
"ia",
"processing",
"pro",
"process",
"pro",
"rendering",
"rnd",
"renderer",
"rnd",
"render",
"rnd",
"datamanagement",
"data",
"management",
"mng",
"manager",
"mng",
"data",
"data",
"anatomy",
"ana",
"neuro",
"neo",
"automatic",
"auto",
"optimizer",
"opt",
"optimize",
"opt",
"binary",
"bin",
"liver",
"liv",
"lymph",
"lym",
"node",
"node",
"tree",
"tree",
"homogeneous",
"hmgn",
"threshold",
"tsh",
"based",
"bsd",
"shape",
"shp",
"model",
"mdl",
"extension",
"ext",
"activator",
"act",
"dicom",
"dicom",
"browser",
"brwr",
"viewer",
"view",
"view",
"view",
"finder",
"fnd",
"indexer",
"idx",
"index",
"idx",
"rapid",
"rpd",
"gui",
"gui",
"slices",
"slc",
"slice",
"slc",
"about",
"abt",
"interpolator",
"inp",
"switcher",
"swh",
"planarfigure",
"pfig",
"planning",
"plan",
"planner",
"plan",
"plane",
"pln",
"plan",
"plan",
"label",
"lbl",
"geometry",
"geom",
"workbench",
"wrkbnc",
"common",
"com",
"resection",
"rsc",
"translation",
"trnsl",
"rotation",
"rot",
"deformation",
"dfrm",
"shader",
"shd",
"repository",
"rep",
"initializer",
"init",
"dialog",
"dlg",
"download",
"down",
"upload",
"up",
"core",
"core",
"manual",
"man",
"leaf",
"leaf",
"internal",
"int",
"external",
"ext",
"platform",
"pltfm",
"method",
"mthd",
"pyramidal",
"prmdl",
"tracking",
"trck",
"track",
"trck",
"bspline",
"bspl",
"spline",
"spl",
"create",
"crt",
"erase",
"ers",
"auto",
"auto",
"crop",
"crop",
"file",
"file",
"io",
"io",
"2d",
"2d",
"3d",
"3d",
".",
"."};
}
#endif
diff --git a/Modules/Classification/DataCollection/Testing/mitkDataCollectionReaderWriterTest.cpp b/Modules/Log/src/mitkLogMessage.cpp
similarity index 56%
rename from Modules/Classification/DataCollection/Testing/mitkDataCollectionReaderWriterTest.cpp
rename to Modules/Log/src/mitkLogMessage.cpp
index a5249d67ad..51b067be7c 100644
--- a/Modules/Classification/DataCollection/Testing/mitkDataCollectionReaderWriterTest.cpp
+++ b/Modules/Log/src/mitkLogMessage.cpp
@@ -1,19 +1,22 @@
/*============================================================================
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>
-int mitkDataCollectionReaderWriterTest(int argc, char* argv[])
+#include <mitkLogMessage.h>
+
+mitk::LogMessage::LogMessage(const LogLevel level, const std::string& filePath, const int lineNumber,
+ const std::string& functionName)
+ : Level(level),
+ FilePath(filePath),
+ LineNumber(lineNumber),
+ FunctionName(functionName)
{
- MITK_TEST_BEGIN("mitkDataCollectionReaderWriterTest");
- MITK_TEST_CONDITION_REQUIRED(true,"Here we test our condition");
- MITK_TEST_END();
}
diff --git a/Modules/MatchPointRegistration/CMakeLists.txt b/Modules/MatchPointRegistration/CMakeLists.txt
index 4be5284265..50eae7426e 100644
--- a/Modules/MatchPointRegistration/CMakeLists.txt
+++ b/Modules/MatchPointRegistration/CMakeLists.txt
@@ -1,29 +1,30 @@
mitk_create_module(
INCLUDE_DIRS
PUBLIC algorithms
PRIVATE src/Helper src/Rendering
DEPENDS MitkCore MitkSceneSerializationBase MitkMultilabel
PACKAGE_DEPENDS
PUBLIC MatchPoint
PRIVATE VTK|ImagingGeneral+ImagingHybrid
)
+if(BUILD_TESTING)
+ add_subdirectory(Testing)
+endif()
+add_subdirectory(autoload/IO)
+add_subdirectory(cmdapps)
+
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()
- add_subdirectory(autoload/IO)
add_subdirectory(deployment)
- if(BUILD_TESTING)
- add_subdirectory(Testing)
- endif()
- add_subdirectory(cmdapps)
endif()
diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h
new file mode 100644
index 0000000000..64661706e1
--- /dev/null
+++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h
@@ -0,0 +1,28 @@
+/*============================================================================
+
+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 mitkMultiModalRigidHeadNeckRegistrationAlgorithm_h
+#define mitkMultiModalRigidHeadNeckRegistrationAlgorithm_h
+
+#include <mapDiscreteElements.h>
+#include <mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h>
+#include <mapConfigure.h>
+
+#include <mitkMultiModalRigidHeadNeckRegistrationAlgorithm_ProfileResource.h>
+
+namespace mitk
+{
+ template <class TImageType>
+ using MultiModalRigidHeadNeckRegistrationAlgorithm = typename map::algorithm::boxed::MultiModalRigidHeadNeckRegistrationAlgorithm<TImageType, ::map::algorithm::mitkMultiModalRigidHeadNeckRegistrationAlgorithmUIDPolicy>;
+}
+
+#endif
diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.profile b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.profile
new file mode 100644
index 0000000000..eccff83a0d
--- /dev/null
+++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidHeadNeckRegistrationAlgorithm.profile
@@ -0,0 +1,20 @@
+SET(ALGORITHM_PROFILE_UID_Namespace "org.mitk")
+SET(ALGORITHM_PROFILE_UID_Name "MultiModal.rigid.Head2HeadNeck")
+SET(ALGORITHM_PROFILE_UID_Version "1.0.0")
+
+SET(ALGORITHM_PROFILE_Description "Algorithm is used for special cases where a head image and a head neck image (assumed to be the larger image in z direction) should be registered. It skips the lower part of the head neck image if a preinitialization (via geometric center or centroid) is used, to establish a better initialization. By default initializes via geometric centers.")
+SET(ALGORITHM_PROFILE_Contact "Ralf Floca\; mitk-users@lists.sourceforge.net")
+
+SET(ALGORITHM_PROFILE_DataType "Image")
+SET(ALGORITHM_PROFILE_ResolutionStyle "3 (multi res)")
+SET(ALGORITHM_PROFILE_DimMoving "3")
+SET(ALGORITHM_PROFILE_ModalityMoving "MR" "any")
+SET(ALGORITHM_PROFILE_DimTarget "3")
+SET(ALGORITHM_PROFILE_ModalityTarget "MR" "any")
+SET(ALGORITHM_PROFILE_Subject "any")
+SET(ALGORITHM_PROFILE_Object "Head" "Head/Neck")
+SET(ALGORITHM_PROFILE_TransformModel "rigid")
+SET(ALGORITHM_PROFILE_Metric "Mattes mutual information")
+SET(ALGORITHM_PROFILE_TransformDomain "global")
+SET(ALGORITHM_PROFILE_Optimization "Regular Step Gradient Descent")
+SET(ALGORITHM_PROFILE_Keywords "basic" "pre initialization" "Head/Neck" "HeadNeck" "multimodal" "rigid")
diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h
new file mode 100644
index 0000000000..71674fe153
--- /dev/null
+++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h
@@ -0,0 +1,28 @@
+/*============================================================================
+
+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 mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm_h
+#define mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm_h
+
+#include <mapDiscreteElements.h>
+#include <mapITKRigid3DMattesMISlabbedHeadRegistrationAlgorithmTemplate.h>
+#include <mapConfigure.h>
+
+#include <mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm_ProfileResource.h>
+
+namespace mitk
+{
+ template <class TImageType>
+ using MultiModalRigidSlabbedHeadRegistrationAlgorithm = typename map::algorithm::boxed::MultiModalRigidSlabbedHeadRegistrationAlgorithm<TImageType, ::map::algorithm::mitkMultiModalRigidSlabbedHeadRegistrationAlgorithmUIDPolicy>;
+}
+
+#endif
diff --git a/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.profile b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.profile
new file mode 100644
index 0000000000..4f455fdf68
--- /dev/null
+++ b/Modules/MatchPointRegistration/algorithms/mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.profile
@@ -0,0 +1,20 @@
+SET(ALGORITHM_PROFILE_UID_Namespace "org.mitk")
+SET(ALGORITHM_PROFILE_UID_Name "MultiModal.rigid.slabbedHead")
+SET(ALGORITHM_PROFILE_UID_Version "1.0.0")
+
+SET(ALGORITHM_PROFILE_Description "Algorithm is used to solve a special case of head registration problems. It is configured to register the slabbed MRI head data (thus data where only a part of the head is visible) onto whole Head images (e.g.CT planning data). Differenz to the default rigid algorithm is that this algorithms is very defensive with rotating out of the slice plan (so roll or pitch). Uses 3 Resolution levels. By default initializes via image centers.")
+SET(ALGORITHM_PROFILE_Contact "Ralf Floca\; mitk-users@lists.sourceforge.net")
+
+SET(ALGORITHM_PROFILE_DataType "Image")
+SET(ALGORITHM_PROFILE_ResolutionStyle "3 (multi res)")
+SET(ALGORITHM_PROFILE_DimMoving "3")
+SET(ALGORITHM_PROFILE_ModalityMoving "MR" "any")
+SET(ALGORITHM_PROFILE_DimTarget "3")
+SET(ALGORITHM_PROFILE_ModalityTarget "MR" "any")
+SET(ALGORITHM_PROFILE_Subject "any")
+SET(ALGORITHM_PROFILE_Object "Head")
+SET(ALGORITHM_PROFILE_TransformModel "rigid")
+SET(ALGORITHM_PROFILE_Metric "Mattes mutual information")
+SET(ALGORITHM_PROFILE_TransformDomain "global")
+SET(ALGORITHM_PROFILE_Optimization "Regular Step Gradient Descent")
+SET(ALGORITHM_PROFILE_Keywords "basic" "pre initialization" "Head" "slabbed" "partial" "multimodal" "rigid")
diff --git a/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt b/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt
index 272923372e..8fbb245098 100644
--- a/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt
+++ b/Modules/MatchPointRegistration/cmdapps/CMakeLists.txt
@@ -1,32 +1,34 @@
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^^
+ MatchImageMiniApp^^
+ MapImageMiniApp^^
)
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}
)
endforeach()
endif(BUILD_MatchPointCmdApps OR MITK_BUILD_ALL_APPS)
diff --git a/Modules/MatchPointRegistration/cmdapps/MapImageMiniApp.cpp b/Modules/MatchPointRegistration/cmdapps/MapImageMiniApp.cpp
new file mode 100644
index 0000000000..3b57cb5023
--- /dev/null
+++ b/Modules/MatchPointRegistration/cmdapps/MapImageMiniApp.cpp
@@ -0,0 +1,286 @@
+/*============================================================================
+
+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 <string>
+#include <numeric>
+
+// itk includes
+//#include <itksys/SystemTools.hxx>
+
+// CTK includes
+#include <mitkCommandLineParser.h>
+
+// MITK includes
+#include <mitkIOUtil.h>
+#include <mitkPreferenceListReaderOptionsFunctor.h>
+#include <mitkMAPRegistrationWrapper.h>
+#include <mitkMAPAlgorithmHelper.h>
+#include <mitkImageStitchingHelper.h>
+
+struct Settings
+{
+ std::string inFileName = "";
+ std::string regFileName = "";
+ std::string outFileName = "";
+ std::string refGeometryFileName = "";
+
+ mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear;
+ double paddingValue = 0;
+ std::vector<unsigned int> superSamplingFactors;
+};
+
+void setupParser(mitkCommandLineParser& parser)
+{
+ // set general information about your MiniApp
+ parser.setCategory("Registration Tools");
+ parser.setTitle("Map Image");
+ parser.setDescription("MiniApp that allows to map a image into a given output geometry by using a given registration.");
+ parser.setContributor("MIC, German Cancer Research Center (DKFZ)");
+ //! [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 image", "Path to the input images that should be mapped", us::Any(), false, false, false, mitkCommandLineParser::Input);
+ parser.addArgument("output",
+ "o",
+ mitkCommandLineParser::File,
+ "Output file path",
+ "Path to the maped image.",
+ us::Any(),
+ false, false, false, mitkCommandLineParser::Output);
+ parser.endGroup();
+
+ parser.beginGroup("Optional parameters");
+ parser.addArgument(
+ "registration", "r", mitkCommandLineParser::File, "Registration filee", "Path to the registration that should be used. If no registration is specified, an identity transform is assumed.", us::Any(), true, false, false, mitkCommandLineParser::Input);
+ parser.addArgument("template",
+ "t",
+ mitkCommandLineParser::File,
+ "Output template image.",
+ "File path to an image that serves as template for the output geometry. If no template is specified, the geometry of the input image will be used.",
+ 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("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("super-sampling", "s", mitkCommandLineParser::StringList, "Super sampling factor", "Value used for super sampling of the result. E.g. factor 2 will lead to a doubled resolution compared to the used template. If not specified, no super sampling will be done.", us::Any(), true);
+ parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text");
+ parser.endGroup();
+ //! [add arguments]
+}
+
+bool configureApplicationSettings(std::map<std::string, us::Any> parsedArgs, Settings& settings)
+{
+ try
+ {
+ if (parsedArgs.size() == 0)
+ return false;
+
+ settings.inFileName = us::any_cast<std::string>(parsedArgs["input"]);
+ settings.outFileName = us::any_cast<std::string>(parsedArgs["output"]);
+
+ if (parsedArgs.count("template"))
+ {
+ settings.refGeometryFileName = us::any_cast<std::string>(parsedArgs["template"]);
+ }
+
+ if (parsedArgs.count("registration"))
+ {
+ settings.regFileName = us::any_cast<std::string>(parsedArgs["registration"]);
+ }
+
+ if (parsedArgs.count("interpolator"))
+ {
+ auto interpolator = us::any_cast<int>(parsedArgs["interpolator"]);
+ settings.interpolatorType = static_cast<mitk::ImageMappingInterpolator::Type>(interpolator);
+ }
+
+ if (parsedArgs.count("padding"))
+ {
+ settings.paddingValue = us::any_cast<float>(parsedArgs["padding"]);
+ }
+
+ settings.superSamplingFactors.clear();
+ if (parsedArgs.count("super-sampling"))
+ {
+ try
+ {
+ auto samplingStrings = us::any_cast<mitkCommandLineParser::StringContainerType>(parsedArgs["super-sampling"]);
+ if (samplingStrings.size() != 1 && samplingStrings.size() != 3)
+ {
+ std::cerr << "Error. Invalid number of super sampling parameters provided. Either give one (for isometric super sampling) or 3.";
+ return false;
+ }
+
+ for (const auto& samplingstr : samplingStrings)
+ {
+ settings.superSamplingFactors.push_back(std::stoul(samplingstr));
+ }
+ if (settings.superSamplingFactors.size() == 1)
+ {
+ settings.superSamplingFactors.push_back(settings.superSamplingFactors[0]);
+ settings.superSamplingFactors.push_back(settings.superSamplingFactors[0]);
+ }
+ }
+ catch (...)
+ {
+ std::cerr << "Error. Invalid super sampling parameter provided.";
+ throw;
+ }
+ }
+ }
+ catch (...)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char* argv[])
+{
+ mitk::Image::ConstPointer inputImage;
+ mitk::MAPRegistrationWrapper::ConstPointer registration;
+ mitk::BaseGeometry::Pointer refGeometry;
+
+ Settings settings;
+ mitkCommandLineParser parser;
+ setupParser(parser);
+
+ mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (autoselect)" }, { "" });
+
+ const std::map<std::string, us::Any>& parsedArgs = parser.parseArguments(argc, argv);
+ if (!configureApplicationSettings(parsedArgs, settings))
+ {
+ 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;
+ }
+
+ std::cout << std::endl << "*******************************************" << std::endl;
+ std::cout << "Input file: " << settings.inFileName << std::endl;
+ std::cout << "Output file: " << settings.outFileName << std::endl;
+ std::cout << "Registration: ";
+ if (settings.regFileName.empty())
+ std::cout << "None (Identity)" << std::endl;
+ else
+ std::cout << settings.regFileName << std::endl;
+ std::cout << "Template: ";
+ if (settings.refGeometryFileName.empty())
+ std::cout << "None (is input geometry)" << std::endl;
+ else
+ std::cout << settings.refGeometryFileName << std::endl;
+ std::cout << "Padding value: " << settings.paddingValue << std::endl;
+ std::cout << "Interpolation type: " << settings.interpolatorType << std::endl;
+ //check for super/sub sampling
+ if (!settings.superSamplingFactors.empty() && (settings.superSamplingFactors.size() != 1 || settings.superSamplingFactors[0] != 1))
+ {
+ std::cout << "Super sampling:";
+ for (auto value : settings.superSamplingFactors)
+ {
+ std::cout << " " << value;
+ }
+ std::cout << std::endl;
+ }
+ //! [do processing]
+ try
+ {
+ std::cout << "Load input data..." << std::endl;
+ inputImage = mitk::IOUtil::Load<mitk::Image>(settings.inFileName);
+
+ if (inputImage.IsNull())
+ {
+ MITK_ERROR << "Cannot load input image.";
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Load registration..." << std::endl;
+ if (settings.regFileName.empty())
+ {
+ std::cout << " associated registration: identity" << std::endl;
+ registration = mitk::GenerateIdentityRegistration3D().GetPointer();
+ }
+ else
+ {
+ registration = mitk::IOUtil::Load<mitk::MAPRegistrationWrapper>(settings.regFileName);
+ }
+
+ if (registration.IsNull())
+ {
+ MITK_ERROR << "Cannot load registration.";
+ return EXIT_FAILURE;
+ }
+
+ if (settings.refGeometryFileName != "")
+ {
+ std::cout << "Load reference image..." << std::endl;
+ auto refImage = mitk::IOUtil::Load<mitk::Image>(settings.refGeometryFileName, &readerFilterFunctor);
+ if (refImage.IsNotNull())
+ {
+ refGeometry = refImage->GetGeometry();
+ }
+ else
+ {
+ MITK_ERROR << "Cannot load reference geometry image.";
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ refGeometry = inputImage->GetGeometry();
+ }
+
+ //check for super/sub sampling
+ if (!settings.superSamplingFactors.empty() && (settings.superSamplingFactors.size()!=1 || settings.superSamplingFactors[0]!=1))
+ {
+ refGeometry = mitk::ImageMappingHelper::GenerateSuperSampledGeometry(refGeometry,
+ settings.superSamplingFactors[0],
+ settings.superSamplingFactors[1],
+ settings.superSamplingFactors[2]);
+ }
+
+ std::cout << "Map the images ..." << std::endl;
+
+ auto output = mitk::ImageMappingHelper::map(inputImage, registration, false, settings.paddingValue, refGeometry, true, 0, settings.interpolatorType);
+
+ std::cout << "Save output image: " << settings.outFileName << std::endl;
+
+ mitk::IOUtil::Save(output, settings.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/cmdapps/MatchImageMiniApp.cpp b/Modules/MatchPointRegistration/cmdapps/MatchImageMiniApp.cpp
new file mode 100644
index 0000000000..bbcb447ea4
--- /dev/null
+++ b/Modules/MatchPointRegistration/cmdapps/MatchImageMiniApp.cpp
@@ -0,0 +1,318 @@
+/*============================================================================
+
+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 "mitkCommandLineParser.h"
+#include <mitkIOUtil.h>
+#include <mitkPreferenceListReaderOptionsFunctor.h>
+#include <mitkMAPRegistrationWrapper.h>
+#include <mitkMAPAlgorithmHelper.h>
+#include <mitkPointSet.h>
+#include <mitkImageTimeSelector.h>
+
+#include <itkStdStreamLogOutput.h>
+
+// MatchPoint
+#include <mapRegistrationAlgorithmInterface.h>
+#include <mapAlgorithmEvents.h>
+#include <mapAlgorithmWrapperEvent.h>
+#include <mapExceptionObjectMacros.h>
+#include <mapImageRegistrationAlgorithmInterface.h>
+#include <mapPointSetRegistrationAlgorithmInterface.h>
+#include <mapMaskedRegistrationAlgorithmInterface.h>
+#include <mapConvert.h>
+#include <mapDeploymentDLLAccess.h>
+#include <mapDeploymentDLLHandle.h>
+#include <mapRegistrationBase.h>
+
+struct Settings
+{
+ std::string movingFileName = "";
+ std::string targetFileName = "";
+ std::string outFileName = "";
+ std::string algFileName = "";
+};
+
+void SetupParser(mitkCommandLineParser& parser)
+{
+ parser.setTitle("Image Matcher");
+ parser.setCategory("Registration Tools");
+ parser.setDescription("");
+ parser.setContributor("MIC, German Cancer Research Center (DKFZ)");
+
+ parser.setArgumentPrefix("--", "-");
+ // Add command line argument names
+ parser.beginGroup("Required I/O parameters");
+ parser.addArgument(
+ "moving", "m",
+ mitkCommandLineParser::File,
+ "Moving image files", "Path to the data that should be registred into the target space.",
+ us::Any(), false, false, false, mitkCommandLineParser::Input);
+ parser.addArgument(
+ "target", "t",
+ mitkCommandLineParser::File,
+ "Tareget image files", "Path to the data that should be the target data on which the moving data should be registered.",
+ us::Any(), false, false, false, mitkCommandLineParser::Input);
+
+ parser.addArgument(
+ "algorithm", "a",
+ mitkCommandLineParser::File,
+ "Registration algorithm", "Path to the registration algorithm that should be used for registration.",
+ us::Any(), false, false, false, mitkCommandLineParser::Input);
+
+ parser.addArgument("output",
+ "o",
+ mitkCommandLineParser::File,
+ "Output file path",
+ "Path to the generated registration.",
+ 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("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text");
+ parser.endGroup();
+}
+
+bool ConfigureApplicationSettings(std::map<std::string, us::Any> parsedArgs, Settings& settings)
+{
+ try
+ {
+ if (parsedArgs.size() == 0)
+ return false;
+
+ settings.movingFileName = us::any_cast<std::string>(parsedArgs["moving"]);
+ settings.targetFileName = us::any_cast<std::string>(parsedArgs["target"]);
+ settings.outFileName = us::any_cast<std::string>(parsedArgs["output"]);
+ settings.algFileName = us::any_cast<std::string>(parsedArgs["algorithm"]);
+ }
+ catch (...)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+map::deployment::RegistrationAlgorithmBasePointer loadAlgorithm(const Settings& settings)
+{
+ map::deployment::RegistrationAlgorithmBasePointer spAlgorithmBase = nullptr;
+
+ std::cout << std::endl << "Load registration algorithm..." << std::endl;
+
+ map::deployment::DLLHandle::Pointer spHandle = nullptr;
+
+ spHandle = map::deployment::openDeploymentDLL(settings.algFileName);
+
+ if (spHandle.IsNull())
+ {
+ mapDefaultExceptionStaticMacro(<<
+ "Cannot open deployed registration algorithm file.");
+ }
+
+ std::cout << "... libary opened..." << std::endl;
+
+ std::cout << "Algorithm information: " << std::endl;
+ spHandle->getAlgorithmUID().Print(std::cout, 2);
+ std::cout << std::endl;
+
+ //Now load the algorthm from DLL
+ spAlgorithmBase = map::deployment::getRegistrationAlgorithm(spHandle);
+
+
+ if (spAlgorithmBase.IsNotNull())
+ {
+ std::cout << "... done" << std::endl << std::endl;
+ }
+ else
+ {
+ mapDefaultExceptionStaticMacro(<< "Cannot create algorithm instance");
+ }
+ return spAlgorithmBase;
+};
+
+mitk::Image::Pointer ExtractFirstFrame(const mitk::Image* dynamicImage)
+{
+ mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New();
+ imageTimeSelector->SetInput(dynamicImage);
+ imageTimeSelector->SetTimeNr(0);
+ imageTimeSelector->UpdateLargestPossibleRegion();
+
+ return imageTimeSelector->GetOutput();
+}
+
+void OnMapAlgorithmEvent(::itk::Object*, const itk::EventObject& event, void*)
+{
+ const map::events::AlgorithmEvent* pAlgEvent = dynamic_cast<const map::events::AlgorithmEvent*>(&event);
+ const map::events::AlgorithmWrapperEvent* pWrapEvent =
+ dynamic_cast<const map::events::AlgorithmWrapperEvent*>(&event);
+ const map::events::InitializingAlgorithmEvent* pInitEvent =
+ dynamic_cast<const map::events::InitializingAlgorithmEvent*>(&event);
+ const map::events::StartingAlgorithmEvent* pStartEvent =
+ dynamic_cast<const map::events::StartingAlgorithmEvent*>(&event);
+ const map::events::StoppingAlgorithmEvent* pStoppingEvent =
+ dynamic_cast<const map::events::StoppingAlgorithmEvent*>(&event);
+ const map::events::StoppedAlgorithmEvent* pStoppedEvent =
+ dynamic_cast<const map::events::StoppedAlgorithmEvent*>(&event);
+ const map::events::FinalizingAlgorithmEvent* pFinalizingEvent =
+ dynamic_cast<const map::events::FinalizingAlgorithmEvent*>(&event);
+ const map::events::FinalizedAlgorithmEvent* pFinalizedEvent =
+ dynamic_cast<const map::events::FinalizedAlgorithmEvent*>(&event);
+
+ if (pInitEvent)
+ {
+ std::cout <<"Initializing algorithm ..." << std::endl;
+ }
+ else if (pStartEvent)
+ {
+ std::cout <<"Starting algorithm ..." << std::endl;
+ }
+ else if (pStoppingEvent)
+ {
+ std::cout <<"Stopping algorithm ..." << std::endl;
+ }
+ else if (pStoppedEvent)
+ {
+ std::cout <<"Stopped algorithm ..." << std::endl;
+
+ if (!pStoppedEvent->getComment().empty())
+ {
+ std::cout <<"Stopping condition: " << pStoppedEvent->getComment() << std::endl;
+ }
+ }
+ else if (pFinalizingEvent)
+ {
+ std::cout <<"Finalizing algorithm and results ..." << std::endl;
+ }
+ else if (pFinalizedEvent)
+ {
+ std::cout <<"Finalized algorithm ..." << std::endl;
+ }
+ else if (pAlgEvent && !pWrapEvent)
+ {
+ std::cout << pAlgEvent->getComment() << std::endl;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ std::cout << "MitkRegistrationMiniApp - Generic light weight image registration tool based on MatchPoint." << std::endl;
+
+ Settings settings;
+ mitkCommandLineParser parser;
+ SetupParser(parser);
+
+ const std::map<std::string, us::Any>& parsedArgs = parser.parseArguments(argc, argv);
+ if (!ConfigureApplicationSettings(parsedArgs, settings))
+ {
+ 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;
+ }
+
+ std::cout << std::endl << "*******************************************" << std::endl;
+ std::cout << "Moving file: " << settings.movingFileName << std::endl;
+ std::cout << "Target file: " << settings.targetFileName << std::endl;
+ std::cout << "Output file: " << settings.outFileName << std::endl;
+ std::cout << "Algorithm location: " << settings.algFileName << std::endl;
+
+ //load algorithm
+ try
+ {
+ auto algorithm = loadAlgorithm(settings);
+
+ auto command = ::itk::CStyleCommand::New();
+ command->SetCallback(OnMapAlgorithmEvent);
+ algorithm->AddObserver(::map::events::AlgorithmEvent(), command);
+
+ std::cout << "Load moving data..." << std::endl;
+ auto movingImage = mitk::IOUtil::Load<mitk::Image>(settings.movingFileName);
+
+ if (movingImage.IsNull())
+ {
+ MITK_ERROR << "Cannot load moving image.";
+ return EXIT_FAILURE;
+ }
+
+ if (movingImage->GetTimeSteps() > 1)
+ {
+ movingImage = mitk::SelectImageByTimeStep(movingImage, 0)->Clone(); //we have to clone because SelectImageByTimeStep
+ //only generates as new view of the data and we
+ //are overwriting the only smartpointer to the source.
+ std::cout << "Moving image has multiple time steps. Use first time step for registartion." << std::endl;
+ }
+
+ std::cout << "Load target data..." << std::endl;
+ auto targetImage = mitk::IOUtil::Load<mitk::Image>(settings.targetFileName);
+
+ if (targetImage.IsNull())
+ {
+ MITK_ERROR << "Cannot load target image.";
+ return EXIT_FAILURE;
+ }
+
+ if (targetImage->GetTimeSteps() > 1)
+ {
+ targetImage = mitk::SelectImageByTimeStep(targetImage, 0)->Clone(); //we have to clone because SelectImageByTimeStep
+ //only generates as new view of the data and we
+ //are overwriting the only smartpointer to the source.
+ std::cout << "Target image has multiple time steps. Use first time step for registartion." << std::endl;
+ }
+
+ std::cout << "Start registration...." << std::endl;
+ mitk::MAPAlgorithmHelper helper(algorithm);
+ helper.SetData(movingImage, targetImage);
+
+ ::itk::StdStreamLogOutput::Pointer spStreamLogOutput = ::itk::StdStreamLogOutput::New();
+ spStreamLogOutput->SetStream(std::cout);
+ map::core::Logbook::addAdditionalLogOutput(spStreamLogOutput);
+
+ auto registration = helper.GetRegistration();
+
+ // wrap the registration in a data node
+ if (registration.IsNull())
+ {
+ MITK_ERROR << "No valid registration generated";
+ return EXIT_FAILURE;
+ }
+
+ auto regWrapper = mitk::MAPRegistrationWrapper::New(registration);
+ std::cout << "Store registration...." << std::endl;
+ mitk::IOUtil::Save(regWrapper, settings.outFileName);
+ }
+ catch (const std::exception& e)
+ {
+ MITK_ERROR << e.what();
+ return EXIT_FAILURE;
+ }
+ catch (...)
+ {
+ MITK_ERROR << "Unexpected error encountered.";
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp b/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp
index ef8fc82bd2..159d96a34f 100644
--- a/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp
+++ b/Modules/MatchPointRegistration/cmdapps/StitchImagesMiniApp.cpp
@@ -1,226 +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 <string>
#include <numeric>
// itk includes
#include "itksys/SystemTools.hxx"
// CTK includes
#include "mitkCommandLineParser.h"
// MITK includes
#include <mitkIOUtil.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkMAPRegistrationWrapper.h>
#include <mitkMAPAlgorithmHelper.h>
#include <mitkImageStitchingHelper.h>
mitkCommandLineParser::StringContainerType inFilenames;
mitkCommandLineParser::StringContainerType regFilenames;
std::string outFileName;
std::string refGeometryFileName;
std::vector<mitk::Image::ConstPointer> images;
std::vector<mitk::MAPRegistrationWrapper::ConstPointer> 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.setCategory("Registration 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");
+ parser.setContributor("MIC, German Cancer Research Center (DKFZ)");
//! [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<std::string, us::Any> parsedArgs)
{
try
{
if (parsedArgs.size() == 0)
return false;
inFilenames = us::any_cast<mitkCommandLineParser::StringContainerType>(parsedArgs["inputs"]);
outFileName = us::any_cast<std::string>(parsedArgs["output"]);
if (parsedArgs.count("template"))
{
refGeometryFileName = us::any_cast<std::string>(parsedArgs["template"]);
}
if (parsedArgs.count("registrations"))
{
regFilenames = us::any_cast<mitkCommandLineParser::StringContainerType>(parsedArgs["registrations"]);
}
else
{
regFilenames.resize(inFilenames.size());
std::fill(regFilenames.begin(), regFilenames.end(), "");
}
if (parsedArgs.count("interpolator"))
{
auto interpolator = us::any_cast<int>(parsedArgs["interpolator"]);
interpolatorType = static_cast<mitk::ImageMappingInterpolator::Type>(interpolator);
}
if (parsedArgs.count("padding"))
{
paddingValue = us::any_cast<float>(parsedArgs["padding"]);
}
if (parsedArgs.count("strategy"))
{
auto temp = us::any_cast<int>(parsedArgs["strategy"]);
stitchStratgy = static_cast<itk::StitchStrategy>(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<std::string, us::Any>& 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 << "#"<<index<<" " << path << std::endl;
auto image = mitk::IOUtil::Load<mitk::Image>(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<mitk::MAPRegistrationWrapper>(regFilenames[index]);
registrations.push_back(reg.GetPointer());
}
++index;
}
std::cout << "Reference image: " << refGeometryFileName << std::endl << std::endl;
auto refImage = mitk::IOUtil::Load<mitk::Image>(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/deployment/CMakeLists.txt b/Modules/MatchPointRegistration/deployment/CMakeLists.txt
index 120526bfa0..b0a51b1ce6 100644
--- a/Modules/MatchPointRegistration/deployment/CMakeLists.txt
+++ b/Modules/MatchPointRegistration/deployment/CMakeLists.txt
@@ -1,8 +1,10 @@
set(MDRA_INCLUDE_DIRS PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../algorithms)
mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_affine_default CPP_FILES mitkMultiModalAffine_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_rigid_default CPP_FILES mitkMultiModalRigid_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
+mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_rigid_headNeck CPP_FILES mitkMultiModalRigid_headNeck.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
+mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_rigid_slabbedHead CPP_FILES mitkMultiModalRigid_slabbedHead.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_MultiModal_translation_default CPP_FILES mitkMultiModalTrans_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_Rigid_closedform_points_default CPP_FILES mitkRigidClosedFormPoints_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_Rigid_ICP_default CPP_FILES mitkRigidICP_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_FastSymmetricForcesDemons_MultiRes_default CPP_FILES mitkFastSymmetricForcesDemonsMultiRes_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
mitkFunctionCreateMatchPointDeployedAlgorithm(NAME MITK_LevelSetMotion_MultiRes_default CPP_FILES mitkLevelSetMotionMultiRes_default.cpp NO_PROFILE_GEN INCLUDE_DIRS ${MDRA_INCLUDE_DIRS})
diff --git a/Modules/Core/include/mitkLogMacros.h b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_headNeck.cpp
similarity index 54%
copy from Modules/Core/include/mitkLogMacros.h
copy to Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_headNeck.cpp
index 8ed99172df..86791c6458 100644
--- a/Modules/Core/include/mitkLogMacros.h
+++ b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_headNeck.cpp
@@ -1,24 +1,21 @@
/*============================================================================
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 mitkLogMacros_h
-#define mitkLogMacros_h
+#include "mapDeploymentDLLHelper.h"
+#include "mapDiscreteElements.h"
+#include "mapConfigure.h"
-#include <mbilog.h>
+#include "mitkMultiModalRigidHeadNeckRegistrationAlgorithm.h"
-#define MITK_INFO MBI_INFO
-#define MITK_WARN MBI_WARN
-#define MITK_ERROR MBI_ERROR
-#define MITK_FATAL MBI_FATAL
-#define MITK_DEBUG MBI_DEBUG
+typedef map::core::discrete::Elements<3>::InternalImageType ImageType;
-#endif
+mapDeployAlgorithmMacro(mitk::MultiModalRigidHeadNeckRegistrationAlgorithm<ImageType>);
diff --git a/Modules/Core/include/mitkLogMacros.h b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_slabbedHead.cpp
similarity index 54%
copy from Modules/Core/include/mitkLogMacros.h
copy to Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_slabbedHead.cpp
index 8ed99172df..eaee90756c 100644
--- a/Modules/Core/include/mitkLogMacros.h
+++ b/Modules/MatchPointRegistration/deployment/mitkMultiModalRigid_slabbedHead.cpp
@@ -1,24 +1,21 @@
/*============================================================================
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 mitkLogMacros_h
-#define mitkLogMacros_h
+#include "mapDeploymentDLLHelper.h"
+#include "mapDiscreteElements.h"
+#include "mapConfigure.h"
-#include <mbilog.h>
+#include "mitkMultiModalRigidSlabbedHeadRegistrationAlgorithm.h"
-#define MITK_INFO MBI_INFO
-#define MITK_WARN MBI_WARN
-#define MITK_ERROR MBI_ERROR
-#define MITK_FATAL MBI_FATAL
-#define MITK_DEBUG MBI_DEBUG
+typedef map::core::discrete::Elements<3>::InternalImageType ImageType;
-#endif
+mapDeployAlgorithmMacro(mitk::MultiModalRigidSlabbedHeadRegistrationAlgorithm<ImageType>);
diff --git a/Modules/MatchPointRegistration/include/mitkImageMappingHelper.h b/Modules/MatchPointRegistration/include/mitkImageMappingHelper.h
index 82cc725c29..7cceb311f5 100644
--- a/Modules/MatchPointRegistration/include/mitkImageMappingHelper.h
+++ b/Modules/MatchPointRegistration/include/mitkImageMappingHelper.h
@@ -1,113 +1,116 @@
/*============================================================================
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 mitkImageMappingHelper_h
#define mitkImageMappingHelper_h
#include "mapImageMappingTask.h"
#include "mapRegistrationBase.h"
#include "mitkImage.h"
#include "mitkGeometry3D.h"
#include "mitkMAPRegistrationWrapper.h"
#include "MitkMatchPointRegistrationExports.h"
namespace mitk
{
struct ImageMappingInterpolator
{
enum Type
{
UserDefined = 0, //< User may specify the interpolator to use
NearestNeighbor = 1, //< use nearest neighbor
Linear = 2, //< use linear
BSpline_3 = 3, //< use a 3rd order spline
WSinc_Hamming = 4, //< use a wsinc with hamming window
WSinc_Welch = 5 //< use a wsinc with welch window
};
};
namespace ImageMappingHelper
{
typedef ::map::core::RegistrationBase RegistrationType;
typedef ::mitk::MAPRegistrationWrapper MITKRegistrationType;
typedef ::mitk::BaseGeometry ResultImageGeometryType;
typedef ::mitk::Image InputImageType;
typedef ::mitk::Image ResultImageType;
/**Helper that maps a given input image
* @param input Image that should be mapped.
* @param registration Pointer to the registration instance that should be used for mapping
* @param throwOnOutOfInputAreaError Indicates if mapping should fail with an exception (true), if the input image does not cover the whole requested region to be mapped into the result image.
* @param paddingValue Indicates the value that should be used if an out of input error occurs (and throwOnOutOfInputAreaError is false).
* @param resultGeometry Pointer to the Geometry object that specifies the grid of the result image. If not defined the geometry of the input image will be used.
* @param throwOnMappingError Indicates if mapping should fail with an exception (true), if the registration does not cover/support the whole requested region for mapping into the result image.
* @param errorValue Indicates the value that should be used if an mapping error occurs (and throwOnMappingError is false).
* @param interpolatorType Indicates the type of interpolation strategy that should be used.
* @pre input must be valid
* @pre registration must be valid
* @pre Dimensionality of the registration must match with the input imageinput must be valid
* @remark Depending in the settings of throwOnOutOfInputAreaError and throwOnMappingError it may also throw
* due to inconsistencies in the mapping process. See parameter description.
* @result Pointer to the resulting mapped image.h*/
MITKMATCHPOINTREGISTRATION_EXPORT ResultImageType::Pointer map(const InputImageType* input, const RegistrationType* registration,
bool throwOnOutOfInputAreaError = false, const double& paddingValue = 0,
const ResultImageGeometryType* resultGeometry = nullptr,
bool throwOnMappingError = true, const double& errorValue = 0, mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear);
/**Helper that maps a given input image.
* @overload
* @param input Image that should be mapped.
* @param registration Pointer to the registration instance that should be used for mapping
* @param throwOnOutOfInputAreaError Indicates if mapping should fail with an exception (true), if the input image does not cover the whole requested region to be mapped into the result image.
* @param paddingValue Indicates the value that should be used if an out of input error occurs (and throwOnOutOfInputAreaError is false).
* @param resultGeometry Pointer to the Geometry object that specifies the grid of the result image. If not defined the geometry of the input image will be used.
* @param throwOnMappingError Indicates if mapping should fail with an exception (true), if the registration does not cover/support the whole requested region for mapping into the result image.
* @param errorValue Indicates the value that should be used if an mapping error occurs (and throwOnMappingError is false).
* @param interpolatorType Indicates the type of interpolation strategy that should be used.
* @pre input must be valid
* @pre registration must be valid
* @pre Dimensionality of the registration must match with the input imageinput must be valid
* @remark Depending in the settings of throwOnOutOfInputAreaError and throwOnMappingError it may also throw
* due to inconsistencies in the mapping process. See parameter description.
* @result Pointer to the resulting mapped image.h*/
MITKMATCHPOINTREGISTRATION_EXPORT ResultImageType::Pointer map(const InputImageType* input, const MITKRegistrationType* registration,
bool throwOnOutOfInputAreaError = false, const double& paddingValue = 0,
const ResultImageGeometryType* resultGeometry = nullptr,
bool throwOnMappingError = true, const double& errorValue = 0, mitk::ImageMappingInterpolator::Type interpolatorType = mitk::ImageMappingInterpolator::Linear);
+ MITKMATCHPOINTREGISTRATION_EXPORT ResultImageGeometryType::Pointer GenerateSuperSampledGeometry(const ResultImageGeometryType* inputGeometry,
+ double xScaling, double yScaling, double zScaling);
+
/**Method clones the input image and applies the registration by applying it to the Geometry3D of the image.
Thus this method only produces a result if the passed registration has an direct mapping kernel that
can be converted into an affine matrix transformation.
@pre input must point to a valid instance
@pre registration must point to a valid instance
@pre registration must be decomposable into rotation matrix and offset or throwOnError must be false.
@result Pointer to the result image with refined geometry. May be null if the result cannot be
generated (e.g. the registration cannot be transformed in a affine matrix transformation)*/
MITKMATCHPOINTREGISTRATION_EXPORT ResultImageType::Pointer refineGeometry(const InputImageType* input, const RegistrationType* registration, bool throwOnError = true);
/**@overload*/
MITKMATCHPOINTREGISTRATION_EXPORT ResultImageType::Pointer refineGeometry(const InputImageType* input, const MITKRegistrationType* registration, bool throwOnError = true);
/**Method allows to pre checks if a registration could be used with refineGeometry. If this method returns true,
* the registration can be used to refine the geometry of images.*/
MITKMATCHPOINTREGISTRATION_EXPORT bool canRefineGeometry(const RegistrationType* registration);
/**@overload*/
MITKMATCHPOINTREGISTRATION_EXPORT bool canRefineGeometry(const MITKRegistrationType* registration);
}
}
#endif
diff --git a/Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapper.h b/Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapper.h
index d6006eb44e..b3460d25c7 100644
--- a/Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapper.h
+++ b/Modules/MatchPointRegistration/include/mitkMAPRegistrationWrapper.h
@@ -1,269 +1,273 @@
/*============================================================================
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 mitkMAPRegistrationWrapper_h
#define mitkMAPRegistrationWrapper_h
//MITK
#include <mitkBaseData.h>
#include <mitkGeometry3D.h>
//MatchPoint
#include <mapRegistrationBase.h>
#include <mapRegistration.h>
#include <mapExceptionObjectMacros.h>
#include <mapContinuousElements.h>
//MITK
#include "MitkMatchPointRegistrationExports.h"
namespace mitk
{
/*!
\brief MAPRegistrationWrapper
Wrapper class to allow the handling of MatchPoint registration objects as mitk data (e.g. in the data explorer).
*/
class MITKMATCHPOINTREGISTRATION_EXPORT MAPRegistrationWrapper: public mitk::BaseData
{
public:
mitkClassMacro( MAPRegistrationWrapper, BaseData );
mitkNewMacro1Param( Self, ::map::core::RegistrationBase*);
Identifiable::UIDType GetUID() const override;
+ bool IsEmptyTimeStep(unsigned int t) const override;
+
+ bool IsEmpty() const override;
+
/**
* Empty implementation, since the MAPRegistrationWrapper doesn't
* support the requested region concept
*/
void SetRequestedRegionToLargestPossibleRegion() override;
/**
* Empty implementation, since the MAPRegistrationWrapper doesn't
* support the requested region concept
*/
bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
/**
* Empty implementation, since the MAPRegistrationWrapper doesn't
* support the requested region concept
*/
bool VerifyRequestedRegion() override;
/**
* Empty implementation, since the MAPRegistrationWrapper doesn't
* support the requested region concept
*/
void SetRequestedRegion(const itk::DataObject*) override;
/*! @brief Gets the number of moving dimensions
@pre valid registration instance must be set.
*/
virtual unsigned int GetMovingDimensions() const;
/*! @brief Gets the number of target dimensions
@pre valid registration instance must be set.
*/
virtual unsigned int GetTargetDimensions() const;
/*! typedefs used for the TagMap
*/
typedef ::map::core::RegistrationBase::TagType TagType;
typedef ::map::core::RegistrationBase::ValueType ValueType;
typedef ::map::core::RegistrationBase::TagMapType TagMapType;
/*! @brief returns the tags associated with this registration
@pre valid registration instance must be set.
@return a TagMapType containing tags
*/
const TagMapType& GetTags() const;
/*! @brief returns the tag value for a specific tag
@pre valid registration instance must be set.
@return the success of the operation
*/
bool GetTagValue(const TagType & tag, ValueType & value) const;
/*! Indicates
@pre valid registration instance must be set.
@return is the target representation limited
@retval true if target representation is limited. Thus it is not guaranteed that all inverse mapping operations
will succeed. Transformation(inverse kernel) covers only a part of the target space).
@retval false if target representation is not limited. Thus it is guaranteed that all inverse mapping operations
will succeed.
*/
bool HasLimitedTargetRepresentation() const;
/*!
@pre valid registration instance must be set.
@return is the moving representation limited
@retval true if moving representation is limited. Thus it is not guaranteed that all direct mapping operations
will succeed. Transformation(direct kernel) covers only a part of the moving space).
@retval false if moving representation is not limited. Thus it is guaranteed that all direct mapping operations
will succeed.
*/
bool HasLimitedMovingRepresentation() const;
/*! Helper function that maps a mitk point (of arbitrary dimension) from moving space to target space.
@remarks The operation might fail, if the moving and target dimension of the registration
is not equal to the dimensionality of the passed points.
@pre valid registration instance must be set.
@param inPoint Reference pointer to a MovingPointType
@param outPoint pointer to a TargetPointType
@return success of operation.
@pre direct mapping kernel must be defined
*/
template <unsigned int VMovingDim, unsigned int VTargetDim>
bool MapPoint(const ::itk::Point<mitk::ScalarType,VMovingDim>& inPoint, ::itk::Point<mitk::ScalarType,VTargetDim>& outPoint) const
{
typedef typename ::map::core::continuous::Elements<VMovingDim>::PointType MAPMovingPointType;
typedef typename ::map::core::continuous::Elements<VTargetDim>::PointType MAPTargetPointType;
if (m_spRegistration.IsNull())
{
mapDefaultExceptionMacro(<< "Error. Cannot map point. Wrapper points to invalid registration (nullptr). Point: " << inPoint);
}
bool result = false;
if ((this->GetMovingDimensions() == VMovingDim)&&(this->GetTargetDimensions() == VTargetDim))
{
MAPMovingPointType tempInP;
MAPTargetPointType tempOutP;
tempInP.CastFrom(inPoint);
typedef ::map::core::Registration<VMovingDim,VTargetDim> CastedRegType;
const CastedRegType* pCastedReg = dynamic_cast<const CastedRegType*>(m_spRegistration.GetPointer());
if (!pCastedReg)
{
mapDefaultExceptionMacro(<< "Error. Cannot map point. Registration has invalid dimension. Point: " << inPoint);
}
result = pCastedReg->mapPoint(tempInP,tempOutP);
if (result)
{
outPoint.CastFrom(tempOutP);
}
}
return result;
};
/*! Helper function that maps a mitk point (of arbitrary dimension) from target space to moving space
@remarks The operation might faile, if the moving and target dimension of the registration
is not equal to the dimensionalities of the passed points.
@pre valid registration instance must be set.
@param inPoint pointer to a TargetPointType
@param outPoint pointer to a MovingPointType
@return success of operation
*/
template <unsigned int VMovingDim, unsigned int VTargetDim>
bool MapPointInverse(const ::itk::Point<mitk::ScalarType,VTargetDim> & inPoint, ::itk::Point<mitk::ScalarType,VMovingDim> & outPoint) const
{
typedef typename ::map::core::continuous::Elements<VMovingDim>::PointType MAPMovingPointType;
typedef typename ::map::core::continuous::Elements<VTargetDim>::PointType MAPTargetPointType;
if (m_spRegistration.IsNull())
{
mapDefaultExceptionMacro(<< "Error. Cannot map point. Wrapper points to invalid registration (nullptr). Point: " << inPoint);
}
bool result = false;
if ((this->GetMovingDimensions() == VMovingDim)&&(this->GetTargetDimensions() == VTargetDim))
{
MAPTargetPointType tempInP;
MAPMovingPointType tempOutP;
tempInP.CastFrom(inPoint);
typedef ::map::core::Registration<VMovingDim,VTargetDim> CastedRegType;
const CastedRegType* pCastedReg = dynamic_cast<const CastedRegType*>(m_spRegistration.GetPointer());
if (!pCastedReg)
{
mapDefaultExceptionMacro(<< "Error. Cannot map point. Registration has invalid dimension. Point: " << inPoint);
}
result = pCastedReg->mapPointInverse(tempInP,tempOutP);
if (result)
{
outPoint.CastFrom(tempOutP);
}
}
return result;
};
/*! returns the direct FieldRepresentationDescriptor which defines the part
of the moving space that is guaranteed to be mapped by the direct mapping kernel.
This member converts the internal MatchPoint type into a mitk::Geometry3D.
@pre valid registration instance must be set.
@return smart pointer to a FieldRepresentationDescriptor for the supported registration space in the moving domain.
May be null if the direct registration kernel is global and thus not limited.
If there is a limitation, the retun value is not nullptr.
@retval nullptr no field representation set/requested by the creating registration algorithm.
*/
mitk::Geometry3D GetDirectFieldRepresentation() const;
/*! returns the inverse FieldRepresentationDescriptor which defines the part
of the target space that is guaranteed to be mapped by the inverse mapping kernel.
This member converts the internal MatchPoint type into a mitk::Geometry3D.
@pre valid registration instance must be set.
@return a const FieldRepresentationDescriptor for the supported registration space in the target domain.
May be null if the inverse registration kernel is global and thus not limited.
If there is a limitation, the retun value is not nullptr.
@retval nullptr no field representation set/requested by the creating registration algorithm.
*/
mitk::Geometry3D GetInverseFieldRepresentation() const;
/*! forces kernel to precompute, even if it is a LazyFieldKernel
@pre valid registration instance must be set.
@todo der LazyFieldBasedRegistrationKernel muss dann die stong guarantee erfllen beim erzeugen des feldes ansonsten
ist die garantie dieser methode nicht erfllbar. noch berprfen
*/
void PrecomputeDirectMapping();
/*! forces kernel to precompute, even if it is a LazyFieldKernel
@pre valid registration instance must be set.
@todo der LazyFieldBasedRegistrationKernel muss dann die stong guarantee erfllen beim erzeugen des feldes ansonsten
ist die garantie dieser methode nicht erfllbar. noch berprfen
*/
void PrecomputeInverseMapping();
::map::core::RegistrationBase* GetRegistration();
const ::map::core::RegistrationBase* GetRegistration() const;
protected:
void PrintSelf (std::ostream &os, itk::Indent indent) const override;
MAPRegistrationWrapper(::map::core::RegistrationBase* registration);
~MAPRegistrationWrapper() override;
void SetUID(const UIDType& uid) override;
::map::core::RegistrationBase::Pointer m_spRegistration;
private:
MAPRegistrationWrapper& operator = (const MAPRegistrationWrapper&);
MAPRegistrationWrapper(const MAPRegistrationWrapper&);
};
}
#endif
diff --git a/Modules/MatchPointRegistration/src/Helper/mitkImageMappingHelper.cpp b/Modules/MatchPointRegistration/src/Helper/mitkImageMappingHelper.cpp
index 1721cdf683..39a9e5f197 100644
--- a/Modules/MatchPointRegistration/src/Helper/mitkImageMappingHelper.cpp
+++ b/Modules/MatchPointRegistration/src/Helper/mitkImageMappingHelper.cpp
@@ -1,444 +1,482 @@
/*============================================================================
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 <itkInterpolateImageFunction.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkBSplineInterpolateImageFunction.h>
#include <itkWindowedSincInterpolateImageFunction.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>
#include <mitkGeometry3D.h>
#include <mitkImageToItk.h>
#include <mitkImageTimeSelector.h>
#include <mitkLabelSetImage.h>
#include "mapRegistration.h"
#include "mitkImageMappingHelper.h"
#include "mitkRegistrationHelper.h"
template <typename TImage >
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<TImage>::New();
break;
}
case mitk::ImageMappingInterpolator::BSpline_3:
{
typename ::itk::BSplineInterpolateImageFunction<TImage>::Pointer spInterpolator = ::itk::BSplineInterpolateImageFunction<TImage>::New();
spInterpolator->SetSplineOrder(3);
result = spInterpolator;
break;
}
case mitk::ImageMappingInterpolator::WSinc_Hamming:
{
result = ::itk::WindowedSincInterpolateImageFunction<TImage,4>::New();
break;
}
case mitk::ImageMappingInterpolator::WSinc_Welch:
{
result = ::itk::WindowedSincInterpolateImageFunction<TImage,4,::itk::Function::WelchWindowFunction<4> >::New();
break;
}
default:
{
result = ::itk::LinearInterpolateImageFunction<TImage>::New();
break;
}
}
return result;
};
template <typename TPixelType, unsigned int VImageDimension >
void doMITKMap(const ::itk::Image<TPixelType,VImageDimension>* input, mitk::ImageMappingHelper::ResultImageType::Pointer& result, const mitk::ImageMappingHelper::RegistrationType*& registration,
bool throwOnOutOfInputAreaError, const double& paddingValue, const mitk::ImageMappingHelper::ResultImageGeometryType*& resultGeometry,
bool throwOnMappingError, const double& errorValue, mitk::ImageMappingInterpolator::Type interpolatorType)
{
typedef ::map::core::Registration<VImageDimension,VImageDimension> ConcreteRegistrationType;
typedef ::map::core::ImageMappingTask<ConcreteRegistrationType, ::itk::Image<TPixelType,VImageDimension>, ::itk::Image<TPixelType,VImageDimension> > MappingTaskType;
typename MappingTaskType::Pointer spTask = MappingTaskType::New();
typedef typename MappingTaskType::ResultImageDescriptorType ResultImageDescriptorType;
typename ResultImageDescriptorType::Pointer resultDescriptor;
//check if image and result geometry fits the passed registration
/////////////////////////////////////////////////////////////////
if (registration->getMovingDimensions()!=VImageDimension)
{
map::core::OStringStream str;
str << "Dimension of MITK image ("<<VImageDimension<<") does not equal the moving dimension of the registration object ("<<registration->getMovingDimensions()<<").";
throw mitk::AccessByItkException(str.str());
}
if (registration->getTargetDimensions()!=VImageDimension)
{
map::core::OStringStream str;
str << "Dimension of MITK image ("<<VImageDimension<<") does not equal the target dimension of the registration object ("<<registration->getTargetDimensions()<<").";
throw mitk::AccessByItkException(str.str());
}
const ConcreteRegistrationType* castedReg = dynamic_cast<const ConcreteRegistrationType*>(registration);
if (registration->getTargetDimensions()==2 && resultGeometry)
{
mitk::ImageMappingHelper::ResultImageGeometryType::BoundsArrayType bounds = resultGeometry->GetBounds();
if (bounds[4]!=0 || bounds[5]!=0)
{
//array "bounds" is constructed as [min Dim1, max Dim1, min Dim2, max Dim2, min Dim3, max Dim3]
//therfore [4] and [5] must be 0
map::core::OStringStream str;
str << "Dimension of defined result geometry does not equal the target dimension of the registration object ("<<registration->getTargetDimensions()<<").";
throw mitk::AccessByItkException(str.str());
}
}
//check/create resultDescriptor
/////////////////////////
if (resultGeometry)
{
resultDescriptor = ResultImageDescriptorType::New();
typename ResultImageDescriptorType::PointType origin;
typename ResultImageDescriptorType::SizeType size;
typename ResultImageDescriptorType::SpacingType fieldSpacing;
typename ResultImageDescriptorType::DirectionType matrix;
mitk::ImageMappingHelper::ResultImageGeometryType::BoundsArrayType geoBounds = resultGeometry->GetBounds();
mitk::Vector3D geoSpacing = resultGeometry->GetSpacing();
mitk::Point3D geoOrigin = resultGeometry->GetOrigin();
mitk::AffineTransform3D::MatrixType geoMatrix = resultGeometry->GetIndexToWorldTransform()->GetMatrix();
for (unsigned int i = 0; i<VImageDimension; ++i)
{
origin[i] = static_cast<typename ResultImageDescriptorType::PointType::ValueType>(geoOrigin[i]);
fieldSpacing[i] = static_cast<typename ResultImageDescriptorType::SpacingType::ValueType>(geoSpacing[i]);
size[i] = static_cast<typename ResultImageDescriptorType::SizeType::SizeValueType>(geoBounds[(2*i)+1]-geoBounds[2*i])*fieldSpacing[i];
}
//Matrix extraction
matrix.SetIdentity();
unsigned int i;
unsigned int j;
/// \warning 2D MITK images could have a 3D rotation, since they have a 3x3 geometry matrix.
/// If it is only a rotation around the transversal plane normal, it can be express with a 2x2 matrix.
/// In this case, the ITK image conservs this information and is identical to the MITK image!
/// If the MITK image contains any other rotation, the ITK image will have no rotation at all.
/// Spacing is of course conserved in both cases.
// the following loop devides by spacing now to normalize columns.
// counterpart of InitializeByItk in mitkImage.h line 372 of revision 15092.
// Check if information is lost
if ( VImageDimension == 2)
{
if ( ( geoMatrix[0][2] != 0) ||
( geoMatrix[1][2] != 0) ||
( geoMatrix[2][0] != 0) ||
( geoMatrix[2][1] != 0) ||
(( geoMatrix[2][2] != 1) && ( geoMatrix[2][2] != -1) ))
{
// The 2D MITK image contains 3D rotation information.
// This cannot be expressed in a 2D ITK image, so the ITK image will have no rotation
}
else
{
// The 2D MITK image can be converted to an 2D ITK image without information loss!
for ( i=0; i < 2; ++i)
{
for( j=0; j < 2; ++j )
{
matrix[i][j] = geoMatrix[i][j]/fieldSpacing[j];
}
}
}
}
else if (VImageDimension == 3)
{
// Normal 3D image. Conversion possible without problem!
for ( i=0; i < 3; ++i)
{
for( j=0; j < 3; ++j )
{
matrix[i][j] = geoMatrix[i][j]/fieldSpacing[j];
}
}
}
else
{
assert(0);
throw mitk::AccessByItkException("Usage of resultGeometry for 2D images is not yet implemented.");
/**@TODO Implement extraction of 2D-Rotation-Matrix out of 3D-Rotation-Matrix
* to cover this case as well.
* matrix = extract2DRotationMatrix(resultGeometry)*/
}
resultDescriptor->setOrigin(origin);
resultDescriptor->setSize(size);
resultDescriptor->setSpacing(fieldSpacing);
resultDescriptor->setDirection(matrix);
}
//do the mapping
/////////////////////////
typedef ::itk::InterpolateImageFunction< ::itk::Image<TPixelType,VImageDimension> > BaseInterpolatorType;
typename BaseInterpolatorType::Pointer interpolator = generateInterpolator< ::itk::Image<TPixelType,VImageDimension> >(interpolatorType);
assert(interpolator.IsNotNull());
spTask->setImageInterpolator(interpolator);
spTask->setInputImage(input);
spTask->setRegistration(castedReg);
spTask->setResultImageDescriptor(resultDescriptor);
spTask->setThrowOnMappingError(throwOnMappingError);
spTask->setErrorValue(errorValue);
spTask->setThrowOnPaddingError(throwOnOutOfInputAreaError);
spTask->setPaddingValue(paddingValue);
spTask->execute();
mitk::CastToMitkImage<>(spTask->getResultImage(),result);
}
/**Helper function to ensure the mapping of all time steps of an image.*/
void doMapTimesteps(const mitk::ImageMappingHelper::InputImageType* input, mitk::Image* result, const mitk::ImageMappingHelper::RegistrationType* registration, bool throwOnOutOfInputAreaError,double paddingValue, const mitk::ImageMappingHelper::ResultImageGeometryType* resultGeometry, bool throwOnMappingError, double errorValue, mitk::ImageMappingInterpolator::Type interpolatorType)
{
for (unsigned int i = 0; i<input->GetTimeSteps(); ++i)
{
mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New();
imageTimeSelector->SetInput(input);
imageTimeSelector->SetTimeNr(i);
imageTimeSelector->UpdateLargestPossibleRegion();
mitk::ImageMappingHelper::InputImageType::Pointer timeStepInput = imageTimeSelector->GetOutput();
mitk::ImageMappingHelper::ResultImageType::Pointer timeStepResult;
AccessByItk_n(timeStepInput, doMITKMap, (timeStepResult, registration, throwOnOutOfInputAreaError, paddingValue, resultGeometry, throwOnMappingError, errorValue, interpolatorType));
mitk::ImageReadAccessor readAccess(timeStepResult);
result->SetVolume(readAccess.GetData(), i);
}
}
mitk::TimeGeometry::Pointer CreateResultTimeGeometry(const mitk::ImageMappingHelper::InputImageType* input, const mitk::ImageMappingHelper::ResultImageGeometryType* resultGeometry)
{
mitk::TimeGeometry::ConstPointer timeGeometry = input->GetTimeGeometry();
mitk::TimeGeometry::Pointer mappedTimeGeometry = timeGeometry->Clone();
for (unsigned int i = 0; i < input->GetTimeSteps(); ++i)
{
mitk::ImageMappingHelper::ResultImageGeometryType::Pointer mappedGeometry = resultGeometry->Clone();
mappedTimeGeometry->SetTimeStepGeometry(mappedGeometry, i);
}
return mappedTimeGeometry;
}
mitk::ImageMappingHelper::ResultImageType::Pointer
mitk::ImageMappingHelper::map(const InputImageType* input, const RegistrationType* registration,
bool throwOnOutOfInputAreaError, const double& paddingValue, const ResultImageGeometryType* resultGeometry,
bool throwOnMappingError, const double& errorValue, mitk::ImageMappingInterpolator::Type interpolatorType)
{
if (!registration)
{
mitkThrow() << "Cannot map image. Passed registration wrapper pointer is nullptr.";
}
if (!input)
{
mitkThrow() << "Cannot map image. Passed image pointer is nullptr.";
}
ResultImageType::Pointer result;
auto inputLabelSetImage = dynamic_cast<const LabelSetImage*>(input);
if (nullptr == inputLabelSetImage)
{
if (input->GetTimeSteps() == 1)
{ //map the image and done
AccessByItk_n(input, doMITKMap, (result, registration, throwOnOutOfInputAreaError, paddingValue, resultGeometry, throwOnMappingError, errorValue, interpolatorType));
}
else
{ //map every time step and compose
auto mappedTimeGeometry = CreateResultTimeGeometry(input, resultGeometry);
result = mitk::Image::New();
result->Initialize(input->GetPixelType(), *mappedTimeGeometry, 1, input->GetTimeSteps());
doMapTimesteps(input, result, registration, throwOnOutOfInputAreaError, paddingValue, resultGeometry, throwOnMappingError, errorValue, interpolatorType);
}
}
else
{
auto resultLabelSetImage = LabelSetImage::New();
auto mappedTimeGeometry = CreateResultTimeGeometry(input, resultGeometry);
auto resultTemplate = mitk::Image::New();
resultTemplate->Initialize(input->GetPixelType(), *mappedTimeGeometry, 1, input->GetTimeSteps());
resultLabelSetImage->Initialize(resultTemplate);
auto cloneInput = inputLabelSetImage->Clone();
//We need to clone the LabelSetImage due to its illposed design. It is state full
//and we have to iterate through all layers as active layers to ensure the content
//was really stored (directly working with the layer images does not work with the
//active layer). The clone wastes rescources but is the easiest and safest way to
//ensure 1) correct mapping 2) avoid race conditions with other parts of the
//application because we would change the state of the input.
//This whole code block should be reworked as soon as T28525 is done.
for (unsigned int layerID = 0; layerID < inputLabelSetImage->GetNumberOfLayers(); ++layerID)
{
if (resultLabelSetImage->GetNumberOfLayers() <= layerID)
{
resultLabelSetImage->AddLayer();
}
resultLabelSetImage->AddLabelSetToLayer(layerID, inputLabelSetImage->GetLabelSet(layerID)->Clone());
cloneInput->SetActiveLayer(layerID);
resultLabelSetImage->SetActiveLayer(layerID);
doMapTimesteps(cloneInput, resultLabelSetImage, registration, throwOnOutOfInputAreaError, paddingValue, resultGeometry, throwOnMappingError, errorValue, mitk::ImageMappingInterpolator::Linear);
}
resultLabelSetImage->SetActiveLayer(inputLabelSetImage->GetActiveLayer());
resultLabelSetImage->GetLabelSet(inputLabelSetImage->GetActiveLayer())->SetActiveLabel(inputLabelSetImage->GetActiveLabel(inputLabelSetImage->GetActiveLayer())->GetValue());
result = resultLabelSetImage;
}
return result;
}
mitk::ImageMappingHelper::ResultImageType::Pointer
mitk::ImageMappingHelper::map(const InputImageType* input, const MITKRegistrationType* registration,
bool throwOnOutOfInputAreaError, const double& paddingValue, const ResultImageGeometryType* resultGeometry,
bool throwOnMappingError, const double& errorValue, mitk::ImageMappingInterpolator::Type)
{
if (!registration)
{
mitkThrow() << "Cannot map image. Passed registration wrapper pointer is nullptr.";
}
if (!registration->GetRegistration())
{
mitkThrow() << "Cannot map image. Passed registration wrapper containes no registration.";
}
if (!input)
{
mitkThrow() << "Cannot map image. Passed image pointer is nullptr.";
}
ResultImageType::Pointer result = map(input, registration->GetRegistration(), throwOnOutOfInputAreaError, paddingValue, resultGeometry, throwOnMappingError, errorValue);
return result;
}
+mitk::ImageMappingHelper::ResultImageGeometryType::Pointer
+mitk::ImageMappingHelper::GenerateSuperSampledGeometry(const ResultImageGeometryType* inputGeometry, double xScaling, double yScaling, double zScaling)
+{
+ auto resultGeometry = inputGeometry->Clone();
+
+ //change the pixel count and spacing of the geometry
+ mitk::BaseGeometry::BoundsArrayType geoBounds = inputGeometry->GetBounds();
+ auto oldSpacing = inputGeometry->GetSpacing();
+ mitk::Vector3D geoSpacing;
+
+ geoSpacing[0] = oldSpacing[0] / xScaling;
+ geoSpacing[1] = oldSpacing[1] / yScaling;
+ geoSpacing[2] = oldSpacing[2] / zScaling;
+
+ geoBounds[1] = geoBounds[1] * xScaling;
+ geoBounds[3] = geoBounds[3] * yScaling;
+ geoBounds[5] = geoBounds[5] * zScaling;
+
+ resultGeometry->SetBounds(geoBounds);
+ resultGeometry->SetSpacing(geoSpacing);
+
+ auto oldOrigin = inputGeometry->GetOrigin();
+
+ //if we change the spacing we must also correct the origin to ensure
+ //that the voxel matrix still covers the same space. This is due the fact
+ //that the origin is not in the corner of the voxel matrix, but in the center
+ // of the voxel that is in the corner.
+ mitk::Point3D newOrigin;
+ for (mitk::Point3D::SizeType i = 0; i < 3; ++i)
+ {
+ newOrigin[i] = 0.5 * (geoSpacing[i] - oldSpacing[i]) + oldOrigin[i];
+ }
+
+ return resultGeometry;
+}
+
mitk::ImageMappingHelper::ResultImageType::Pointer
mitk::ImageMappingHelper::
- refineGeometry(const InputImageType* input, const RegistrationType* registration,
- bool throwOnError)
+ refineGeometry(const InputImageType * input, const RegistrationType * registration,
+ bool throwOnError)
{
mitk::ImageMappingHelper::ResultImageType::Pointer result = nullptr;
if (!registration)
{
mitkThrow() << "Cannot refine image geometry. Passed registration pointer is nullptr.";
}
if (!input)
{
mitkThrow() << "Cannot refine image geometry. Passed image pointer is nullptr.";
}
- mitk::MITKRegistrationHelper::Affine3DTransformType::Pointer spTransform = mitk::MITKRegistrationHelper::getAffineMatrix(registration,false);
- if(spTransform.IsNull() && throwOnError)
+ mitk::MITKRegistrationHelper::Affine3DTransformType::Pointer spTransform = mitk::MITKRegistrationHelper::getAffineMatrix(registration, false);
+ if (spTransform.IsNull() && throwOnError)
{
mitkThrow() << "Cannot refine image geometry. Registration does not contain a suitable direct mapping kernel (3D affine transformation or compatible required).";
}
- if(spTransform.IsNotNull())
+ if (spTransform.IsNotNull())
{
//copy input image
result = input->Clone();
//refine geometries
- for(unsigned int i = 0; i < result->GetTimeSteps(); ++i)
+ for (unsigned int i = 0; i < result->GetTimeSteps(); ++i)
{ //refine every time step
result->GetGeometry(i)->Compose(spTransform);
}
result->GetTimeGeometry()->Update();
}
return result;
}
+
+
mitk::ImageMappingHelper::ResultImageType::Pointer
mitk::ImageMappingHelper::
refineGeometry(const InputImageType* input, const MITKRegistrationType* registration,
bool throwOnError)
{
if (!registration)
{
mitkThrow() << "Cannot refine image geometry. Passed registration wrapper pointer is nullptr.";
}
if (!registration->GetRegistration())
{
mitkThrow() << "Cannot refine image geometry. Passed registration wrapper containes no registration.";
}
if (!input)
{
mitkThrow() << "Cannot refine image geometry. Passed image pointer is nullptr.";
}
ResultImageType::Pointer result = refineGeometry(input, registration->GetRegistration(), throwOnError);
return result;
}
bool
mitk::ImageMappingHelper::
canRefineGeometry(const RegistrationType* registration)
{
bool result = true;
if (!registration)
{
mitkThrow() << "Cannot check refine capability of registration. Passed registration pointer is nullptr.";
}
//if the helper does not return null, we can refine the geometry.
result = mitk::MITKRegistrationHelper::getAffineMatrix(registration,false).IsNotNull();
return result;
}
bool
mitk::ImageMappingHelper::
canRefineGeometry(const MITKRegistrationType* registration)
{
if (!registration)
{
mitkThrow() << "Cannot check refine capability of registration. Passed registration wrapper pointer is nullptr.";
}
if (!registration->GetRegistration())
{
mitkThrow() << "Cannot check refine capability of registration. Passed registration wrapper containes no registration.";
}
return canRefineGeometry(registration->GetRegistration());
}
diff --git a/Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapper.cpp b/Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapper.cpp
index 2ad231a33d..b029d62d78 100644
--- a/Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapper.cpp
+++ b/Modules/MatchPointRegistration/src/mitkMAPRegistrationWrapper.cpp
@@ -1,159 +1,169 @@
/*============================================================================
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 "mitkMAPRegistrationWrapper.h"
#include <mapExceptionObjectMacros.h>
#include <mapRegistrationManipulator.h>
mitk::MAPRegistrationWrapper::MAPRegistrationWrapper(map::core::RegistrationBase* registration) : m_spRegistration(registration)
{
if (registration == nullptr)
{
mitkThrow() << "Error. Cannot create MAPRegistrationWrapper with invalid registration instance (nullptr).";
}
Identifiable::SetUID(registration->getRegistrationUID());
}
mitk::MAPRegistrationWrapper::~MAPRegistrationWrapper()
{
}
void mitk::MAPRegistrationWrapper::SetRequestedRegionToLargestPossibleRegion()
{
//nothing to do
}
bool mitk::MAPRegistrationWrapper::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::MAPRegistrationWrapper::VerifyRequestedRegion()
{
return true;
}
+bool mitk::MAPRegistrationWrapper::IsEmptyTimeStep(unsigned int /*t*/) const
+{
+ return m_spRegistration.IsNull();
+}
+
+bool mitk::MAPRegistrationWrapper::IsEmpty() const
+{
+ return m_spRegistration.IsNull();
+}
+
void mitk::MAPRegistrationWrapper::SetRequestedRegion(const itk::DataObject*)
{
//nothing to do
}
unsigned int mitk::MAPRegistrationWrapper::GetMovingDimensions() const
{
if (m_spRegistration.IsNull())
{
mitkThrow()<< "Error. Cannot return moving dimension. Wrapper points to invalid registration (nullptr).";
}
return m_spRegistration->getMovingDimensions();
}
unsigned int mitk::MAPRegistrationWrapper::GetTargetDimensions() const
{
if (m_spRegistration.IsNull())
{
mitkThrow()<< "Error. Cannot return target dimension. Wrapper points to invalid registration (nullptr).";
}
return m_spRegistration->getTargetDimensions();
}
const mitk::MAPRegistrationWrapper::TagMapType& mitk::MAPRegistrationWrapper::GetTags() const
{
if (m_spRegistration.IsNull())
{
mitkThrow()<< "Error. Cannot return registration tags. Wrapper points to invalid registration (nullptr).";
}
return m_spRegistration->getTags();
}
bool mitk::MAPRegistrationWrapper::GetTagValue(const TagType & tag, ValueType & value) const
{
if (m_spRegistration.IsNull())
{
mitkThrow()<< "Error. Cannot return registration tag value. Wrapper points to invalid registration (nullptr). Tag: " << tag;
}
return m_spRegistration->getTagValue(tag,value);
}
bool mitk::MAPRegistrationWrapper::HasLimitedTargetRepresentation() const
{
if (m_spRegistration.IsNull())
{
mitkThrow()<< "Error. Cannot determin HasLimitedTargetRepresentation(). Wrapper points to invalid registration (nullptr).";
}
return m_spRegistration->hasLimitedTargetRepresentation();
}
bool mitk::MAPRegistrationWrapper::HasLimitedMovingRepresentation() const
{
if (m_spRegistration.IsNull())
{
mitkThrow()<< "Error. Cannot determin HasLimitedMovingRepresentation(). Wrapper points to invalid registration (nullptr).";
}
return m_spRegistration->hasLimitedMovingRepresentation();
}
map::core::RegistrationBase* mitk::MAPRegistrationWrapper::GetRegistration()
{
return m_spRegistration;
}
const map::core::RegistrationBase* mitk::MAPRegistrationWrapper::GetRegistration() const
{
return m_spRegistration;
}
void mitk::MAPRegistrationWrapper::PrintSelf (std::ostream &os, itk::Indent indent) const
{
Superclass::PrintSelf(os,indent);
if (m_spRegistration.IsNull())
{
os<< "Error. Wrapper points to invalid registration (nullptr).";
}
else
{
os<<std::endl<<indent<<"MatchPoint registration instance:";
m_spRegistration->Print(os,indent.GetNextIndent());
typedef map::core::Registration<3,3> CastedRegType;
const CastedRegType* pCastedReg = dynamic_cast<const CastedRegType*>(m_spRegistration.GetPointer());
os<<std::endl<<indent<<"MatchPoint registration direct kernel instance:";
pCastedReg->getDirectMapping().Print(os,indent.GetNextIndent());
os<<std::endl<<indent<<"MatchPoint registration inverse kernel instance:";
pCastedReg->getInverseMapping().Print(os,indent.GetNextIndent());
}
}
void mitk::MAPRegistrationWrapper::SetUID(const UIDType& uid)
{
if (m_spRegistration.IsNull())
{
mitkThrow() << "Error. Cannot set UID. Wrapper points to invalid registration (nullptr).";
}
Identifiable::SetUID(uid);
::map::core::RegistrationBaseManipulator manip(m_spRegistration);
manip.getTagValues()[::map::tags::RegistrationUID] = uid;
};
mitk::Identifiable::UIDType mitk::MAPRegistrationWrapper::GetUID() const
{
if (m_spRegistration.IsNull())
{
mitkThrow() << "Error. Cannot return UID. Wrapper points to invalid registration (nullptr).";
}
return m_spRegistration->getRegistrationUID();
};
diff --git a/Modules/MatchPointRegistrationUI/Qmitk/QmitkAlgorithmListModel.h b/Modules/MatchPointRegistrationUI/Qmitk/QmitkAlgorithmListModel.h
index 24da486c08..c1187112ec 100644
--- a/Modules/MatchPointRegistrationUI/Qmitk/QmitkAlgorithmListModel.h
+++ b/Modules/MatchPointRegistrationUI/Qmitk/QmitkAlgorithmListModel.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 QmitkAlgorithmListModel_h
#define QmitkAlgorithmListModel_h
#include <QAbstractTableModel>
#include <QStringList>
// MITK
#include "MitkMatchPointRegistrationUIExports.h"
// MatchPoint
#include <mapDeploymentDLLDirectoryBrowser.h>
/*!
\class QmitkAlgorithmListModel
Model that takes a list of MatchPoint algorithm dll handles and represents it as model in context of the QT
view-model-concept.
\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation.
*/
-class MITKMATCHPOINTREGISTRATIONUI_EXPORT QmitkAlgorithmListModel : public QAbstractTableModel
+class MITKMATCHPOINTREGISTRATIONUI_EXPORT QmitkAlgorithmListModel /** \cond */ : public QAbstractTableModel /** \endcond */
{
Q_OBJECT
public:
QmitkAlgorithmListModel(QObject *parent = nullptr);
~QmitkAlgorithmListModel() override{};
void SetAlgorithms(::map::deployment::DLLDirectoryBrowser::DLLInfoListType algList);
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
private:
::map::deployment::DLLDirectoryBrowser::DLLInfoListType m_AlgList;
};
#endif
diff --git a/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.h b/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.h
index 0363ecc89e..7e00996dd3 100644
--- a/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.h
+++ b/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.h
@@ -1,78 +1,78 @@
/*============================================================================
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 QmitkMapPropertyDelegate_h
#define QmitkMapPropertyDelegate_h
/// Toolkit includes.
#include "mitkBaseProperty.h"
#include <QStyledItemDelegate>
// MITK
#include "MitkMatchPointRegistrationUIExports.h"
/// Forward declarations.
///
/// \class QmitkPropertyDelegate
/// \brief An item delegate for rendering and editing mitk::Properties in a QTableView.
///
/// \see QmitkPropertiesTableModel
-class MITKMATCHPOINTREGISTRATIONUI_EXPORT QmitkMapPropertyDelegate : public QStyledItemDelegate
+class MITKMATCHPOINTREGISTRATIONUI_EXPORT QmitkMapPropertyDelegate /** \cond */ : public QStyledItemDelegate /** \endcond */
{
Q_OBJECT
public:
///
/// Creates a new PropertyDelegate.
///
QmitkMapPropertyDelegate(QObject *parent = nullptr);
///
/// Renders a specific property (overwritten from QItemDelegate)
///
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
///
/// Create an editor for a specific property (overwritten from QItemDelegate)
///
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
///
/// Create an editor for a specific property (overwritten from QItemDelegate)
///
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
///
/// When the user accepts input this func commits the data to the model (overwritten from QItemDelegate)
///
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
///
/// \brief Fit an editor to some geometry (overwritten from QItemDelegate)
///
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
protected:
bool eventFilter(QObject *o, QEvent *e) override;
private slots:
///
/// Invoked when the user accepts editor input, that is when he does not pushes ESC.
///
void commitAndCloseEditor();
void showColorDialog();
void ComboBoxCurrentIndexChanged(int index);
void SpinBoxValueChanged(const QString &value);
};
#endif
diff --git a/Modules/ModelFit/autoload/Models/mitkModelFitModelsActivator.cpp b/Modules/ModelFit/autoload/Models/mitkModelFitModelsActivator.cpp
index e58a17b569..6c62aaf983 100644
--- a/Modules/ModelFit/autoload/Models/mitkModelFitModelsActivator.cpp
+++ b/Modules/ModelFit/autoload/Models/mitkModelFitModelsActivator.cpp
@@ -1,62 +1,64 @@
/*============================================================================
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 <usModuleActivator.h>
#include <usModuleContext.h>
#include <mitkModelFitProviderBase.h>
//general models
#include "mitkGenericParamModelFactory.h"
#include "mitkLinearModelFactory.h"
#include "mitkT2DecayModelFactory.h"
#include "mitkExpDecayOffsetModelFactory.h"
+#include "mitkExponentialSaturationModelFactory.h"
namespace mitk
{
/*
* This is the module activator for the IO aspects of the "ModelFit" module.
*/
class ModelFitModelsActivator : public us::ModuleActivator
{
public:
template <class TProvider> void RegisterProvider(us::ModuleContext* context)
{
auto provider = new TProvider();
provider->RegisterService(context);
m_RegisteredProviders.push_back(std::unique_ptr<IModelFitProvider>(provider));
}
void Load(us::ModuleContext* context) override
{
m_RegisteredProviders.clear();
RegisterProvider<mitk::ModelFitProviderBase<mitk::GenericParamModelFactory> >(context);
RegisterProvider<mitk::ModelFitProviderBase<mitk::LinearModelFactory> >(context);
RegisterProvider<mitk::ModelFitProviderBase<mitk::T2DecayModelFactory> >(context);
RegisterProvider<mitk::ModelFitProviderBase<mitk::ExpDecayOffsetModelFactory> >(context);
+ RegisterProvider<mitk::ModelFitProviderBase<mitk::ExponentialSaturationModelFactory> >(context);
}
void Unload(us::ModuleContext* ) override
{
}
private:
std::vector<std::unique_ptr<IModelFitProvider> > m_RegisteredProviders;
};
}
US_EXPORT_MODULE_ACTIVATOR(mitk::ModelFitModelsActivator)
diff --git a/Modules/ModelFit/files.cmake b/Modules/ModelFit/files.cmake
index a46a3694cb..97c70eaeb0 100644
--- a/Modules/ModelFit/files.cmake
+++ b/Modules/ModelFit/files.cmake
@@ -1,79 +1,82 @@
file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*")
set(CPP_FILES
Common/mitkExtractTimeGrid.cpp
Common/mitkTimeGridHelper.cpp
Common/mitkMaskedDynamicImageStatisticsGenerator.cpp
Common/mitkModelFitConstants.cpp
Common/mitkModelFitParameter.cpp
Common/mitkModelFitCmdAppsHelper.cpp
Common/mitkParameterFitImageGeneratorBase.cpp
Common/mitkPixelBasedParameterFitImageGenerator.cpp
Common/mitkROIBasedParameterFitImageGenerator.cpp
Common/mitkModelFitInfo.cpp
Common/mitkModelFitStaticParameterMap.cpp
Common/mitkModelGenerator.cpp
Common/mitkModelFitResultHelper.cpp
Common/mitkScalarListLookupTable.cpp
Common/mitkScalarListLookupTableProperty.cpp
Common/mitkScalarListLookupTablePropertySerializer.cpp
Common/mitkIModelFitProvider.cpp
Common/mitkModelFitParameterValueExtraction.cpp
Common/mitkBinaryImageToLabelSetImageFilter.cpp
Common/mitkFormulaParser.cpp
Common/mitkFresnel.cpp
Common/mitkModelFitPlotDataHelper.cpp
Common/mitkModelSignalImageGenerator.cpp
Common/mitkModelFitResultRelationRule.cpp
Functors/mitkSimpleFunctorBase.cpp
Functors/mitkSimpleFunctorPolicy.cpp
Functors/mitkChiSquareFitCostFunction.cpp
Functors/mitkReducedChiSquareFitCostFunction.cpp
Functors/mitkConstraintCheckerBase.cpp
Functors/mitkSimpleBarrierConstraintChecker.cpp
Functors/mitkSquaredDifferencesFitCostFunction.cpp
Functors/mitkSumOfSquaredDifferencesFitCostFunction.cpp
Functors/mitkMVConstrainedCostFunctionDecorator.cpp
Functors/mitkMVModelFitCostFunction.cpp
Functors/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.cpp
Functors/mitkSVModelFitCostFunction.cpp
Functors/mitkModelFitFunctorBase.cpp
Functors/mitkLevenbergMarquardtModelFitFunctor.cpp
Functors/mitkDummyModelFitFunctor.cpp
Functors/mitkModelFitInfoSignalGenerationFunctor.cpp
Functors/mitkIndexedValueFunctorPolicy.cpp
Functors/mitkModelDataGenerationFunctor.cpp
Models/mitkModelBase.cpp
Models/mitkModelFactoryBase.cpp
Models/mitkModelParameterizerBase.cpp
Models/mitkLinearModel.cpp
Models/mitkLinearModelFactory.cpp
Models/mitkInitialParameterizationDelegateBase.cpp
Models/mitkImageBasedParameterizationDelegate.cpp
Models/mitkGenericParamModel.cpp
Models/mitkGenericParamModelFactory.cpp
Models/mitkGenericParamModelParameterizer.cpp
Models/mitkValueBasedParameterizationDelegate.cpp
Models/mitkT2DecayModel.cpp
Models/mitkT2DecayModelFactory.cpp
Models/mitkT2DecayModelParameterizer.cpp
+ Models/mitkExponentialSaturationModel.cpp
+ Models/mitkExponentialSaturationModelFactory.cpp
+ Models/mitkExponentialSaturationModelParameterizer.cpp
Models/mitkExpDecayOffsetModel.cpp
Models/mitkExpDecayOffsetModelFactory.cpp
Models/mitkExpDecayOffsetModelParameterizer.cpp
TestingHelper/mitkTestModel.cpp
TestingHelper/mitkTestModelFactory.cpp
)
set(TPP_FILES
include/itkMultiOutputNaryFunctorImageFilter.tpp
include/itkMaskedStatisticsImageFilter.hxx
include/itkMaskedNaryStatisticsImageFilter.hxx
include/mitkModelFitProviderBase.tpp
)
set(HXX_FILES
)
set(MOC_H_FILES
)
diff --git a/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h b/Modules/ModelFit/include/mitkExponentialSaturationModel.h
similarity index 52%
copy from Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h
copy to Modules/ModelFit/include/mitkExponentialSaturationModel.h
index 71758e63b5..7072660796 100644
--- a/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h
+++ b/Modules/ModelFit/include/mitkExponentialSaturationModel.h
@@ -1,123 +1,86 @@
/*============================================================================
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 mitkThreeStepLinearModel_h
-#define mitkThreeStepLinearModel_h
+#ifndef __MITK_EXPONENTIAL_SATURATION_MODEL_H_
+#define __MITK_EXPONENTIAL_SATURATION_MODEL_H_
#include "mitkModelBase.h"
-#include "MitkPharmacokineticsExports.h"
+#include "MitkModelFitExports.h"
namespace mitk
{
- class MITKPHARMACOKINETICS_EXPORT ThreeStepLinearModel : public mitk::ModelBase
+ /** @class ExponentialSaturationModel
+ * @brief This genric model has the form: if x<BAT f(x) = S0 , else f(x) = A * (1-exp(-*B(x-BAT)))
+ */
+ class MITKMODELFIT_EXPORT ExponentialSaturationModel : public mitk::ModelBase
{
public:
- typedef ThreeStepLinearModel Self;
+ typedef ExponentialSaturationModel Self;
typedef mitk::ModelBase Superclass;
typedef itk::SmartPointer< Self > Pointer;
typedef itk::SmartPointer< const Self > ConstPointer;
typedef Superclass::ParameterNameType ParameterNameType;
typedef Superclass::ParametersSizeType ParametersSizeType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
/** Run-time type information (and related methods). */
- itkTypeMacro(ThreeStepLinearModel, ModelBase);
-
- static const std::string MODEL_DISPLAY_NAME;
- static const std::string NAME_PARAMETER_S0;
- static const std::string NAME_PARAMETER_t1;
- static const std::string NAME_PARAMETER_t2;
- static const std::string NAME_PARAMETER_a1;
- static const std::string NAME_PARAMETER_a2;
- static const std::string NAME_PARAMETER_b1;
- static const std::string NAME_PARAMETER_b2;
-
- static const std::string UNIT_PARAMETER_S0;
- static const std::string UNIT_PARAMETER_t1;
- static const std::string UNIT_PARAMETER_t2;
- static const std::string UNIT_PARAMETER_a1;
- static const std::string UNIT_PARAMETER_a2;
- static const std::string UNIT_PARAMETER_b1;
- static const std::string UNIT_PARAMETER_b2;
-
- static const unsigned int POSITION_PARAMETER_S0;
- static const unsigned int POSITION_PARAMETER_t1;
- static const unsigned int POSITION_PARAMETER_t2;
- static const unsigned int POSITION_PARAMETER_a1;
- static const unsigned int POSITION_PARAMETER_a2;
- static const unsigned int POSITION_PARAMETER_b1;
- static const unsigned int POSITION_PARAMETER_b2;
-
- static const unsigned int NUMBER_OF_PARAMETERS;
+ itkTypeMacro(ExponentialSaturationModel, ModelBase);
std::string GetModelDisplayName() const override;
std::string GetModelType() const override;
FunctionStringType GetFunctionString() const override;
std::string GetXName() const override;
ParameterNamesType GetParameterNames() const override;
ParametersSizeType GetNumberOfParameters() const override;
- ParamterUnitMapType GetParameterUnits() const override;
-
ParameterNamesType GetStaticParameterNames() const override;
ParametersSizeType GetNumberOfStaticParameters() const override;
- ParameterNamesType GetDerivedParameterNames() const override;
-
- ParametersSizeType GetNumberOfDerivedParameters() const override;
-
- ParamterUnitMapType GetDerivedParameterUnits() const override;
-
-
protected:
- ThreeStepLinearModel() {};
- ~ThreeStepLinearModel() override{};
-
+ ExponentialSaturationModel() {};
+ ~ExponentialSaturationModel() override {};
/**
* Actual implementation of the clone method. This method should be reimplemeted
* in subclasses to clone the extra required parameters.
*/
itk::LightObject::Pointer InternalClone() const override;
ModelResultType ComputeModelfunction(const ParametersType& parameters) const override;
- DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType&
- parameters) const override;
void SetStaticParameter(const ParameterNameType& name,
const StaticParameterValuesType& values) override;
StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const override;
private:
//No copy constructor allowed
- ThreeStepLinearModel(const Self& source);
+ ExponentialSaturationModel(const Self& source);
void operator=(const Self&); //purposely not implemented
};
}
-
#endif
diff --git a/Modules/ModelFit/include/mitkExponentialSaturationModelFactory.h b/Modules/ModelFit/include/mitkExponentialSaturationModelFactory.h
new file mode 100644
index 0000000000..4ade8277cd
--- /dev/null
+++ b/Modules/ModelFit/include/mitkExponentialSaturationModelFactory.h
@@ -0,0 +1,53 @@
+/*============================================================================
+
+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 __EXPONENTIAL_SATURATION_TEST_MODEL_FACTORY_H
+#define __EXPONENTIAL_SATURATION_TEST_MODEL_FACTORY_H
+
+#include <mitkCommon.h>
+
+#include "mitkConcreteModelFactoryBase.h"
+#include "mitkExponentialSaturationModel.h"
+
+#include "MitkModelFitExports.h"
+
+namespace mitk
+{
+
+ class MITKMODELFIT_EXPORT ExponentialSaturationModelFactory : public ConcreteModelFactoryBase<ExponentialSaturationModel>
+ {
+ public:
+ mitkClassMacroItkParent(ExponentialSaturationModelFactory, ConcreteModelFactoryBase<ExponentialSaturationModel>);
+ itkFactorylessNewMacro(Self);
+
+ ParametersType GetDefaultInitialParameterization() const override;
+
+ ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override;
+
+ protected:
+ ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit)
+ const override;
+
+ ExponentialSaturationModelFactory();
+
+ ~ExponentialSaturationModelFactory() override;
+
+ private:
+
+ //No copy constructor allowed
+ ExponentialSaturationModelFactory(const Self& source);
+ void operator=(const Self&); //purposely not implemented
+ };
+}
+
+
+#endif //__EXPONENTIAL_SATURATION_TEST_MODEL_FACTORY_H
diff --git a/Modules/ModelFit/include/mitkExponentialSaturationModelParameterizer.h b/Modules/ModelFit/include/mitkExponentialSaturationModelParameterizer.h
new file mode 100644
index 0000000000..7e38afd9e0
--- /dev/null
+++ b/Modules/ModelFit/include/mitkExponentialSaturationModelParameterizer.h
@@ -0,0 +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.
+
+============================================================================*/
+
+#ifndef __EXPONENTIAL_SATURATION_MODEL_PARAMETERIZER_H
+#define __EXPONENTIAL_SATURATION_MODEL_PARAMETERIZER_H
+
+#include "mitkConcreteModelParameterizerBase.h"
+#include "mitkExponentialSaturationModel.h"
+#include "MitkModelFitExports.h"
+
+namespace mitk
+{
+
+ class MITKMODELFIT_EXPORT ExponentialSaturationModelParameterizer : public
+ mitk::ConcreteModelParameterizerBase<mitk::ExponentialSaturationModel>
+ {
+ public:
+ typedef ExponentialSaturationModelParameterizer Self;
+ typedef mitk::ConcreteModelParameterizerBase<mitk::ExponentialSaturationModel> Superclass;
+ typedef itk::SmartPointer< Self > Pointer;
+ typedef itk::SmartPointer< const Self > ConstPointer;
+
+ itkTypeMacro(ExponentialSaturationModelParameterizer,
+ mitk::ConcreteModelParameterizerBase<mitk::ExponentialSaturationModel>);
+ itkFactorylessNewMacro(Self);
+
+ typedef Superclass::ModelBaseType ModelBaseType;
+ typedef Superclass::ModelBasePointer ModelBasePointer;
+
+ typedef Superclass::ModelType ModelType;
+ typedef ModelType::Pointer ModelPointer;
+
+ typedef Superclass::StaticParameterValueType StaticParameterValueType;
+ typedef Superclass::StaticParameterValuesType StaticParameterValuesType;
+ typedef Superclass::StaticParameterMapType StaticParameterMapType;
+
+ typedef Superclass::IndexType IndexType;
+
+ ParametersType GetDefaultInitialParameterization() const override;
+
+ protected:
+ ExponentialSaturationModelParameterizer();
+
+ ~ExponentialSaturationModelParameterizer() override;
+
+ private:
+
+ //No copy constructor allowed
+ ExponentialSaturationModelParameterizer(const Self& source);
+ void operator=(const Self&); //purposely not implemented
+ };
+}
+
+#endif // __EXPONENTIAL_SATURATION_MODEL_PARAMETERIZER_H
diff --git a/Modules/ModelFit/include/mitkIModelProvider.h b/Modules/ModelFit/include/mitkIModelProvider.h
index 24c9928502..3df525229c 100644
--- a/Modules/ModelFit/include/mitkIModelProvider.h
+++ b/Modules/ModelFit/include/mitkIModelProvider.h
@@ -1,113 +1,114 @@
/*============================================================================
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 mitkIModelProvider_h
#define mitkIModelProvider_h
-
+#include <mitkDataStorage.h>
+#include <mitkIFileIO.h>
#include <mitkServiceInterface.h>
namespace mitk
{
class BaseData;
}
namespace itk
{
template <class T>
class SmartPointer;
}
namespace mitk
{
/**
* \ingroup MicroServices_Interfaces
*
* \brief The common interface for all providers of models for fitting in mitk.
*
* Implementations of this interface must be registered as a service
* to make themselve available via the service registry. If the
* implementation is state-full, the service should be registered using
* a PrototypeServiceFactory.
*
* It is recommended to derive new implementations from ModelFitProviderBase,
* which provide correct service registration semantics.
*
* \sa ModelFitProviderBase
*/
- struct MITKCORE_EXPORT IFileReader : public IFileIO
+ struct MITKCORE_EXPORT IFileReader /** \cond */ : public IFileIO /** \endcond */
{
virtual ~IFileReader();
/**
* \brief Set the input location.
* \param location The file name to read from.
*/
virtual void SetInput(const std::string &location) = 0;
/**
* @brief Set an input stream to read from.
* @param location A custom label for the input stream.
* @param is The input stream.
*
* If \c is is \c NULL, this clears the current input stream and \c location
* is interpreted as a file-system path. Otherwise, \c location is a custom
* label describing the input stream \c is.
*/
virtual void SetInput(const std::string &location, std::istream *is) = 0;
/**
* @brief Get the current input location.
* @return The input location.
*/
virtual std::string GetInputLocation() const = 0;
/**
* @brief Get the input stream.
* @return The currently set input stream.
*/
virtual std::istream *GetInputStream() const = 0;
/**
* \brief Reads the specified file or input stream and returns its contents.
*
* \return A list of created BaseData objects.
*
* If GetInputStream() returns a non-null value, this method must use
* the returned stream object to read the data from. If no input stream
* was set, the data must be read from the path returned by GetInputLocation().
*
* \throws mitk::Exception
*/
virtual std::vector<itk::SmartPointer<BaseData>> Read() = 0;
/**
* \brief Reads the specified file or input stream, loading its
* contents into the provided DataStorage.
*
* \param ds The DataStorage to which the data is added.
* \return The set of added DataNodes to \c ds.
*
* This method may be overridden by implementations to create or
* reconstructed a hierarchy of mitk::DataNode instances in the
* provided mitk::DataStorage.
*
* \throws mitk::Exception
*/
virtual DataStorage::SetOfObjects::Pointer Read(mitk::DataStorage &ds) = 0;
};
} // namespace mitk
MITK_DECLARE_SERVICE_INTERFACE(mitk::IFileReader, "org.mitk.IFileReader")
#endif
diff --git a/Modules/ModelFit/include/mitkModelTestFixture.h b/Modules/ModelFit/include/mitkModelTestFixture.h
new file mode 100644
index 0000000000..27cbb97b42
--- /dev/null
+++ b/Modules/ModelFit/include/mitkModelTestFixture.h
@@ -0,0 +1,192 @@
+/*============================================================================
+
+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 MITKMODELTESTFIXTURE_H
+#define MITKMODELTESTFIXTURE_H
+
+
+#include "mitkTestingMacros.h"
+#include <mitkTestingConfig.h>
+#include "mitkTestFixture.h"
+#include <itksys/SystemTools.hxx>
+#include <mitkModelBase.h>
+#include "mitkModelFitException.h"
+
+#include <nlohmann/json.hpp>
+#include <iostream>
+#include <fstream>
+#include "mitkVector.h"
+
+using json = nlohmann::json;
+
+namespace mitk
+{
+ class mitkModelTestFixture : public mitk::TestFixture
+ {
+ public:
+ static json ParseJSONFile(const std::string path)
+ {
+ std::string pathToFile = GetTestDataFilePath(path);
+ std::ifstream file(pathToFile);
+ json json_obj;
+ if (!file.is_open())
+ {
+ MITK_ERROR << "Could not open \"" << pathToFile << "\"!";
+ }
+ try
+ {
+ json_obj = nlohmann::json::parse(file);
+ }
+ catch (const json::exception& e)
+ {
+ MITK_ERROR << "Could not parse JSON file!";
+ }
+ return json_obj;
+ }
+
+ static ModelBase::ParametersType ParseTestParameters(const json modelValues_json_obj)
+ {
+ ModelBase::ParametersType testparameters;
+ testparameters.SetSize(modelValues_json_obj["modelParameterValues"].size());
+ for (unsigned long i = 0; i < modelValues_json_obj["modelParameterValues"].size(); ++i)
+ {
+ testparameters[i] = modelValues_json_obj["modelParameterValues"][i];
+ }
+ return testparameters;
+ }
+
+ static ModelBase::StaticParameterMapType ParseStaticParameters(const json profile_json_obj, const json modelValues_json_obj)
+ {
+ ModelBase::StaticParameterMapType staticParameterMap;
+ for (unsigned long i = 0; i < modelValues_json_obj["staticParameterValues"].size(); ++i)
+ {
+ ModelBase::StaticParameterValuesType staticParameterValues;
+ ModelBase::ParameterNameType staticParameterName;
+ staticParameterName = profile_json_obj["staticParameterNames"][i];
+ for (unsigned int j = 0; j < modelValues_json_obj["staticParameterValues"][i].size(); ++j)
+ {
+ staticParameterValues.push_back(modelValues_json_obj["staticParameterValues"][i][j]);
+ }
+ staticParameterMap.insert(std::make_pair(staticParameterName, staticParameterValues));
+ }
+ return staticParameterMap;
+ }
+
+ static void SetStaticParametersForTest(mitk::ModelBase::Pointer testmodel, const json profile_json_obj, const json modelValues_json_obj)
+ {
+ mitk::ModelBase::StaticParameterMapType staticParameterMap;
+ staticParameterMap = ParseStaticParameters(profile_json_obj, modelValues_json_obj);
+ testmodel->SetStaticParameters(staticParameterMap);
+ }
+
+ static void CompareModelAndReferenceProfile(const mitk::ModelBase::Pointer testmodel, const json profile_json_obj)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking number of parameters in model.", testmodel->GetNumberOfParameters() == profile_json_obj["numberOfParameters"]);
+ for (unsigned long i = 0; i < profile_json_obj["numberOfParameters"]; i++)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking parameter names.", testmodel->GetParameterNames()[i] == profile_json_obj["parameterNames"][i]);
+ CPPUNIT_ASSERT_MESSAGE("Checking parameter scales.", testmodel->GetParameterScales()[testmodel->GetParameterNames()[i]] == profile_json_obj["parameterScales"][i]);
+ CPPUNIT_ASSERT_MESSAGE("Checking parameter units.", testmodel->GetParameterUnits()[testmodel->GetParameterNames()[i]] == profile_json_obj["parameterUnits"][i]);
+ }
+ CPPUNIT_ASSERT_MESSAGE("Checking number of derived parameters in model.", testmodel->GetNumberOfDerivedParameters() == profile_json_obj["numberOfDerivedParameters"]);
+ for (unsigned long i = 0; i < profile_json_obj["numberOfDerivedParameters"]; i++)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking derived parameter names.", testmodel->GetDerivedParameterNames()[i] == profile_json_obj["derivedParameterNames"][i]);
+ CPPUNIT_ASSERT_MESSAGE("Checking derived parameter scales.", testmodel->GetDerivedParameterScales()[testmodel->GetDerivedParameterNames()[i]] == profile_json_obj["derivedParameterScales"][i]);
+ CPPUNIT_ASSERT_MESSAGE("Checking derived parameter units.", testmodel->GetDerivedParameterUnits()[testmodel->GetDerivedParameterNames()[i]] == profile_json_obj["derivedParameterUnits"][i]);
+ }
+ CPPUNIT_ASSERT_MESSAGE("Checking number of static parameters in model.", testmodel->GetNumberOfStaticParameters() == profile_json_obj["numberOfStaticParameters"]);
+ for (unsigned long i = 0; i < profile_json_obj["numberOfStaticParameters"]; i++)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking static parameter names.", testmodel->GetStaticParameterNames()[i] == profile_json_obj["staticParameterNames"][i]);
+ CPPUNIT_ASSERT_MESSAGE("Checking static parameter units.", testmodel->GetStaticParameterUnits()[testmodel->GetStaticParameterNames()[i]] == profile_json_obj["staticParameterUnits"][i]);
+ }
+ CPPUNIT_ASSERT_MESSAGE("Checking function string.", testmodel->GetFunctionString() == profile_json_obj["functionString"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking class ID.", testmodel->GetClassID() == profile_json_obj["classID"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking model display name.", testmodel->GetModelDisplayName() == profile_json_obj["modelDisplayName"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking model type.", testmodel->GetModelType() == profile_json_obj["modelType"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking x name.", testmodel->GetXName() == profile_json_obj["xName"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking x axis name.", testmodel->GetXAxisName() == profile_json_obj["xAxisName"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking x axis unit.", testmodel->GetXAxisUnit() == profile_json_obj["xAxisUnit"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking y axis name.", testmodel->GetYAxisName() == profile_json_obj["yAxisName"]);
+ CPPUNIT_ASSERT_MESSAGE("Checking y axis unit.", testmodel->GetYAxisUnit() == profile_json_obj["yAxisUnit"]);
+ }
+
+ static void CompareModelAndReferenceSignal(mitk::ModelBase::Pointer testmodel, const json modelValues_json_obj, const json profile_json_obj)
+ {
+
+ for (unsigned int j = 0; j < modelValues_json_obj["modelValues"].size(); j++)
+ {
+ json modelValues_json_obj_current = modelValues_json_obj["modelValues"][j];
+
+ SetStaticParametersForTest(testmodel, profile_json_obj, modelValues_json_obj_current);
+
+ // Set time grid
+ mitk::ModelBase::TimeGridType timeGrid;
+ timeGrid.SetSize(modelValues_json_obj_current["timeGrid"].size());
+ for (unsigned long i = 0; i < modelValues_json_obj_current["timeGrid"].size(); ++i)
+ {
+ timeGrid[i] = modelValues_json_obj_current["timeGrid"][i];
+ }
+ testmodel->SetTimeGrid(timeGrid);
+
+ // Parse test parameters
+ mitk::ModelBase::ParametersType testparameters;
+ testparameters = ParseTestParameters(modelValues_json_obj_current);
+
+ //Generate signal
+ mitk::ModelBase::ModelResultType signal;
+ signal = testmodel->GetSignal(testparameters);
+
+
+ //ComputeModelfunction is called within GetSignal(), therefore no explicit testing of ComputeModelFunction()
+ // The reference signal has been calculated in a matlab script.
+ std::stringstream ss;
+ ss << "Checking signal for model parameter set " << j << ".";
+ std::string message = ss.str();
+ for (unsigned long i = 0; i < signal.size(); i++)
+ {
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(signal[i], modelValues_json_obj_current["signal"][i], 1e-6, true) == true);
+ }
+ }
+ }
+
+ static void CompareModelAndReferenceDerivedParameters(const mitk::ModelBase::Pointer testmodel, json modelValues_json_obj)
+ {
+ for (unsigned int j = 0; j < modelValues_json_obj["modelValues"].size(); j++)
+ {
+ json modelValues_json_obj_current = modelValues_json_obj["modelValues"][j];
+
+ // Set time grid
+ mitk::ModelBase::TimeGridType timeGrid;
+ timeGrid.SetSize(modelValues_json_obj_current["timeGrid"].size());
+ for (unsigned long i = 0; i < modelValues_json_obj_current["timeGrid"].size(); ++i)
+ {
+ timeGrid[i] = modelValues_json_obj_current["timeGrid"][i];
+ }
+ testmodel->SetTimeGrid(timeGrid);
+ mitk::ModelBase::ParametersType testparameters;
+ testparameters = mitk::mitkModelTestFixture::ParseTestParameters(modelValues_json_obj_current);
+ mitk::ModelBase::DerivedParameterMapType derivedParameterMap;
+ derivedParameterMap = testmodel->GetDerivedParameters(testparameters);
+ std::stringstream ss;
+ ss << "Checking derived parameters for model parameter set " << j << ".";
+ std::string message = ss.str();
+ for (unsigned long i = 0; i < modelValues_json_obj_current["derivedParameterValues"].size(); i++)
+ {
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(derivedParameterMap[testmodel->GetDerivedParameterNames()[i]], modelValues_json_obj_current["derivedParameterValues"][i], 1e-6, true) == true);
+ }
+ }
+ }
+ };
+}
+#endif // MITKMODELTESTFIXTURE_H
diff --git a/Modules/ModelFit/src/Functors/mitkSumOfSquaredDifferencesFitCostFunction.cpp b/Modules/ModelFit/src/Functors/mitkSumOfSquaredDifferencesFitCostFunction.cpp
index f40a7e31c6..b5c18ad721 100644
--- a/Modules/ModelFit/src/Functors/mitkSumOfSquaredDifferencesFitCostFunction.cpp
+++ b/Modules/ModelFit/src/Functors/mitkSumOfSquaredDifferencesFitCostFunction.cpp
@@ -1,26 +1,25 @@
/*============================================================================
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 "mitkSumOfSquaredDifferencesFitCostFunction.h"
-#include "mitkLogMacros.h"
mitk::SumOfSquaredDifferencesFitCostFunction::MeasureType mitk::SumOfSquaredDifferencesFitCostFunction::CalcMeasure(const ParametersType & /*parameters*/, const SignalType &signal) const
{
MeasureType measure = 0.0;
for(SignalType::size_type i=0; i<signal.GetSize(); ++i)
{
measure += (m_Sample[i] - signal[i]) * (m_Sample[i] - signal[i]);
}
return measure;
}
diff --git a/Modules/ModelFit/src/Models/mitkExponentialSaturationModel.cpp b/Modules/ModelFit/src/Models/mitkExponentialSaturationModel.cpp
new file mode 100644
index 0000000000..51bcecc086
--- /dev/null
+++ b/Modules/ModelFit/src/Models/mitkExponentialSaturationModel.cpp
@@ -0,0 +1,112 @@
+/*============================================================================
+
+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 "mitkExponentialSaturationModel.h"
+#include "mitkNumericConstants.h"
+
+std::string mitk::ExponentialSaturationModel::GetModelDisplayName() const
+{
+ return "Exponential Saturation Model";
+};
+
+std::string mitk::ExponentialSaturationModel::GetModelType() const
+{
+ return "Generic";
+};
+
+mitk::ExponentialSaturationModel::FunctionStringType mitk::ExponentialSaturationModel::GetFunctionString() const
+{
+ return "if x<BAT f(x) = S0 , else f(x) = A * (1-exp(-*B(x-BAT)))";
+};
+
+std::string mitk::ExponentialSaturationModel::GetXName() const
+{
+ return "t";
+};
+
+mitk::ExponentialSaturationModel::ParameterNamesType
+mitk::ExponentialSaturationModel::GetParameterNames() const
+{
+ ParameterNamesType result;
+ result.push_back("bat");
+ result.push_back("s0");
+ result.push_back("sfin");
+ result.push_back("rate");
+ return result;
+};
+
+mitk::ExponentialSaturationModel::ParametersSizeType
+mitk::ExponentialSaturationModel::GetNumberOfParameters() const
+{
+ return 4;
+};
+
+mitk::ExponentialSaturationModel::ModelResultType
+mitk::ExponentialSaturationModel::ComputeModelfunction(const ParametersType& parameters) const
+{
+ ModelResultType signal(m_TimeGrid.GetSize());
+
+ ModelResultType::iterator signalPos = signal.begin();
+
+ for (const auto& gridPos : m_TimeGrid)
+ {
+ if ((gridPos) < parameters[0])
+ {
+ *signalPos = parameters[1];
+ }
+ else
+ {
+ *signalPos = parameters[1] + (parameters[2]- parameters[1]) * (1.0 - exp((-1.0) * parameters[3] * (gridPos - parameters[0])));
+ }
+
+ ++signalPos;
+ }
+
+ return signal;
+};
+
+mitk::ExponentialSaturationModel::ParameterNamesType mitk::ExponentialSaturationModel::GetStaticParameterNames() const
+{
+ ParameterNamesType result;
+
+ return result;
+}
+
+mitk::ExponentialSaturationModel::ParametersSizeType mitk::ExponentialSaturationModel::GetNumberOfStaticParameters() const
+{
+ return 0;
+}
+
+void mitk::ExponentialSaturationModel::SetStaticParameter(const ParameterNameType& /*name*/,
+ const StaticParameterValuesType& /*values*/)
+{
+ //do nothing
+};
+
+mitk::ExponentialSaturationModel::StaticParameterValuesType mitk::ExponentialSaturationModel::GetStaticParameterValue(
+ const ParameterNameType& /*name*/) const
+{
+ StaticParameterValuesType result;
+
+ //do nothing
+
+ return result;
+};
+
+itk::LightObject::Pointer mitk::ExponentialSaturationModel::InternalClone() const
+{
+ ExponentialSaturationModel::Pointer newClone = ExponentialSaturationModel::New();
+
+ newClone->SetTimeGrid(this->m_TimeGrid);
+
+ return newClone.GetPointer();
+};
diff --git a/Modules/ModelFit/src/Models/mitkExponentialSaturationModelFactory.cpp b/Modules/ModelFit/src/Models/mitkExponentialSaturationModelFactory.cpp
new file mode 100644
index 0000000000..104e99759e
--- /dev/null
+++ b/Modules/ModelFit/src/Models/mitkExponentialSaturationModelFactory.cpp
@@ -0,0 +1,45 @@
+/*============================================================================
+
+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 "mitkExponentialSaturationModelFactory.h"
+#include "mitkExponentialSaturationModelParameterizer.h"
+#include "mitkSimpleBarrierConstraintChecker.h"
+
+mitk::ExponentialSaturationModelFactory::ExponentialSaturationModelFactory()
+{
+};
+
+mitk::ExponentialSaturationModelFactory::~ExponentialSaturationModelFactory()
+{
+};
+
+mitk::ModelParameterizerBase::ParametersType
+mitk::ExponentialSaturationModelFactory::GetDefaultInitialParameterization() const
+{
+ return ExponentialSaturationModelParameterizer::New()->GetDefaultInitialParameterization();
+};
+
+mitk::ConstraintCheckerBase::Pointer mitk::ExponentialSaturationModelFactory::CreateDefaultConstraints() const
+{
+ mitk::SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New();
+
+ constraints->SetLowerBarrier(0, 0, 0);
+ constraints->SetLowerBarrier(1, 0, 0);
+
+ return constraints.GetPointer();
+};
+
+mitk::ModelParameterizerBase::Pointer mitk::ExponentialSaturationModelFactory::DoCreateParameterizer(
+ const modelFit::ModelFitInfo* /*fit*/) const
+{
+ return ExponentialSaturationModelParameterizer::New().GetPointer();
+};
diff --git a/Modules/ModelFit/src/Models/mitkExponentialSaturationModelParameterizer.cpp b/Modules/ModelFit/src/Models/mitkExponentialSaturationModelParameterizer.cpp
new file mode 100644
index 0000000000..b9f54129c9
--- /dev/null
+++ b/Modules/ModelFit/src/Models/mitkExponentialSaturationModelParameterizer.cpp
@@ -0,0 +1,34 @@
+/*============================================================================
+
+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 "mitkExponentialSaturationModelParameterizer.h"
+
+mitk::ExponentialSaturationModelParameterizer::ParametersType
+mitk::ExponentialSaturationModelParameterizer::GetDefaultInitialParameterization() const
+{
+ ParametersType initialParameters;
+ initialParameters.SetSize(4);
+ initialParameters[0] = 0.0; //bat
+ initialParameters[1] = 0.0; //s0
+ initialParameters[2] = 100.0; //sfin
+ initialParameters[3] = 0.1; //k
+
+ return initialParameters;
+};
+
+mitk::ExponentialSaturationModelParameterizer::ExponentialSaturationModelParameterizer()
+{
+};
+
+mitk::ExponentialSaturationModelParameterizer::~ExponentialSaturationModelParameterizer()
+{
+};
diff --git a/Modules/ModelFit/test/files.cmake b/Modules/ModelFit/test/files.cmake
index 7a2d71e252..e0b2725304 100644
--- a/Modules/ModelFit/test/files.cmake
+++ b/Modules/ModelFit/test/files.cmake
@@ -1,16 +1,19 @@
SET(MODULE_TESTS
itkMultiOutputNaryFunctorImageFilterTest.cpp
itkMaskedStatisticsImageFilterTest.cpp
itkMaskedNaryStatisticsImageFilterTest.cpp
mitkLevenbergMarquardtModelFitFunctorTest.cpp
mitkPixelBasedParameterFitImageGeneratorTest.cpp
mitkROIBasedParameterFitImageGeneratorTest.cpp
mitkMaskedDynamicImageStatisticsGeneratorTest.cpp
mitkModelFitInfoTest.cpp
mitkModelFitStaticParameterMapTest.cpp
mitkSimpleBarrierConstraintCheckerTest.cpp
mitkMVConstrainedCostFunctionDecoratorTest.cpp
mitkConcreteModelFactoryBaseTest.cpp
mitkFormulaParserTest.cpp
mitkModelFitResultRelationRuleTest.cpp
+ mitkT2DecayModelTest.cpp
+ mitkLinearModelTest.cpp
+ mitkExpDecayOffsetModelTest.cpp
)
diff --git a/Modules/ModelFit/test/mitkExpDecayOffsetModelTest.cpp b/Modules/ModelFit/test/mitkExpDecayOffsetModelTest.cpp
new file mode 100644
index 0000000000..83cc2448f2
--- /dev/null
+++ b/Modules/ModelFit/test/mitkExpDecayOffsetModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+// Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkExpDecayOffsetModel.h"
+
+
+ class mitkExpDecayOffsetModelTestSuite : public mitk::mitkModelTestFixture
+ {
+ CPPUNIT_TEST_SUITE(mitkExpDecayOffsetModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+ mitk::ModelBase::Pointer m_testmodel;
+
+ public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("ModelFit/mitkExpDecayOffsetModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("ModelFit/mitkExpDecayOffsetModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::ExpDecayOffsetModel::New();
+ }
+
+ void tearDown() override
+ {
+
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+ };
+
+MITK_TEST_SUITE_REGISTRATION(mitkExpDecayOffsetModel)
diff --git a/Modules/ModelFit/test/mitkLinearModelTest.cpp b/Modules/ModelFit/test/mitkLinearModelTest.cpp
new file mode 100644
index 0000000000..b7cfc1ff5c
--- /dev/null
+++ b/Modules/ModelFit/test/mitkLinearModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+// Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkLinearModel.h"
+
+
+ class mitkLinearModelTestSuite : public mitk::mitkModelTestFixture
+ {
+ CPPUNIT_TEST_SUITE(mitkLinearModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+ mitk::ModelBase::Pointer m_testmodel;
+
+ public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("ModelFit/mitkLinearModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("ModelFit/mitkLinearModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::LinearModel::New();
+ }
+
+ void tearDown() override
+ {
+
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+ };
+
+MITK_TEST_SUITE_REGISTRATION(mitkLinearModel)
diff --git a/Modules/ModelFit/test/mitkT2DecayModelTest.cpp b/Modules/ModelFit/test/mitkT2DecayModelTest.cpp
new file mode 100644
index 0000000000..b66b4f5398
--- /dev/null
+++ b/Modules/ModelFit/test/mitkT2DecayModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+// Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkT2DecayModel.h"
+
+
+ class mitkT2DecayModelTestSuite : public mitk::mitkModelTestFixture
+ {
+ CPPUNIT_TEST_SUITE(mitkT2DecayModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+ mitk::ModelBase::Pointer m_testmodel;
+
+ public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("ModelFit/mitkT2DecayModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("ModelFit/mitkT2DecayModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::T2DecayModel::New();
+ }
+
+ void tearDown() override
+ {
+
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+ };
+
+MITK_TEST_SUITE_REGISTRATION(mitkT2DecayModel)
diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake
index d558488b7b..89d0588465 100644
--- a/Modules/ModuleList.cmake
+++ b/Modules/ModuleList.cmake
@@ -1,76 +1,77 @@
# The entries in the mitk_modules list must be
# ordered according to their dependencies.
set(MITK_MODULES
+ Log
Core
CommandLine
CoreCmdApps
AppUtil
LegacyIO
DataTypesExt
Annotation
LegacyGL
AlgorithmsExt
MapperExt
DICOM
DICOMQI
DICOMTesting
SceneSerializationBase
PlanarFigure
ImageDenoising
ImageExtraction
SceneSerialization
Gizmo
GraphAlgorithms
Multilabel
Chart
ImageStatistics
ContourModel
SurfaceInterpolation
Segmentation
QtWidgets
QtWidgetsExt
ImageStatisticsUI
SegmentationUI
MatchPointRegistration
MatchPointRegistrationUI
Classification
OpenIGTLink
IGTBase
IGT
CameraCalibration
OpenCL
OpenCVVideoSupport
QtOverlays
ToFHardware
ToFProcessing
ToFUI
US
USUI
DICOMUI
Remeshing
Python
QtPython
Persistence
OpenIGTLinkUI
IGTUI
RT
RTUI
IOExt
XNAT
TubeGraph
BoundingShape
RenderWindowManagerUI
SemanticRelations
SemanticRelationsUI
CEST
BasicImageProcessing
ModelFit
ModelFitUI
Pharmacokinetics
PharmacokineticsUI
DICOMPM
REST
RESTService
DICOMweb
)
diff --git a/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegIOMimeTypes.cpp b/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegIOMimeTypes.cpp
index 5abb559208..e43198415f 100644
--- a/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegIOMimeTypes.cpp
+++ b/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegIOMimeTypes.cpp
@@ -1,134 +1,134 @@
/*============================================================================
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 "mitkDICOMSegIOMimeTypes.h"
#include "mitkIOMimeTypes.h"
#include <array>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <itkGDCMImageIO.h>
#include <itksys/SystemTools.hxx>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmdata/dcdeftag.h>
namespace mitk
{
std::vector<CustomMimeType *> MitkDICOMSEGIOMimeTypes::Get()
{
std::vector<CustomMimeType *> mimeTypes;
// order matters here (descending rank for mime types)
mimeTypes.push_back(DICOMSEG_MIMETYPE().Clone());
return mimeTypes;
}
MitkDICOMSEGIOMimeTypes::MitkDICOMSEGMimeType::MitkDICOMSEGMimeType() : CustomMimeType(DICOMSEG_MIMETYPE_NAME())
{
this->AddExtension("dcm");
this->SetCategory(IOMimeTypes::CATEGORY_IMAGES());
this->SetComment("DICOM SEG");
}
bool MitkDICOMSEGIOMimeTypes::MitkDICOMSEGMimeType::AppliesTo(const std::string &path) const
{
bool canRead(CustomMimeType::AppliesTo(path));
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if (!itksys::SystemTools::FileExists(path.c_str()))
{
return canRead;
}
// end fix for bug 18572
const std::size_t offset = 128;
const std::size_t bufferSize = 4;
std::ifstream myfile(path, std::ifstream::binary);
if (!myfile.is_open())
return false;
myfile.seekg(0, std::ifstream::end);
const auto fileSize = static_cast<std::size_t>(myfile.tellg());
if (fileSize < offset + bufferSize)
return false;
myfile.seekg(offset);
std::array<char, bufferSize> buffer;
myfile.read(buffer.data(), bufferSize);
if (0 != std::string(buffer.data(), bufferSize).compare("DICM"))
return false;
DcmFileFormat dcmFileFormat;
OFCondition status = dcmFileFormat.loadFile(path.c_str());
if (status.bad())
{
canRead = false;
}
if (!canRead)
{
return canRead;
}
OFString modality;
OFString sopClassUID;
if (dcmFileFormat.getDataset()->findAndGetOFString(DCM_Modality, modality).good() && dcmFileFormat.getDataset()->findAndGetOFString(DCM_SOPClassUID, sopClassUID).good())
{
if (modality.compare("SEG") == 0)
{//atm we could read SegmentationStorage files. Other storage classes with "SEG" modality, e.g. SurfaceSegmentationStorage (1.2.840.10008.5.1.4.1.1.66.5), are not supported yet.
if (sopClassUID.compare("1.2.840.10008.5.1.4.1.1.66.4") == 0)
{
canRead = true;
}
else
{
canRead = false;
}
}
else
{
canRead = false;
}
}
return canRead;
}
MitkDICOMSEGIOMimeTypes::MitkDICOMSEGMimeType *MitkDICOMSEGIOMimeTypes::MitkDICOMSEGMimeType::Clone() const
{
return new MitkDICOMSEGMimeType(*this);
}
MitkDICOMSEGIOMimeTypes::MitkDICOMSEGMimeType MitkDICOMSEGIOMimeTypes::DICOMSEG_MIMETYPE()
{
return MitkDICOMSEGMimeType();
}
std::string MitkDICOMSEGIOMimeTypes::DICOMSEG_MIMETYPE_NAME()
{
// create a unique and sensible name for this mime type
return IOMimeTypes::DEFAULT_BASE_NAME() + ".image.dicom.seg";
}
}
diff --git a/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegmentationIO.cpp b/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegmentationIO.cpp
index e10302229c..d7a1a54de9 100644
--- a/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegmentationIO.cpp
+++ b/Modules/Multilabel/autoload/DICOMSegIO/mitkDICOMSegmentationIO.cpp
@@ -1,704 +1,699 @@
/*============================================================================
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 __mitkDICOMSegmentationIO__cpp
#define __mitkDICOMSegmentationIO__cpp
#include "mitkDICOMSegmentationIO.h"
#include "mitkDICOMSegIOMimeTypes.h"
#include "mitkDICOMSegmentationConstants.h"
#include <mitkDICOMDCMTKTagScanner.h>
#include <mitkDICOMIOHelper.h>
#include <mitkDICOMProperty.h>
#include <mitkIDICOMTagsOfInterest.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>
#include <mitkLocaleSwitch.h>
#include <mitkPropertyNameHelper.h>
// itk
#include <itkThresholdImageFilter.h>
// dcmqi
#include <dcmqi/ImageSEGConverter.h>
// us
#include <usGetModuleContext.h>
#include <usModuleContext.h>
namespace mitk
{
DICOMSegmentationIO::DICOMSegmentationIO()
: AbstractFileIO(LabelSetImage::GetStaticNameOfClass(),
mitk::MitkDICOMSEGIOMimeTypes::DICOMSEG_MIMETYPE_NAME(),
"DICOM Segmentation")
{
AbstractFileWriter::SetRanking(10);
AbstractFileReader::SetRanking(10);
this->RegisterService();
}
std::vector<mitk::DICOMTagPath> DICOMSegmentationIO::GetDICOMTagsOfInterest()
{
std::vector<mitk::DICOMTagPath> result;
result.emplace_back(DICOMSegmentationConstants::SEGMENT_SEQUENCE_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_NUMBER_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_LABEL_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_ALGORITHM_TYPE_PATH());
result.emplace_back(DICOMSegmentationConstants::ANATOMIC_REGION_SEQUENCE_PATH());
result.emplace_back(DICOMSegmentationConstants::ANATOMIC_REGION_CODE_VALUE_PATH());
result.emplace_back(DICOMSegmentationConstants::ANATOMIC_REGION_CODE_SCHEME_PATH());
result.emplace_back(DICOMSegmentationConstants::ANATOMIC_REGION_CODE_MEANING_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENTED_PROPERTY_CATEGORY_SEQUENCE_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_VALUE_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_SCHEME_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_MEANING_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENTED_PROPERTY_TYPE_SEQUENCE_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_VALUE_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_SCHEME_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_MEANING_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENTED_PROPERTY_MODIFIER_SEQUENCE_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_VALUE_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_SCHEME_PATH());
result.emplace_back(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_MEANING_PATH());
return result;
}
IFileIO::ConfidenceLevel DICOMSegmentationIO::GetWriterConfidenceLevel() const
{
if (AbstractFileIO::GetWriterConfidenceLevel() == Unsupported)
return Unsupported;
// Check if the input file is a segmentation
const LabelSetImage *input = dynamic_cast<const LabelSetImage *>(this->GetInput());
if (input)
{
if ((input->GetDimension() != 3))
{
MITK_INFO << "DICOM segmentation writer is tested only with 3D images, sorry.";
return Unsupported;
}
// Check if input file has dicom information for the referenced image (original DICOM image, e.g. CT) Still necessary, see write()
mitk::StringLookupTableProperty::Pointer dicomFilesProp =
dynamic_cast<mitk::StringLookupTableProperty *>(input->GetProperty("referenceFiles").GetPointer());
if (dicomFilesProp.IsNotNull())
return Supported;
}
return Unsupported;
}
void DICOMSegmentationIO::Write()
{
ValidateOutputLocation();
mitk::LocaleSwitch localeSwitch("C");
LocalFile localFile(this);
const std::string path = localFile.GetFileName();
auto input = dynamic_cast<const LabelSetImage *>(this->GetInput());
if (input == nullptr)
mitkThrow() << "Cannot write non-image data";
// Get DICOM information from referenced image
vector<std::unique_ptr<DcmDataset>> dcmDatasetsSourceImage;
std::unique_ptr<DcmFileFormat> readFileFormat(new DcmFileFormat());
try
{
// TODO: Generate dcmdataset witk DICOM tags from property list; ATM the source are the filepaths from the
// property list
mitk::StringLookupTableProperty::Pointer filesProp =
dynamic_cast<mitk::StringLookupTableProperty *>(input->GetProperty("referenceFiles").GetPointer());
if (filesProp.IsNull())
{
mitkThrow() << "No property with dicom file path.";
return;
}
StringLookupTable filesLut = filesProp->GetValue();
const StringLookupTable::LookupTableType &lookUpTableMap = filesLut.GetLookupTable();
for (const auto &it : lookUpTableMap)
{
const char *fileName = (it.second).c_str();
if (readFileFormat->loadFile(fileName, EXS_Unknown).good())
{
std::unique_ptr<DcmDataset> readDCMDataset(readFileFormat->getAndRemoveDataset());
dcmDatasetsSourceImage.push_back(std::move(readDCMDataset));
}
}
}
catch (const std::exception &e)
{
MITK_ERROR << "An error occurred while getting the dicom informations: " << e.what() << endl;
return;
}
// Iterate over all layers. For each a dcm file will be generated
for (unsigned int layer = 0; layer < input->GetNumberOfLayers(); ++layer)
{
vector<itkInternalImageType::Pointer> segmentations;
try
{
// Hack: Remove the const attribute to switch between the layer images. Normally you could get the different
// layer images by input->GetLayerImage(layer)
mitk::LabelSetImage *mitkLayerImage = const_cast<mitk::LabelSetImage *>(input);
mitkLayerImage->SetActiveLayer(layer);
// Cast mitk layer image to itk
ImageToItk<itkInputImageType>::Pointer imageToItkFilter = ImageToItk<itkInputImageType>::New();
imageToItkFilter->SetInput(mitkLayerImage);
// Cast from original itk type to dcmqi input itk image type
typedef itk::CastImageFilter<itkInputImageType, itkInternalImageType> castItkImageFilterType;
castItkImageFilterType::Pointer castFilter = castItkImageFilterType::New();
castFilter->SetInput(imageToItkFilter->GetOutput());
castFilter->Update();
itkInternalImageType::Pointer itkLabelImage = castFilter->GetOutput();
itkLabelImage->DisconnectPipeline();
// Iterate over all labels. For each label a segmentation image will be created
const LabelSet *labelSet = input->GetLabelSet(layer);
- auto labelIter = labelSet->IteratorConstBegin();
- // Ignore background label
- ++labelIter;
- for (; labelIter != labelSet->IteratorConstEnd(); ++labelIter)
+ for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelSet->IteratorConstEnd(); ++labelIter)
{
// Thresold over the image with the given label value
itk::ThresholdImageFilter<itkInternalImageType>::Pointer thresholdFilter =
itk::ThresholdImageFilter<itkInternalImageType>::New();
thresholdFilter->SetInput(itkLabelImage);
thresholdFilter->ThresholdOutside(labelIter->first, labelIter->first);
thresholdFilter->SetOutsideValue(0);
thresholdFilter->Update();
itkInternalImageType::Pointer segmentImage = thresholdFilter->GetOutput();
segmentImage->DisconnectPipeline();
segmentations.push_back(segmentImage);
}
}
catch (const itk::ExceptionObject &e)
{
MITK_ERROR << e.GetDescription() << endl;
return;
}
// Create segmentation meta information
const std::string tmpMetaInfoFile = this->CreateMetaDataJsonFile(layer);
MITK_INFO << "Writing image: " << path << std::endl;
try
{
//TODO is there a better way? Interface expects a vector of raw pointer.
vector<DcmDataset*> rawVecDataset;
for (const auto& dcmDataSet : dcmDatasetsSourceImage)
rawVecDataset.push_back(dcmDataSet.get());
// Convert itk segmentation images to dicom image
std::unique_ptr<dcmqi::ImageSEGConverter> converter = std::make_unique<dcmqi::ImageSEGConverter>();
std::unique_ptr<DcmDataset> result(converter->itkimage2dcmSegmentation(rawVecDataset, segmentations, tmpMetaInfoFile, false));
// Write dicom file
DcmFileFormat dcmFileFormat(result.get());
std::string filePath = path.substr(0, path.find_last_of("."));
// If there is more than one layer, we have to write more than 1 dicom file
if (input->GetNumberOfLayers() != 1)
filePath = filePath + std::to_string(layer) + ".dcm";
else
filePath = filePath + ".dcm";
dcmFileFormat.saveFile(filePath.c_str(), EXS_LittleEndianExplicit);
}
catch (const std::exception &e)
{
MITK_ERROR << "An error occurred during writing the DICOM Seg: " << e.what() << endl;
return;
}
} // Write a dcm file for the next layer
}
IFileIO::ConfidenceLevel DICOMSegmentationIO::GetReaderConfidenceLevel() const
{
if (AbstractFileIO::GetReaderConfidenceLevel() == Unsupported)
return Unsupported;
const std::string fileName = this->GetLocalFileName();
DcmFileFormat dcmFileFormat;
OFCondition status = dcmFileFormat.loadFile(fileName.c_str());
if (status.bad())
return Unsupported;
OFString modality;
if (dcmFileFormat.getDataset()->findAndGetOFString(DCM_Modality, modality).good())
{
if (modality.compare("SEG") == 0)
return Supported;
else
return Unsupported;
}
return Unsupported;
}
std::vector<BaseData::Pointer> DICOMSegmentationIO::DoRead()
{
mitk::LocaleSwitch localeSwitch("C");
LabelSetImage::Pointer labelSetImage;
std::vector<BaseData::Pointer> result;
const std::string path = this->GetLocalFileName();
MITK_INFO << "loading " << path << std::endl;
if (path.empty())
mitkThrow() << "Empty filename in mitk::ItkImageIO ";
try
{
// Get the dcm data set from file path
DcmFileFormat dcmFileFormat;
OFCondition status = dcmFileFormat.loadFile(path.c_str());
if (status.bad())
mitkThrow() << "Can't read the input file!";
DcmDataset *dataSet = dcmFileFormat.getDataset();
if (dataSet == nullptr)
mitkThrow() << "Can't read data from input file!";
//=============================== dcmqi part ====================================
// Read the DICOM SEG images (segItkImages) and DICOM tags (metaInfo)
std::unique_ptr<dcmqi::ImageSEGConverter> converter = std::make_unique<dcmqi::ImageSEGConverter>();
pair<map<unsigned, itkInternalImageType::Pointer>, string> dcmqiOutput =
converter->dcmSegmentation2itkimage(dataSet);
map<unsigned, itkInternalImageType::Pointer> segItkImages = dcmqiOutput.first;
dcmqi::JSONSegmentationMetaInformationHandler metaInfo(dcmqiOutput.second.c_str());
metaInfo.read();
MITK_INFO << "Input " << metaInfo.getJSONOutputAsString();
//===============================================================================
// Get the label information from segment attributes for each itk image
vector<map<unsigned, dcmqi::SegmentAttributes *>>::const_iterator segmentIter =
metaInfo.segmentsAttributesMappingList.begin();
// For each itk image add a layer to the LabelSetImage output
for (auto &element : segItkImages)
{
// Get the labeled image and cast it to mitkImage
typedef itk::CastImageFilter<itkInternalImageType, itkInputImageType> castItkImageFilterType;
castItkImageFilterType::Pointer castFilter = castItkImageFilterType::New();
castFilter->SetInput(element.second);
castFilter->Update();
Image::Pointer layerImage;
CastToMitkImage(castFilter->GetOutput(), layerImage);
// Get pixel value of the label
itkInternalImageType::ValueType segValue = 1;
typedef itk::ImageRegionIterator<const itkInternalImageType> IteratorType;
// Iterate over the image to find the pixel value of the label
IteratorType iter(element.second, element.second->GetLargestPossibleRegion());
iter.GoToBegin();
while (!iter.IsAtEnd())
{
itkInputImageType::PixelType value = iter.Get();
if (value != LabelSetImage::UnlabeledValue)
{
segValue = value;
break;
}
++iter;
}
// Get Segment information map
map<unsigned, dcmqi::SegmentAttributes *> segmentMap = (*segmentIter);
map<unsigned, dcmqi::SegmentAttributes *>::const_iterator segmentMapIter = (*segmentIter).begin();
dcmqi::SegmentAttributes *segmentAttribute = (*segmentMapIter).second;
OFString labelName;
if (segmentAttribute->getSegmentedPropertyTypeCodeSequence() != nullptr)
{
segmentAttribute->getSegmentedPropertyTypeCodeSequence()->getCodeMeaning(labelName);
if (segmentAttribute->getSegmentedPropertyTypeModifierCodeSequence() != nullptr)
{
OFString modifier;
segmentAttribute->getSegmentedPropertyTypeModifierCodeSequence()->getCodeMeaning(modifier);
labelName.append(" (").append(modifier).append(")");
}
}
else
{
labelName = std::to_string(segmentAttribute->getLabelID()).c_str();
if (labelName.empty())
labelName = "Unnamed";
}
float tmp[3] = { 0.0, 0.0, 0.0 };
if (segmentAttribute->getRecommendedDisplayRGBValue() != nullptr)
{
tmp[0] = segmentAttribute->getRecommendedDisplayRGBValue()[0] / 255.0;
tmp[1] = segmentAttribute->getRecommendedDisplayRGBValue()[1] / 255.0;
tmp[2] = segmentAttribute->getRecommendedDisplayRGBValue()[2] / 255.0;
}
Label *newLabel = nullptr;
// If labelSetImage do not exists (first image)
if (labelSetImage.IsNull())
{
// Initialize the labelSetImage with the read image
labelSetImage = LabelSetImage::New();
labelSetImage->InitializeByLabeledImage(layerImage);
// Already a label was generated, so set the information to this
newLabel = labelSetImage->GetActiveLabel(labelSetImage->GetActiveLayer());
newLabel->SetName(labelName.c_str());
newLabel->SetColor(Color(tmp));
newLabel->SetValue(segValue);
}
else
{
// Add a new layer to the labelSetImage. Background label is set automatically
labelSetImage->AddLayer(layerImage);
// Add new label
newLabel = new Label;
newLabel->SetName(labelName.c_str());
newLabel->SetColor(Color(tmp));
newLabel->SetValue(segValue);
labelSetImage->GetLabelSet(labelSetImage->GetActiveLayer())->AddLabel(newLabel);
}
// Add some more label properties
this->SetLabelProperties(newLabel, segmentAttribute);
++segmentIter;
}
labelSetImage->GetLabelSet()->SetAllLabelsVisible(true);
// Add some general DICOM Segmentation properties
mitk::IDICOMTagsOfInterest *toiSrv = DICOMIOHelper::GetTagsOfInterestService();
auto tagsOfInterest = toiSrv->GetTagsOfInterest();
DICOMTagPathList tagsOfInterestList;
for (const auto &tag : tagsOfInterest)
{
tagsOfInterestList.push_back(tag.first);
}
mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New();
scanner->SetInputFiles({ GetInputLocation() });
scanner->AddTagPaths(tagsOfInterestList);
scanner->Scan();
mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList();
if (frames.empty())
{
MITK_ERROR << "Error reading the DICOM Seg file" << std::endl;
return result;
}
auto findings = DICOMIOHelper::ExtractPathsOfInterest(tagsOfInterestList, frames);
DICOMIOHelper::SetProperties(labelSetImage, findings);
// Set active layer to the first layer of the labelset image
if (labelSetImage->GetNumberOfLayers() > 1 && labelSetImage->GetActiveLayer() != 0)
labelSetImage->SetActiveLayer(0);
}
catch (const std::exception &e)
{
MITK_ERROR << "An error occurred while reading the DICOM Seg file: " << e.what();
return result;
}
catch (...)
{
MITK_ERROR << "An error occurred in dcmqi while reading the DICOM Seg file";
return result;
}
result.push_back(labelSetImage.GetPointer());
return result;
}
const std::string mitk::DICOMSegmentationIO::CreateMetaDataJsonFile(int layer)
{
const mitk::LabelSetImage *image = dynamic_cast<const mitk::LabelSetImage *>(this->GetInput());
const std::string output;
dcmqi::JSONSegmentationMetaInformationHandler handler;
// 1. Metadata attributes that will be listed in the resulting DICOM SEG object
std::string contentCreatorName;
if (!image->GetPropertyList()->GetStringProperty(GeneratePropertyNameForDICOMTag(0x0070, 0x0084).c_str(),
contentCreatorName))
contentCreatorName = "MITK";
handler.setContentCreatorName(contentCreatorName);
std::string clinicalTrailSeriesId;
if (!image->GetPropertyList()->GetStringProperty(GeneratePropertyNameForDICOMTag(0x0012, 0x0071).c_str(),
clinicalTrailSeriesId))
clinicalTrailSeriesId = "Session 1";
handler.setClinicalTrialSeriesID(clinicalTrailSeriesId);
std::string clinicalTrialTimePointID;
if (!image->GetPropertyList()->GetStringProperty(GeneratePropertyNameForDICOMTag(0x0012, 0x0050).c_str(),
clinicalTrialTimePointID))
clinicalTrialTimePointID = "0";
handler.setClinicalTrialTimePointID(clinicalTrialTimePointID);
std::string clinicalTrialCoordinatingCenterName = "";
if (!image->GetPropertyList()->GetStringProperty(GeneratePropertyNameForDICOMTag(0x0012, 0x0060).c_str(),
clinicalTrialCoordinatingCenterName))
clinicalTrialCoordinatingCenterName = "Unknown";
handler.setClinicalTrialCoordinatingCenterName(clinicalTrialCoordinatingCenterName);
std::string seriesDescription;
if (!image->GetPropertyList()->GetStringProperty("name", seriesDescription))
seriesDescription = "MITK Segmentation";
handler.setSeriesDescription(seriesDescription);
handler.setSeriesNumber("0" + std::to_string(layer));
handler.setInstanceNumber("1");
handler.setBodyPartExamined("");
const LabelSet *labelSet = image->GetLabelSet(layer);
- auto labelIter = labelSet->IteratorConstBegin();
- // Ignore background label
- ++labelIter;
- for (; labelIter != labelSet->IteratorConstEnd(); ++labelIter)
+ for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelSet->IteratorConstEnd(); ++labelIter)
{
const Label *label = labelIter->second;
if (label != nullptr)
{
TemporoSpatialStringProperty *segmentNumberProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_NUMBER_PATH()).c_str()));
TemporoSpatialStringProperty *segmentLabelProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_LABEL_PATH()).c_str()));
TemporoSpatialStringProperty *algorithmTypeProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_ALGORITHM_TYPE_PATH()).c_str()));
TemporoSpatialStringProperty *segmentCategoryCodeValueProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_VALUE_PATH()).c_str()));
TemporoSpatialStringProperty *segmentCategoryCodeSchemeProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_SCHEME_PATH()).c_str()));
TemporoSpatialStringProperty *segmentCategoryCodeMeaningProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_MEANING_PATH()).c_str()));
TemporoSpatialStringProperty *segmentTypeCodeValueProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_VALUE_PATH()).c_str()));
TemporoSpatialStringProperty *segmentTypeCodeSchemeProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_SCHEME_PATH()).c_str()));
TemporoSpatialStringProperty *segmentTypeCodeMeaningProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_MEANING_PATH()).c_str()));
TemporoSpatialStringProperty *segmentModifierCodeValueProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_VALUE_PATH()).c_str()));
TemporoSpatialStringProperty *segmentModifierCodeSchemeProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_SCHEME_PATH()).c_str()));
TemporoSpatialStringProperty *segmentModifierCodeMeaningProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(label->GetProperty(
mitk::DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_MEANING_PATH()).c_str()));
dcmqi::SegmentAttributes *segmentAttribute = nullptr;
if (segmentNumberProp->GetValue() == "")
{
MITK_ERROR << "Something went wrong with the label ID.";
}
else
{
int labelId = std::stoi(segmentNumberProp->GetValue());
segmentAttribute = handler.createAndGetNewSegment(labelId);
}
if (segmentAttribute != nullptr)
{
+ segmentAttribute->setSegmentLabel(segmentLabelProp->GetValueAsString());
segmentAttribute->setSegmentDescription(segmentLabelProp->GetValueAsString());
segmentAttribute->setSegmentAlgorithmType(algorithmTypeProp->GetValueAsString());
segmentAttribute->setSegmentAlgorithmName("MITK Segmentation");
if (segmentCategoryCodeValueProp != nullptr && segmentCategoryCodeSchemeProp != nullptr &&
segmentCategoryCodeMeaningProp != nullptr)
segmentAttribute->setSegmentedPropertyCategoryCodeSequence(
segmentCategoryCodeValueProp->GetValueAsString(),
segmentCategoryCodeSchemeProp->GetValueAsString(),
segmentCategoryCodeMeaningProp->GetValueAsString());
else
// some default values
segmentAttribute->setSegmentedPropertyCategoryCodeSequence(
"M-01000", "SRT", "Morphologically Altered Structure");
if (segmentTypeCodeValueProp != nullptr && segmentTypeCodeSchemeProp != nullptr &&
segmentTypeCodeMeaningProp != nullptr)
{
segmentAttribute->setSegmentedPropertyTypeCodeSequence(segmentTypeCodeValueProp->GetValueAsString(),
segmentTypeCodeSchemeProp->GetValueAsString(),
segmentTypeCodeMeaningProp->GetValueAsString());
handler.setBodyPartExamined(segmentTypeCodeMeaningProp->GetValueAsString());
}
else
{
// some default values
segmentAttribute->setSegmentedPropertyTypeCodeSequence("M-03000", "SRT", "Mass");
handler.setBodyPartExamined("Mass");
}
if (segmentModifierCodeValueProp != nullptr && segmentModifierCodeSchemeProp != nullptr &&
segmentModifierCodeMeaningProp != nullptr)
segmentAttribute->setSegmentedPropertyTypeModifierCodeSequence(
segmentModifierCodeValueProp->GetValueAsString(),
segmentModifierCodeSchemeProp->GetValueAsString(),
segmentModifierCodeMeaningProp->GetValueAsString());
Color color = label->GetColor();
segmentAttribute->setRecommendedDisplayRGBValue(color[0] * 255, color[1] * 255, color[2] * 255);
}
}
}
return handler.getJSONOutputAsString();
}
void mitk::DICOMSegmentationIO::SetLabelProperties(mitk::Label *label, dcmqi::SegmentAttributes *segmentAttribute)
{
// Segment Number:Identification number of the segment.The value of Segment Number(0062, 0004) shall be unique
// within the Segmentation instance in which it is created
label->SetProperty(DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_NUMBER_PATH()).c_str(),
TemporoSpatialStringProperty::New(std::to_string(label->GetValue())));
// Segment Label: User-defined label identifying this segment.
label->SetProperty(DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_LABEL_PATH()).c_str(),
TemporoSpatialStringProperty::New(label->GetName()));
// Segment Algorithm Type: Type of algorithm used to generate the segment.
if (!segmentAttribute->getSegmentAlgorithmType().empty())
label->SetProperty(DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_ALGORITHM_TYPE_PATH()).c_str(),
TemporoSpatialStringProperty::New(segmentAttribute->getSegmentAlgorithmType()));
// Add Segmented Property Category Code Sequence tags
auto categoryCodeSequence = segmentAttribute->getSegmentedPropertyCategoryCodeSequence();
if (categoryCodeSequence != nullptr)
{
OFString codeValue; // (0008,0100) Code Value
categoryCodeSequence->getCodeValue(codeValue);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_VALUE_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeValue.c_str()));
OFString codeScheme; // (0008,0102) Coding Scheme Designator
categoryCodeSequence->getCodingSchemeDesignator(codeScheme);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_SCHEME_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeScheme.c_str()));
OFString codeMeaning; // (0008,0104) Code Meaning
categoryCodeSequence->getCodeMeaning(codeMeaning);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_MEANING_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeMeaning.c_str()));
}
// Add Segmented Property Type Code Sequence tags
auto typeCodeSequence = segmentAttribute->getSegmentedPropertyTypeCodeSequence();
if (typeCodeSequence != nullptr)
{
OFString codeValue; // (0008,0100) Code Value
typeCodeSequence->getCodeValue(codeValue);
label->SetProperty(DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_VALUE_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeValue.c_str()));
OFString codeScheme; // (0008,0102) Coding Scheme Designator
typeCodeSequence->getCodingSchemeDesignator(codeScheme);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_SCHEME_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeScheme.c_str()));
OFString codeMeaning; // (0008,0104) Code Meaning
typeCodeSequence->getCodeMeaning(codeMeaning);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_MEANING_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeMeaning.c_str()));
}
// Add Segmented Property Type Modifier Code Sequence tags
auto modifierCodeSequence = segmentAttribute->getSegmentedPropertyTypeModifierCodeSequence();
if (modifierCodeSequence != nullptr)
{
OFString codeValue; // (0008,0100) Code Value
modifierCodeSequence->getCodeValue(codeValue);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_VALUE_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeValue.c_str()));
OFString codeScheme; // (0008,0102) Coding Scheme Designator
modifierCodeSequence->getCodingSchemeDesignator(codeScheme);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_SCHEME_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeScheme.c_str()));
OFString codeMeaning; // (0008,0104) Code Meaning
modifierCodeSequence->getCodeMeaning(codeMeaning);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_MODIFIER_CODE_MEANING_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeMeaning.c_str()));
}
// Add Atomic RegionSequence tags
auto atomicRegionSequence = segmentAttribute->getAnatomicRegionSequence();
if (atomicRegionSequence != nullptr)
{
OFString codeValue; // (0008,0100) Code Value
atomicRegionSequence->getCodeValue(codeValue);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::ANATOMIC_REGION_CODE_VALUE_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeValue.c_str()));
OFString codeScheme; // (0008,0102) Coding Scheme Designator
atomicRegionSequence->getCodingSchemeDesignator(codeScheme);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::ANATOMIC_REGION_CODE_SCHEME_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeScheme.c_str()));
OFString codeMeaning; // (0008,0104) Code Meaning
atomicRegionSequence->getCodeMeaning(codeMeaning);
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::ANATOMIC_REGION_CODE_MEANING_PATH()).c_str(),
TemporoSpatialStringProperty::New(codeMeaning.c_str()));
}
}
DICOMSegmentationIO *DICOMSegmentationIO::IOClone() const { return new DICOMSegmentationIO(*this); }
} // namespace
#endif //__mitkDICOMSegmentationIO__cpp
diff --git a/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp b/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp
index aee9aa0727..3f54523643 100644
--- a/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp
+++ b/Modules/Multilabel/autoload/IO/mitkMultilabelIOMimeTypes.cpp
@@ -1,146 +1,146 @@
/*============================================================================
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 "mitkMultilabelIOMimeTypes.h"
#include <mitkIOMimeTypes.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <filesystem>
#include <fstream>
#include <nlohmann/json.hpp>
#include <itkNrrdImageIO.h>
#include "itkMetaDataObject.h"
mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType::MitkSegmentationTaskListMimeType()
: CustomMimeType(SEGMENTATIONTASKLIST_MIMETYPE_NAME())
{
this->AddExtension("json");
this->SetCategory("MITK Segmentation Task List");
this->SetComment("MITK Segmentation Task List");
}
bool mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType::AppliesTo(const std::string& path) const
{
bool result = CustomMimeType::AppliesTo(path);
if (!std::filesystem::exists(path)) // T18572
return result;
std::ifstream file(path);
if (!file.is_open())
return false;
auto json = nlohmann::json::parse(file, nullptr, false);
if (json.is_discarded() || !json.is_object())
return false;
if ("MITK Segmentation Task List" != json.value("FileFormat", ""))
return false;
if (1 != json.value<int>("Version", 0))
return false;
return true;
}
mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType* mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType::Clone() const
{
return new MitkSegmentationTaskListMimeType(*this);
}
mitk::MitkMultilabelIOMimeTypes::MitkSegmentationTaskListMimeType mitk::MitkMultilabelIOMimeTypes::SEGMENTATIONTASKLIST_MIMETYPE()
{
return MitkSegmentationTaskListMimeType();
}
std::string mitk::MitkMultilabelIOMimeTypes::SEGMENTATIONTASKLIST_MIMETYPE_NAME()
{
return IOMimeTypes::DEFAULT_BASE_NAME() + ".segmentationtasklist";
}
mitk::MitkMultilabelIOMimeTypes::LegacyLabelSetMimeType::LegacyLabelSetMimeType()
: CustomMimeType(LEGACYLABELSET_MIMETYPE_NAME())
{
this->AddExtension("nrrd");
this->SetCategory("MITK LabelSetImage");
this->SetComment("MITK LabelSetImage (legacy format)");
}
bool mitk::MitkMultilabelIOMimeTypes::LegacyLabelSetMimeType::AppliesTo(const std::string& path) const
{
bool canRead = CustomMimeType::AppliesTo(path);
if (!std::filesystem::exists(path)) // T18572
return canRead;
if (!canRead)
{
return false;
}
std::string value("");
try
{
std::ifstream file(path);
if (!file.is_open())
return false;
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
io->SetFileName(path);
io->ReadImageInformation();
itk::MetaDataDictionary imgMetaDataDictionary = io->GetMetaDataDictionary();
itk::ExposeMetaData<std::string>(imgMetaDataDictionary, "modality", value);
}
catch(const std::exception& e)
{
MITK_DEBUG << "Error while try to anylize NRRD file for LegacyLabelSetMimeType. File: " << path <<"; Error: " << e.what();
}
catch(...)
{
MITK_DEBUG << "Unkown error while try to anylize NRRD file for LegacyLabelSetMimeType. File: " << path;
}
if (value.compare("org.mitk.image.multilabel") != 0)
{
return false;
}
return true;
}
mitk::MitkMultilabelIOMimeTypes::LegacyLabelSetMimeType* mitk::MitkMultilabelIOMimeTypes::LegacyLabelSetMimeType::Clone() const
{
return new LegacyLabelSetMimeType(*this);
}
mitk::MitkMultilabelIOMimeTypes::LegacyLabelSetMimeType mitk::MitkMultilabelIOMimeTypes::LEGACYLABELSET_MIMETYPE()
{
return LegacyLabelSetMimeType();
}
std::string mitk::MitkMultilabelIOMimeTypes::LEGACYLABELSET_MIMETYPE_NAME()
{
return IOMimeTypes::DEFAULT_BASE_NAME() + ".legacylabelsetimage";
}
std::vector<mitk::CustomMimeType*> mitk::MitkMultilabelIOMimeTypes::Get()
{
std::vector<CustomMimeType*> mimeTypes;
mimeTypes.push_back(SEGMENTATIONTASKLIST_MIMETYPE().Clone());
mimeTypes.push_back(LEGACYLABELSET_MIMETYPE().Clone());
return mimeTypes;
}
diff --git a/Modules/Multilabel/mitkLabelSetImage.cpp b/Modules/Multilabel/mitkLabelSetImage.cpp
index 5dabaf8adb..48cfd421c1 100644
--- a/Modules/Multilabel/mitkLabelSetImage.cpp
+++ b/Modules/Multilabel/mitkLabelSetImage.cpp
@@ -1,1553 +1,1562 @@
/*============================================================================
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 "mitkLabelSetImage.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageCast.h"
#include "mitkImagePixelReadAccessor.h"
#include "mitkImagePixelWriteAccessor.h"
#include "mitkInteractionConst.h"
#include "mitkLookupTableProperty.h"
#include "mitkPadImageFilter.h"
#include "mitkRenderingManager.h"
#include "mitkDICOMSegmentationPropertyHelper.h"
#include "mitkDICOMQIPropertyHelper.h"
#include <vtkCell.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <itkImageRegionIterator.h>
#include <itkQuadEdgeMesh.h>
#include <itkTriangleMeshToBinaryImageFilter.h>
#include <itkLabelGeometryImageFilter.h>
//#include <itkRelabelComponentImageFilter.h>
#include <itkCommand.h>
#include <itkBinaryFunctorImageFilter.h>
template <typename TPixel, unsigned int VDimensions>
void SetToZero(itk::Image<TPixel, VDimensions> *source)
{
source->FillBuffer(0);
}
template <unsigned int VImageDimension = 3>
void CreateLabelMaskProcessing(mitk::Image *layerImage, mitk::Image *mask, mitk::LabelSet::PixelType index)
{
mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(layerImage);
mitk::ImagePixelWriteAccessor<mitk::LabelSet::PixelType, VImageDimension> writeAccessor(mask);
std::size_t numberOfPixels = 1;
for (int dim = 0; dim < static_cast<int>(VImageDimension); ++dim)
numberOfPixels *= static_cast<std::size_t>(readAccessor.GetDimension(dim));
auto src = readAccessor.GetData();
auto dest = writeAccessor.GetData();
for (std::size_t i = 0; i < numberOfPixels; ++i)
{
if (index == *(src + i))
*(dest + i) = 1;
}
}
mitk::LabelSetImage::LabelSetImage()
: mitk::Image(), m_UnlabeledLabelLock(false), m_ActiveLayer(0), m_activeLayerInvalid(false)
{
// Add some DICOM Tags as properties to segmentation image
DICOMSegmentationPropertyHelper::DeriveDICOMSegmentationProperties(this);
}
mitk::LabelSetImage::LabelSetImage(const mitk::LabelSetImage &other)
: Image(other),
m_UnlabeledLabelLock(other.m_UnlabeledLabelLock),
m_ActiveLayer(other.GetActiveLayer()),
m_activeLayerInvalid(false)
{
for (unsigned int i = 0; i < other.GetNumberOfLayers(); i++)
{
// Clone LabelSet data
mitk::LabelSet::Pointer lsClone = other.GetLabelSet(i)->Clone();
this->RegisterLabelSet(lsClone);
m_LabelSetContainer.push_back(lsClone);
// clone layer Image data
mitk::Image::Pointer liClone = other.GetLayerImage(i)->Clone();
m_LayerContainer.push_back(liClone);
}
+ this->ReinitMaps();
+
// Add some DICOM Tags as properties to segmentation image
DICOMSegmentationPropertyHelper::DeriveDICOMSegmentationProperties(this);
}
void mitk::LabelSetImage::OnLabelSetModified()
{
Superclass::Modified();
}
void mitk::LabelSetImage::Initialize(const mitk::Image *other)
{
mitk::PixelType pixelType(mitk::MakeScalarPixelType<LabelSetImage::PixelType>());
if (other->GetDimension() == 2)
{
const unsigned int dimensions[] = {other->GetDimension(0), other->GetDimension(1), 1};
Superclass::Initialize(pixelType, 3, dimensions);
}
else
{
Superclass::Initialize(pixelType, other->GetDimension(), other->GetDimensions());
}
auto originalGeometry = other->GetTimeGeometry()->Clone();
this->SetTimeGeometry(originalGeometry);
// initialize image memory to zero
if (4 == this->GetDimension())
{
AccessFixedDimensionByItk(this, SetToZero, 4);
}
else
{
AccessByItk(this, SetToZero);
}
// Transfer some general DICOM properties from the source image to derived image (e.g. Patient information,...)
DICOMQIPropertyHelper::DeriveDICOMSourceProperties(other, this);
// Add a inital LabelSet ans corresponding image data to the stack
if (this->GetNumberOfLayers() == 0)
{
AddLayer();
}
}
mitk::LabelSetImage::~LabelSetImage()
{
for (auto ls : m_LabelSetContainer)
{
this->ReleaseLabelSet(ls);
}
m_LabelSetContainer.clear();
}
mitk::Image *mitk::LabelSetImage::GetLayerImage(unsigned int layer)
{
return m_LayerContainer[layer];
}
const mitk::Image *mitk::LabelSetImage::GetLayerImage(unsigned int layer) const
{
return m_LayerContainer[layer];
}
unsigned int mitk::LabelSetImage::GetActiveLayer() const
{
return m_ActiveLayer;
}
unsigned int mitk::LabelSetImage::GetNumberOfLayers() const
{
return m_LabelSetContainer.size();
}
void mitk::LabelSetImage::RegisterLabelSet(mitk::LabelSet* ls)
{
// add modified event listener to LabelSet (listen to LabelSet changes)
itk::SimpleMemberCommand<Self>::Pointer command = itk::SimpleMemberCommand<Self>::New();
command->SetCallbackFunction(this, &mitk::LabelSetImage::OnLabelSetModified);
ls->AddObserver(itk::ModifiedEvent(), command);
ls->AddLabelEvent.AddListener(mitk::MessageDelegate1<LabelSetImage, LabelValueType>(
this, &LabelSetImage::OnLabelAdded));
ls->ModifyLabelEvent.AddListener(mitk::MessageDelegate1<LabelSetImage, LabelValueType>(
this, &LabelSetImage::OnLabelModified));
ls->RemoveLabelEvent.AddListener(mitk::MessageDelegate1<LabelSetImage, LabelValueType>(
this, &LabelSetImage::OnLabelRemoved));
ls->m_ReservedLabelValuesFunctor = [this]() {return this->GetUsedLabelValues(); };
}
void mitk::LabelSetImage::ReleaseLabelSet(mitk::LabelSet* ls)
{
ls->RemoveAllObservers();
ls->AddLabelEvent.RemoveListener(mitk::MessageDelegate1<LabelSetImage, LabelValueType>(
this, &LabelSetImage::OnLabelAdded));
ls->ModifyLabelEvent.RemoveListener(mitk::MessageDelegate1<LabelSetImage, LabelValueType>(
this, &LabelSetImage::OnLabelModified));
ls->RemoveLabelEvent.RemoveListener(mitk::MessageDelegate1<LabelSetImage, LabelValueType>(
this, &LabelSetImage::OnLabelRemoved));
ls->m_ReservedLabelValuesFunctor = nullptr;
}
void mitk::LabelSetImage::RemoveLayer()
{
int layerToDelete = GetActiveLayer();
// remove all observers from active label set
GetLabelSet(layerToDelete)->RemoveAllObservers();
// set the active layer to one below, if exists.
if (layerToDelete != 0)
{
SetActiveLayer(layerToDelete - 1);
}
else
{
// we are deleting layer zero, it should not be copied back into the vector
m_activeLayerInvalid = true;
}
// remove labelset and image data
m_LabelSetContainer.erase(m_LabelSetContainer.begin() + layerToDelete);
m_LayerContainer.erase(m_LayerContainer.begin() + layerToDelete);
if (layerToDelete == 0)
{
this->SetActiveLayer(layerToDelete);
}
this->OnGroupRemoved(layerToDelete);
this->Modified();
}
void mitk::LabelSetImage::RemoveGroup(GroupIndexType indexToDelete)
{
const auto activeIndex = GetActiveLayer();
// remove all observers from active label set
GetLabelSet(indexToDelete)->RemoveAllObservers();
// set the active layer to one below, if exists.
if (activeIndex>indexToDelete)
{
SetActiveLayer(activeIndex - 1);
}
else if (activeIndex==indexToDelete)
{
// we are deleting layer zero, it should not be copied back into the vector
m_activeLayerInvalid = true;
}
// remove labelset and image data
m_LabelSetContainer.erase(m_LabelSetContainer.begin() + indexToDelete);
m_LayerContainer.erase(m_LayerContainer.begin() + indexToDelete);
if (indexToDelete == activeIndex)
{ //enforces the new active layer to be set and copied
auto newActiveIndex = indexToDelete < GetNumberOfLayers() ? indexToDelete : GetNumberOfLayers() - 1;
this->SetActiveLayer(newActiveIndex);
}
this->OnGroupRemoved(indexToDelete);
this->Modified();
}
mitk::LabelSetImage::LabelValueVectorType mitk::LabelSetImage::GetUsedLabelValues() const
{
LabelValueVectorType result = { UnlabeledValue };
for (auto [value, label] : m_LabelMap)
{
result.emplace_back(value);
}
return result;
}
unsigned int mitk::LabelSetImage::AddLayer(mitk::LabelSet::Pointer labelSet)
{
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->Initialize(this->GetPixelType(),
this->GetDimension(),
this->GetDimensions(),
this->GetImageDescriptor()->GetNumberOfChannels());
newImage->SetTimeGeometry(this->GetTimeGeometry()->Clone());
if (newImage->GetDimension() < 4)
{
AccessByItk(newImage, SetToZero);
}
else
{
AccessFixedDimensionByItk(newImage, SetToZero, 4);
}
return this->AddLayer(newImage, labelSet);
}
unsigned int mitk::LabelSetImage::AddLayer(mitk::Image::Pointer layerImage, mitk::LabelSet::Pointer labelSet)
{
unsigned int newLabelSetId = m_LayerContainer.size();
// Add labelset to layer
mitk::LabelSet::Pointer ls;
if (labelSet.IsNotNull())
{
ls = labelSet;
}
else
{
ls = mitk::LabelSet::New();
ls->SetActiveLabel(UnlabeledValue);
}
ls->SetLayer(newLabelSetId);
// push a new working image for the new layer
m_LayerContainer.push_back(layerImage);
// push a new labelset for the new layer
m_LabelSetContainer.push_back(ls);
RegisterLabelSet(ls);
this->ReinitMaps();
SetActiveLayer(newLabelSetId);
this->Modified();
this->OnGroupAdded(newLabelSetId);
return newLabelSetId;
}
void mitk::LabelSetImage::AddLabelSetToLayer(const unsigned int layerIdx, const mitk::LabelSet* labelSet)
{
if (m_LayerContainer.size() <= layerIdx)
{
mitkThrow() << "Trying to add labelSet to non-existing layer.";
}
auto clonedLabelSet = labelSet->Clone();
this->RegisterLabelSet(clonedLabelSet);
std::vector<GroupIndexType> addedGroups;
if (layerIdx < m_LabelSetContainer.size())
{
if (m_LabelSetContainer[layerIdx].IsNotNull())
{
this->ReleaseLabelSet(m_LabelSetContainer[layerIdx]);
}
m_LabelSetContainer[layerIdx] = clonedLabelSet;
}
else
{
while (layerIdx >= m_LabelSetContainer.size())
{
mitk::LabelSet::Pointer defaultLabelSet = mitk::LabelSet::New();
defaultLabelSet->SetActiveLabel(UnlabeledValue);
defaultLabelSet->SetLayer(m_LabelSetContainer.size());
this->RegisterLabelSet(defaultLabelSet);
this->ReinitMaps();
m_LabelSetContainer.push_back(defaultLabelSet);
addedGroups.emplace_back(m_LabelSetContainer.size() - 1);
}
m_LabelSetContainer.push_back(clonedLabelSet);
addedGroups.emplace_back(m_LabelSetContainer.size() - 1);
}
this->ReinitMaps();
for (auto groupID : addedGroups)
{
this->m_GroupAddedMessage.Send(groupID);
}
}
void mitk::LabelSetImage::SetActiveLayer(unsigned int layer)
{
try
{
if (4 == this->GetDimension())
{
if ((layer != GetActiveLayer() || m_activeLayerInvalid) && (layer < this->GetNumberOfLayers()))
{
BeforeChangeLayerEvent.Send();
if (m_activeLayerInvalid)
{
// We should not write the invalid layer back to the vector
m_activeLayerInvalid = false;
}
else
{
AccessFixedDimensionByItk_n(this, ImageToLayerContainerProcessing, 4, (GetActiveLayer()));
}
m_ActiveLayer = layer; // only at this place m_ActiveLayer should be manipulated!!! Use Getter and Setter
AccessFixedDimensionByItk_n(this, LayerContainerToImageProcessing, 4, (GetActiveLayer()));
AfterChangeLayerEvent.Send();
}
}
else
{
if ((layer != GetActiveLayer() || m_activeLayerInvalid) && (layer < this->GetNumberOfLayers()))
{
BeforeChangeLayerEvent.Send();
if (m_activeLayerInvalid)
{
// We should not write the invalid layer back to the vector
m_activeLayerInvalid = false;
}
else
{
AccessByItk_1(this, ImageToLayerContainerProcessing, GetActiveLayer());
}
m_ActiveLayer = layer; // only at this place m_ActiveLayer should be manipulated!!! Use Getter and Setter
AccessByItk_1(this, LayerContainerToImageProcessing, GetActiveLayer());
AfterChangeLayerEvent.Send();
}
}
}
catch (itk::ExceptionObject &e)
{
mitkThrow() << e.GetDescription();
}
this->Modified();
}
void mitk::LabelSetImage::ClearBuffer()
{
try
{
if (this->GetDimension() == 4)
{ //remark: this extra branch was added, because LabelSetImage instances can be
//dynamic (4D), but AccessByItk by support only supports 2D and 3D.
//The option to change the CMake default dimensions for AccessByItk was
//dropped (for details see discussion in T28756)
AccessFixedDimensionByItk(this, ClearBufferProcessing,4);
}
else
{
AccessByItk(this, ClearBufferProcessing);
}
this->Modified();
}
catch (itk::ExceptionObject &e)
{
mitkThrow() << e.GetDescription();
}
}
bool mitk::LabelSetImage::ExistLabel(PixelType pixelValue) const
{
bool exist = false;
for (unsigned int lidx = 0; lidx < GetNumberOfLayers(); lidx++)
exist |= m_LabelSetContainer[lidx]->ExistLabel(pixelValue);
return exist;
}
bool mitk::LabelSetImage::ExistLabel(PixelType pixelValue, unsigned int layer) const
{
bool exist = m_LabelSetContainer[layer]->ExistLabel(pixelValue);
return exist;
}
bool mitk::LabelSetImage::ExistLabelSet(unsigned int layer) const
{
return layer < m_LabelSetContainer.size();
}
void mitk::LabelSetImage::MergeLabel(PixelType pixelValue, PixelType sourcePixelValue, unsigned int layer)
{
try
{
AccessByItk_2(this, MergeLabelProcessing, pixelValue, sourcePixelValue);
}
catch (itk::ExceptionObject &e)
{
mitkThrow() << e.GetDescription();
}
GetLabelSet(layer)->SetActiveLabel(pixelValue);
this->m_LabelModifiedMessage.Send(sourcePixelValue);
this->m_LabelModifiedMessage.Send(pixelValue);
this->m_LabelsChangedMessage.Send({ sourcePixelValue, pixelValue });
Modified();
}
void mitk::LabelSetImage::MergeLabels(PixelType pixelValue, const std::vector<PixelType>& vectorOfSourcePixelValues, unsigned int layer)
{
try
{
for (unsigned int idx = 0; idx < vectorOfSourcePixelValues.size(); idx++)
{
AccessByItk_2(this, MergeLabelProcessing, pixelValue, vectorOfSourcePixelValues[idx]);
this->m_LabelModifiedMessage.Send(vectorOfSourcePixelValues[idx]);
}
}
catch (itk::ExceptionObject &e)
{
mitkThrow() << e.GetDescription();
}
GetLabelSet(layer)->SetActiveLabel(pixelValue);
this->m_LabelModifiedMessage.Send(pixelValue);
auto modifiedValues = vectorOfSourcePixelValues;
modifiedValues.push_back(pixelValue);
this->m_LabelsChangedMessage.Send(modifiedValues);
Modified();
}
void mitk::LabelSetImage::RemoveLabel(LabelValueType pixelValue)
{
auto groupID = this->GetGroupIndexOfLabel(pixelValue);
//first erase the pixel content (also triggers a LabelModified event)
this->EraseLabel(pixelValue);
//now remove the label entry itself
this->GetLabelSet(groupID)->RemoveLabel(pixelValue);
// in the interim version triggered by label set events: this->m_LabelRemovedMessage.Send(pixelValue);
this->m_LabelsChangedMessage.Send({ pixelValue });
this->m_GroupModifiedMessage.Send(groupID);
}
void mitk::LabelSetImage::RemoveLabels(const std::vector<PixelType>& VectorOfLabelPixelValues)
{
for (unsigned int idx = 0; idx < VectorOfLabelPixelValues.size(); idx++)
{
this->RemoveLabel(VectorOfLabelPixelValues[idx]);
this->m_LabelsChangedMessage.Send({ VectorOfLabelPixelValues[idx] });
}
}
void mitk::LabelSetImage::EraseLabel(PixelType pixelValue)
{
try
{
auto groupID = this->GetGroupIndexOfLabel(pixelValue);
mitk::Image* groupImage = this->GetActiveLayer() != groupID
? this->GetLayerImage(groupID)
: this;
if (4 == this->GetDimension())
{
AccessFixedDimensionByItk_1(groupImage, EraseLabelProcessing, 4, pixelValue);
}
else
{
AccessByItk_1(groupImage, EraseLabelProcessing, pixelValue);
}
}
catch (const itk::ExceptionObject& e)
{
mitkThrow() << e.GetDescription();
}
this->m_LabelModifiedMessage.Send(pixelValue);
this->m_LabelsChangedMessage.Send({ pixelValue });
Modified();
}
void mitk::LabelSetImage::EraseLabels(const std::vector<PixelType>& VectorOfLabelPixelValues)
{
for (unsigned int idx = 0; idx < VectorOfLabelPixelValues.size(); idx++)
{
this->EraseLabel(VectorOfLabelPixelValues[idx]);
}
}
mitk::Label *mitk::LabelSetImage::GetActiveLabel(unsigned int layer)
{
if (m_LabelSetContainer.size() <= layer)
return nullptr;
else
return m_LabelSetContainer[layer]->GetActiveLabel();
}
const mitk::Label* mitk::LabelSetImage::GetActiveLabel(unsigned int layer) const
{
if (m_LabelSetContainer.size() <= layer)
return nullptr;
else
return m_LabelSetContainer[layer]->GetActiveLabel();
}
mitk::Label *mitk::LabelSetImage::GetLabel(PixelType pixelValue, unsigned int layer) const
{
if (m_LabelSetContainer.size() <= layer)
return nullptr;
else
return m_LabelSetContainer[layer]->GetLabel(pixelValue);
}
mitk::LabelSet *mitk::LabelSetImage::GetLabelSet(unsigned int layer)
{
if (m_LabelSetContainer.size() <= layer)
return nullptr;
else
return m_LabelSetContainer[layer].GetPointer();
}
const mitk::LabelSet *mitk::LabelSetImage::GetLabelSet(unsigned int layer) const
{
if (m_LabelSetContainer.size() <= layer)
return nullptr;
else
return m_LabelSetContainer[layer].GetPointer();
}
mitk::LabelSet *mitk::LabelSetImage::GetActiveLabelSet()
{
if (m_LabelSetContainer.size() == 0)
return nullptr;
else
return m_LabelSetContainer[GetActiveLayer()].GetPointer();
}
const mitk::LabelSet* mitk::LabelSetImage::GetActiveLabelSet() const
{
if (m_LabelSetContainer.size() == 0)
return nullptr;
else
return m_LabelSetContainer[GetActiveLayer()].GetPointer();
}
void mitk::LabelSetImage::UpdateCenterOfMass(PixelType pixelValue)
{
this->UpdateCenterOfMass(pixelValue, this->GetGroupIndexOfLabel(pixelValue));
}
void mitk::LabelSetImage::UpdateCenterOfMass(PixelType pixelValue, unsigned int layer)
{
if (4 == this->GetDimension())
{
AccessFixedDimensionByItk_2(this, CalculateCenterOfMassProcessing, 4, pixelValue, layer);
}
else
{
AccessByItk_2(this, CalculateCenterOfMassProcessing, pixelValue, layer);
}
}
unsigned int mitk::LabelSetImage::GetNumberOfLabels(unsigned int layer) const
{
return m_LabelSetContainer[layer]->GetNumberOfLabels();
}
unsigned int mitk::LabelSetImage::GetTotalNumberOfLabels() const
{
unsigned int totalLabels(0);
auto layerIter = m_LabelSetContainer.begin();
for (; layerIter != m_LabelSetContainer.end(); ++layerIter)
totalLabels += (*layerIter)->GetNumberOfLabels();
return totalLabels;
}
void mitk::LabelSetImage::MaskStamp(mitk::Image *mask, bool forceOverwrite)
{
try
{
mitk::PadImageFilter::Pointer padImageFilter = mitk::PadImageFilter::New();
padImageFilter->SetInput(0, mask);
padImageFilter->SetInput(1, this);
padImageFilter->SetPadConstant(0);
padImageFilter->SetBinaryFilter(false);
padImageFilter->SetLowerThreshold(0);
padImageFilter->SetUpperThreshold(1);
padImageFilter->Update();
mitk::Image::Pointer paddedMask = padImageFilter->GetOutput();
if (paddedMask.IsNull())
return;
AccessByItk_2(this, MaskStampProcessing, paddedMask, forceOverwrite);
}
catch (...)
{
mitkThrow() << "Could not stamp the provided mask on the selected label.";
}
}
mitk::Image::Pointer mitk::LabelSetImage::CreateLabelMask(PixelType index, bool useActiveLayer, unsigned int layer)
{
auto previousActiveLayer = this->GetActiveLayer();
auto mask = mitk::Image::New();
try
{
// mask->Initialize(this) does not work here if this label set image has a single slice,
// since the mask would be automatically flattened to a 2-d image, whereas we expect the
// original dimension of this label set image. Hence, initialize the mask more explicitly:
mask->Initialize(this->GetPixelType(), this->GetDimension(), this->GetDimensions());
mask->SetTimeGeometry(this->GetTimeGeometry()->Clone());
auto byteSize = sizeof(LabelSetImage::PixelType);
for (unsigned int dim = 0; dim < mask->GetDimension(); ++dim)
byteSize *= mask->GetDimension(dim);
{
ImageWriteAccessor accessor(mask);
memset(accessor.GetData(), 0, byteSize);
}
if (!useActiveLayer)
this->SetActiveLayer(layer);
if (4 == this->GetDimension())
{
::CreateLabelMaskProcessing<4>(this, mask, index);
}
else if (3 == this->GetDimension())
{
::CreateLabelMaskProcessing(this, mask, index);
}
else
{
mitkThrow();
}
}
catch (...)
{
if (!useActiveLayer)
this->SetActiveLayer(previousActiveLayer);
mitkThrow() << "Could not create a mask out of the selected label.";
}
if (!useActiveLayer)
this->SetActiveLayer(previousActiveLayer);
return mask;
}
void mitk::LabelSetImage::InitializeByLabeledImage(mitk::Image::Pointer image)
{
if (image.IsNull() || image->IsEmpty() || !image->IsInitialized())
mitkThrow() << "Invalid labeled image.";
try
{
this->Initialize(image);
unsigned int byteSize = sizeof(LabelSetImage::PixelType);
for (unsigned int dim = 0; dim < image->GetDimension(); ++dim)
{
byteSize *= image->GetDimension(dim);
}
mitk::ImageWriteAccessor *accessor = new mitk::ImageWriteAccessor(static_cast<mitk::Image *>(this));
memset(accessor->GetData(), 0, byteSize);
delete accessor;
auto geometry = image->GetTimeGeometry()->Clone();
this->SetTimeGeometry(geometry);
if (image->GetDimension() == 3)
{
AccessTwoImagesFixedDimensionByItk(this, image, InitializeByLabeledImageProcessing, 3);
}
else if (image->GetDimension() == 4)
{
AccessTwoImagesFixedDimensionByItk(this, image, InitializeByLabeledImageProcessing, 4);
}
else
{
mitkThrow() << image->GetDimension() << "-dimensional label set images not yet supported";
}
}
catch (...)
{
mitkThrow() << "Could not intialize by provided labeled image.";
}
this->Modified();
}
template <typename LabelSetImageType, typename ImageType>
void mitk::LabelSetImage::InitializeByLabeledImageProcessing(LabelSetImageType *labelSetImage, ImageType *image)
{
typedef itk::ImageRegionConstIteratorWithIndex<ImageType> SourceIteratorType;
typedef itk::ImageRegionIterator<LabelSetImageType> TargetIteratorType;
TargetIteratorType targetIter(labelSetImage, labelSetImage->GetRequestedRegion());
targetIter.GoToBegin();
SourceIteratorType sourceIter(image, image->GetRequestedRegion());
sourceIter.GoToBegin();
while (!sourceIter.IsAtEnd())
{
auto sourceValue = static_cast<PixelType>(sourceIter.Get());
targetIter.Set(sourceValue);
if (LabelSetImage::UnlabeledValue!=sourceValue && !this->ExistLabel(sourceValue))
{
std::stringstream name;
name << "object-" << sourceValue;
double rgba[4];
m_LabelSetContainer[this->GetActiveLayer()]->GetLookupTable()->GetTableValue(sourceValue, rgba);
mitk::Color color;
color.SetRed(rgba[0]);
color.SetGreen(rgba[1]);
color.SetBlue(rgba[2]);
auto label = mitk::Label::New();
label->SetName(name.str().c_str());
label->SetColor(color);
label->SetOpacity(rgba[3]);
label->SetValue(sourceValue);
this->GetLabelSet()->AddLabel(label);
if (GetActiveLabelSet()->GetNumberOfLabels() >= mitk::Label::MAX_LABEL_VALUE ||
sourceValue >= mitk::Label::MAX_LABEL_VALUE)
this->AddLayer();
}
++sourceIter;
++targetIter;
}
}
template <typename ImageType>
void mitk::LabelSetImage::MaskStampProcessing(ImageType *itkImage, mitk::Image *mask, bool forceOverwrite)
{
typename ImageType::Pointer itkMask;
mitk::CastToItkImage(mask, itkMask);
typedef itk::ImageRegionConstIterator<ImageType> SourceIteratorType;
typedef itk::ImageRegionIterator<ImageType> TargetIteratorType;
SourceIteratorType sourceIter(itkMask, itkMask->GetLargestPossibleRegion());
sourceIter.GoToBegin();
TargetIteratorType targetIter(itkImage, itkImage->GetLargestPossibleRegion());
targetIter.GoToBegin();
int activeLabel = this->GetActiveLabel(GetActiveLayer())->GetValue();
while (!sourceIter.IsAtEnd())
{
PixelType sourceValue = sourceIter.Get();
PixelType targetValue = targetIter.Get();
if ((sourceValue != UnlabeledValue) &&
(forceOverwrite || !this->IsLabelLocked(targetValue))) // skip unlabeled pixels and locked labels
{
targetIter.Set(activeLabel);
}
++sourceIter;
++targetIter;
}
this->Modified();
}
template <typename ImageType>
void mitk::LabelSetImage::CalculateCenterOfMassProcessing(ImageType *itkImage, PixelType pixelValue, unsigned int layer)
{
if (ImageType::GetImageDimension() != 3)
{
return;
}
auto labelGeometryFilter = itk::LabelGeometryImageFilter<ImageType>::New();
labelGeometryFilter->SetInput(itkImage);
labelGeometryFilter->Update();
auto centroid = labelGeometryFilter->GetCentroid(pixelValue);
mitk::Point3D pos;
pos[0] = centroid[0];
pos[1] = centroid[1];
pos[2] = centroid[2];
GetLabelSet(layer)->GetLabel(pixelValue)->SetCenterOfMassIndex(pos);
this->GetSlicedGeometry()->IndexToWorld(pos, pos); // TODO: TimeGeometry?
GetLabelSet(layer)->GetLabel(pixelValue)->SetCenterOfMassCoordinates(pos);
}
template <typename ImageType>
void mitk::LabelSetImage::ClearBufferProcessing(ImageType *itkImage)
{
itkImage->FillBuffer(0);
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::LabelSetImage::LayerContainerToImageProcessing(itk::Image<TPixel, VImageDimension> *target,
unsigned int layer)
{
typedef itk::Image<TPixel, VImageDimension> ImageType;
typename ImageType::Pointer itkSource;
// mitk::CastToItkImage(m_LayerContainer[layer], itkSource);
itkSource = ImageToItkImage<TPixel, VImageDimension>(m_LayerContainer[layer]);
typedef itk::ImageRegionConstIterator<ImageType> SourceIteratorType;
typedef itk::ImageRegionIterator<ImageType> TargetIteratorType;
SourceIteratorType sourceIter(itkSource, itkSource->GetLargestPossibleRegion());
sourceIter.GoToBegin();
TargetIteratorType targetIter(target, target->GetLargestPossibleRegion());
targetIter.GoToBegin();
while (!sourceIter.IsAtEnd())
{
targetIter.Set(sourceIter.Get());
++sourceIter;
++targetIter;
}
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::LabelSetImage::ImageToLayerContainerProcessing(itk::Image<TPixel, VImageDimension> *source,
unsigned int layer) const
{
typedef itk::Image<TPixel, VImageDimension> ImageType;
typename ImageType::Pointer itkTarget;
// mitk::CastToItkImage(m_LayerContainer[layer], itkTarget);
itkTarget = ImageToItkImage<TPixel, VImageDimension>(m_LayerContainer[layer]);
typedef itk::ImageRegionConstIterator<ImageType> SourceIteratorType;
typedef itk::ImageRegionIterator<ImageType> TargetIteratorType;
SourceIteratorType sourceIter(source, source->GetLargestPossibleRegion());
sourceIter.GoToBegin();
TargetIteratorType targetIter(itkTarget, itkTarget->GetLargestPossibleRegion());
targetIter.GoToBegin();
while (!sourceIter.IsAtEnd())
{
targetIter.Set(sourceIter.Get());
++sourceIter;
++targetIter;
}
}
template <typename ImageType>
void mitk::LabelSetImage::EraseLabelProcessing(ImageType *itkImage, PixelType pixelValue)
{
typedef itk::ImageRegionIterator<ImageType> IteratorType;
IteratorType iter(itkImage, itkImage->GetLargestPossibleRegion());
iter.GoToBegin();
while (!iter.IsAtEnd())
{
PixelType value = iter.Get();
if (value == pixelValue)
{
iter.Set(0);
}
++iter;
}
}
template <typename ImageType>
void mitk::LabelSetImage::MergeLabelProcessing(ImageType *itkImage, PixelType pixelValue, PixelType index)
{
typedef itk::ImageRegionIterator<ImageType> IteratorType;
IteratorType iter(itkImage, itkImage->GetLargestPossibleRegion());
iter.GoToBegin();
while (!iter.IsAtEnd())
{
if (iter.Get() == index)
{
iter.Set(pixelValue);
}
++iter;
}
}
void mitk::LabelSetImage::OnLabelAdded(LabelValueType labelValue)
{
Label* label = nullptr;
unsigned int layerID = 0;
for (; layerID < this->GetNumberOfLayers(); ++layerID)
{
label = this->GetLabel(labelValue, layerID);
if (nullptr != label) break;
}
if (!label) mitkThrow() << "Wrong internal state. OnLabelAdded was triggered, but label cannot be found. Invalid label: " << labelValue;
AddLabelToMap(labelValue, label, layerID);
this->m_LabelAddedMessage.Send(labelValue);
}
void mitk::LabelSetImage::AddLabelToMap(LabelValueType labelValue, mitk::Label* label, GroupIndexType groupID)
{
if (m_LabelMap.find(labelValue)!=m_LabelMap.end())
mitkThrow() << "Segmentation is in an invalid state: Label value collision. A label was added with a LabelValue already in use. LabelValue: " << labelValue;
m_LabelMap[labelValue] = label;
m_LabelToGroupMap[labelValue] = groupID;
auto groupFinding = m_GroupToLabelMap.find(groupID);
if (groupFinding == m_GroupToLabelMap.end())
{
m_GroupToLabelMap[groupID] = { labelValue };
}
else
{
m_GroupToLabelMap[groupID].push_back(labelValue);
}
}
void mitk::LabelSetImage::OnLabelModified(LabelValueType labelValue)
{
this->m_LabelModifiedMessage.Send(labelValue);
}
void mitk::LabelSetImage::OnLabelRemoved(LabelValueType labelValue)
{
m_LabelMap.erase(labelValue);
auto finding = m_LabelToGroupMap.find(labelValue);
if (finding != m_LabelToGroupMap.end())
{
auto labelsInGroup = m_GroupToLabelMap[finding->second];
auto labelFinding = std::find(labelsInGroup.begin(), labelsInGroup.end(),finding->second);
if (labelFinding != labelsInGroup.end())
{
labelsInGroup.erase(labelFinding);
}
m_LabelToGroupMap.erase(labelValue);
}
this->m_LabelRemovedMessage.Send(labelValue);
}
void mitk::LabelSetImage::OnGroupAdded(GroupIndexType groupIndex)
{
this->m_GroupToLabelMap.insert(std::make_pair(groupIndex, LabelValueVectorType()));
this->m_GroupAddedMessage.Send(groupIndex);
}
void mitk::LabelSetImage::OnGroupModified(GroupIndexType groupIndex)
{
this->m_GroupModifiedMessage.Send(groupIndex);
}
void mitk::LabelSetImage::OnGroupRemoved(GroupIndexType groupIndex)
{
this->ReinitMaps();
this->m_GroupRemovedMessage.Send(groupIndex);
}
// future implementation for T28524
//bool mitk::LabelSetImage::ExistLabel(LabelValueType value, GroupIndexType groupIndex) const
//{
// auto finding = m_LabelToGroupMap.find(value);
// if (m_LabelToGroupMap.end() != finding)
// {
// return finding->second == groupIndex;
// }
// return false;
//}
//
//bool mitk::LabelSetImage::ExistGroup(GroupIndexType index) const
//{
// return index < m_LabelSetContainer.size();
//}
bool mitk::LabelSetImage::ExistGroup(GroupIndexType index) const
{
return index < m_LabelSetContainer.size();
}
bool mitk::LabelSetImage::IsLabelInGroup(LabelValueType value) const
{
GroupIndexType dummy;
return this->IsLabelInGroup(value, dummy);
}
bool mitk::LabelSetImage::IsLabelInGroup(LabelValueType value, GroupIndexType& groupIndex) const
{
auto finding = m_LabelToGroupMap.find(value);
if (m_LabelToGroupMap.end() != finding)
{
groupIndex = finding->second;
return true;
}
return false;
}
mitk::LabelSetImage::GroupIndexType mitk::LabelSetImage::GetGroupIndexOfLabel(LabelValueType value) const
{
auto finding = m_LabelToGroupMap.find(value);
if (m_LabelToGroupMap.end() == finding)
{
mitkThrow()<< "Cannot deduce group index. Passed label value does not exist. Value: "<< value;
}
return finding->second;
}
const mitk::Label* mitk::LabelSetImage::GetLabel(LabelValueType value) const
{
auto finding = m_LabelMap.find(value);
if (m_LabelMap.end() != finding)
{
return finding->second;
}
return nullptr;
};
mitk::Label* mitk::LabelSetImage::GetLabel(LabelValueType value)
{
auto finding = m_LabelMap.find(value);
if (m_LabelMap.end() != finding)
{
return finding->second;
}
return nullptr;
};
bool mitk::LabelSetImage::IsLabelLocked(LabelValueType value) const
{
if (value == UnlabeledValue)
{
return m_UnlabeledLabelLock;
}
const auto label = this->GetLabel(value);
return label->GetLocked();
}
const mitk::LabelSetImage::ConstLabelVectorType mitk::LabelSetImage::GetLabels() const
{
ConstLabelVectorType result;
for (auto [value, label] : m_LabelMap)
{
result.emplace_back(label);
}
return result;
}
const mitk::LabelSetImage::LabelVectorType mitk::LabelSetImage::GetLabels()
{
LabelVectorType result;
for (auto [value, label] : m_LabelMap)
{
result.emplace_back(label);
}
return result;
}
const mitk::LabelSetImage::ConstLabelVectorType mitk::LabelSetImage::GetLabelsInGroup(GroupIndexType index) const
{
if (!this->ExistGroup(index))
- {
mitkThrow() << "Cannot get labels of an invalid group. Invalid group index: " << index;
- }
mitk::LabelSetImage::ConstLabelVectorType result;
+ const auto labelValues = m_GroupToLabelMap.find(index)->second;
- const auto labellist = m_GroupToLabelMap.find(index)->second;
- for (const auto& labelvalue : labellist)
+ for (const auto& labelValue : labelValues)
{
- result.emplace_back(this->GetLabel(labelvalue));
+ const auto* label = this->GetLabel(labelValue);
+
+ if (label != nullptr)
+ result.emplace_back(label);
}
return result;
}
const mitk::LabelSetImage::LabelVectorType mitk::LabelSetImage::GetLabelsInGroup(GroupIndexType index)
{
if (!this->ExistGroup(index))
- {
mitkThrow() << "Cannot get labels of an invalid group. Invalid group index: " << index;
- }
mitk::LabelSetImage::LabelVectorType result;
+ const auto labelValues = m_GroupToLabelMap[index];
- const auto labellist = m_GroupToLabelMap[index];
- for (const auto& labelvalue : labellist)
+ for (const auto& labelValue : labelValues)
{
- result.emplace_back(this->GetLabel(labelvalue));
+ auto* label = this->GetLabel(labelValue);
+
+ if (label != nullptr)
+ result.emplace_back(label);
}
return result;
}
void mitk::LabelSetImage::ReinitMaps()
{
this->m_LabelMap.clear();
this->m_LabelToGroupMap.clear();
this->m_GroupToLabelMap.clear();
for (GroupIndexType layerID = 0; layerID < this->GetNumberOfLayers(); ++layerID)
{
auto labelSet = this->GetLabelSet(layerID);
- for (auto iter = labelSet->IteratorBegin(); iter != labelSet->IteratorEnd(); ++iter)
+
+ if (labelSet->GetNumberOfLabels() != 0)
{
- if (iter->first != UnlabeledValue)
+ for (auto iter = labelSet->IteratorBegin(); iter != labelSet->IteratorEnd(); ++iter)
{
- this->AddLabelToMap(iter->first, iter->second, layerID);
+ if (iter->first != UnlabeledValue)
+ this->AddLabelToMap(iter->first, iter->second, layerID);
}
}
+ else
+ {
+ m_GroupToLabelMap[layerID] = {};
+ }
}
}
-
bool mitk::Equal(const mitk::LabelSetImage &leftHandSide,
const mitk::LabelSetImage &rightHandSide,
ScalarType eps,
bool verbose)
{
bool returnValue = true;
/* LabelSetImage members */
MITK_INFO(verbose) << "--- LabelSetImage Equal ---";
// number layers
returnValue = leftHandSide.GetNumberOfLayers() == rightHandSide.GetNumberOfLayers();
if (!returnValue)
{
MITK_INFO(verbose) << "Number of layers not equal.";
return false;
}
// total number labels
returnValue = leftHandSide.GetTotalNumberOfLabels() == rightHandSide.GetTotalNumberOfLabels();
if (!returnValue)
{
MITK_INFO(verbose) << "Total number of labels not equal.";
return false;
}
// active layer
returnValue = leftHandSide.GetActiveLayer() == rightHandSide.GetActiveLayer();
if (!returnValue)
{
MITK_INFO(verbose) << "Active layer not equal.";
return false;
}
if (4 == leftHandSide.GetDimension())
{
MITK_INFO(verbose) << "Can not compare image data for 4D images - skipping check.";
}
else
{
// working image data
returnValue = mitk::Equal((const mitk::Image &)leftHandSide, (const mitk::Image &)rightHandSide, eps, verbose);
if (!returnValue)
{
MITK_INFO(verbose) << "Working image data not equal.";
return false;
}
}
for (unsigned int layerIndex = 0; layerIndex < leftHandSide.GetNumberOfLayers(); layerIndex++)
{
if (4 == leftHandSide.GetDimension())
{
MITK_INFO(verbose) << "Can not compare image data for 4D images - skipping check.";
}
else
{
// layer image data
returnValue =
mitk::Equal(*leftHandSide.GetLayerImage(layerIndex), *rightHandSide.GetLayerImage(layerIndex), eps, verbose);
if (!returnValue)
{
MITK_INFO(verbose) << "Layer image data not equal.";
return false;
}
}
// layer labelset data
returnValue =
mitk::Equal(*leftHandSide.GetLabelSet(layerIndex), *rightHandSide.GetLabelSet(layerIndex), eps, verbose);
if (!returnValue)
{
MITK_INFO(verbose) << "Layer labelset data not equal.";
return false;
}
}
return returnValue;
}
/** Functor class that implements the label transfer and is used in conjunction with the itk::BinaryFunctorImageFilter.
* For details regarding the usage of the filter and the functor patterns, please see info of itk::BinaryFunctorImageFilter.
*/
template <class TDestinationPixel, class TSourcePixel, class TOutputpixel>
class LabelTransferFunctor
{
public:
LabelTransferFunctor() {};
LabelTransferFunctor(const mitk::LabelSet* destinationLabelSet, mitk::Label::PixelType sourceBackground,
mitk::Label::PixelType destinationBackground, bool destinationBackgroundLocked,
mitk::Label::PixelType sourceLabel, mitk::Label::PixelType newDestinationLabel, mitk::MultiLabelSegmentation::MergeStyle mergeStyle,
mitk::MultiLabelSegmentation::OverwriteStyle overwriteStyle) :
m_DestinationLabelSet(destinationLabelSet), m_SourceBackground(sourceBackground),
m_DestinationBackground(destinationBackground), m_DestinationBackgroundLocked(destinationBackgroundLocked),
m_SourceLabel(sourceLabel), m_NewDestinationLabel(newDestinationLabel), m_MergeStyle(mergeStyle), m_OverwriteStyle(overwriteStyle)
{
};
~LabelTransferFunctor() {};
bool operator!=(const LabelTransferFunctor& other)const
{
return !(*this == other);
}
bool operator==(const LabelTransferFunctor& other) const
{
return this->m_SourceBackground == other.m_SourceBackground &&
this->m_DestinationBackground == other.m_DestinationBackground &&
this->m_DestinationBackgroundLocked == other.m_DestinationBackgroundLocked &&
this->m_SourceLabel == other.m_SourceLabel &&
this->m_NewDestinationLabel == other.m_NewDestinationLabel &&
this->m_MergeStyle == other.m_MergeStyle &&
this->m_OverwriteStyle == other.m_OverwriteStyle &&
this->m_DestinationLabelSet == other.m_DestinationLabelSet;
}
LabelTransferFunctor& operator=(const LabelTransferFunctor& other)
{
this->m_DestinationLabelSet = other.m_DestinationLabelSet;
this->m_SourceBackground = other.m_SourceBackground;
this->m_DestinationBackground = other.m_DestinationBackground;
this->m_DestinationBackgroundLocked = other.m_DestinationBackgroundLocked;
this->m_SourceLabel = other.m_SourceLabel;
this->m_NewDestinationLabel = other.m_NewDestinationLabel;
this->m_MergeStyle = other.m_MergeStyle;
this->m_OverwriteStyle = other.m_OverwriteStyle;
return *this;
}
inline TOutputpixel operator()(const TDestinationPixel& existingDestinationValue, const TSourcePixel& existingSourceValue)
{
if (existingSourceValue == this->m_SourceLabel)
{
if (mitk::MultiLabelSegmentation::OverwriteStyle::IgnoreLocks == this->m_OverwriteStyle)
{
return this->m_NewDestinationLabel;
}
else
{
if (existingDestinationValue == m_DestinationBackground)
{
if (!m_DestinationBackgroundLocked)
{
return this->m_NewDestinationLabel;
}
}
else
{
auto label = this->m_DestinationLabelSet->GetLabel(existingDestinationValue);
if (nullptr == label || !label->GetLocked())
{
return this->m_NewDestinationLabel;
}
}
}
}
else if (mitk::MultiLabelSegmentation::MergeStyle::Replace == this->m_MergeStyle
&& existingSourceValue == this->m_SourceBackground
&& existingDestinationValue == this->m_NewDestinationLabel
&& (mitk::MultiLabelSegmentation::OverwriteStyle::IgnoreLocks == this->m_OverwriteStyle
|| !this->m_DestinationBackgroundLocked))
{
return this->m_DestinationBackground;
}
return existingDestinationValue;
}
private:
const mitk::LabelSet* m_DestinationLabelSet = nullptr;
mitk::Label::PixelType m_SourceBackground = 0;
mitk::Label::PixelType m_DestinationBackground = 0;
bool m_DestinationBackgroundLocked = false;
mitk::Label::PixelType m_SourceLabel = 1;
mitk::Label::PixelType m_NewDestinationLabel = 1;
mitk::MultiLabelSegmentation::MergeStyle m_MergeStyle = mitk::MultiLabelSegmentation::MergeStyle::Replace;
mitk::MultiLabelSegmentation::OverwriteStyle m_OverwriteStyle = mitk::MultiLabelSegmentation::OverwriteStyle::RegardLocks;
};
/**Helper function used by TransferLabelContentAtTimeStep to allow the templating over different image dimensions in conjunction of AccessFixedPixelTypeByItk_n.*/
template<unsigned int VImageDimension>
void TransferLabelContentAtTimeStepHelper(const itk::Image<mitk::Label::PixelType, VImageDimension>* itkSourceImage, mitk::Image* destinationImage,
const mitk::LabelSet* destinationLabelSet, mitk::Label::PixelType sourceBackground, mitk::Label::PixelType destinationBackground,
bool destinationBackgroundLocked, mitk::Label::PixelType sourceLabel, mitk::Label::PixelType newDestinationLabel, mitk::MultiLabelSegmentation::MergeStyle mergeStyle, mitk::MultiLabelSegmentation::OverwriteStyle overwriteStyle)
{
typedef itk::Image<mitk::Label::PixelType, VImageDimension> ContentImageType;
typename ContentImageType::Pointer itkDestinationImage;
mitk::CastToItkImage(destinationImage, itkDestinationImage);
auto sourceRegion = itkSourceImage->GetLargestPossibleRegion();
auto relevantRegion = itkDestinationImage->GetLargestPossibleRegion();
bool overlapping = relevantRegion.Crop(sourceRegion);
if (!overlapping)
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage and destinationImage seem to have no overlapping image region.";
}
typedef LabelTransferFunctor <mitk::Label::PixelType, mitk::Label::PixelType, mitk::Label::PixelType> LabelTransferFunctorType;
typedef itk::BinaryFunctorImageFilter<ContentImageType, ContentImageType, ContentImageType, LabelTransferFunctorType> FilterType;
LabelTransferFunctorType transferFunctor(destinationLabelSet, sourceBackground, destinationBackground,
destinationBackgroundLocked, sourceLabel, newDestinationLabel, mergeStyle, overwriteStyle);
auto transferFilter = FilterType::New();
transferFilter->SetFunctor(transferFunctor);
transferFilter->InPlaceOn();
transferFilter->SetInput1(itkDestinationImage);
transferFilter->SetInput2(itkSourceImage);
transferFilter->GetOutput()->SetRequestedRegion(relevantRegion);
transferFilter->Update();
}
void mitk::TransferLabelContentAtTimeStep(
const Image* sourceImage, Image* destinationImage, const mitk::LabelSet* destinationLabelSet, const TimeStepType timeStep, mitk::Label::PixelType sourceBackground,
mitk::Label::PixelType destinationBackground, bool destinationBackgroundLocked, std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping,
MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
{
if (nullptr == sourceImage)
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage must not be null.";
}
if (nullptr == destinationImage)
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; destinationImage must not be null.";
}
if (nullptr == destinationLabelSet)
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; destinationLabelSet must not be null";
}
if (sourceImage == destinationImage && labelMapping.size() > 1)
{
MITK_DEBUG << "Warning. Using TransferLabelContentAtTimeStep or TransferLabelContent with equal source and destination and more then on label to transfer, can lead to wrong results. Please see documentation and verify that the usage is OK.";
}
Image::ConstPointer sourceImageAtTimeStep = SelectImageByTimeStep(sourceImage, timeStep);
Image::Pointer destinationImageAtTimeStep = SelectImageByTimeStep(destinationImage, timeStep);
if (nullptr == sourceImageAtTimeStep)
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage does not have the requested time step: " << timeStep;
}
if (nullptr == destinationImageAtTimeStep)
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; destinationImage does not have the requested time step: " << timeStep;
}
for (const auto& [sourceLabel, newDestinationLabel] : labelMapping)
{
if (LabelSetImage::UnlabeledValue!=newDestinationLabel && nullptr == destinationLabelSet->GetLabel(newDestinationLabel))
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep. Defined destination label does not exist in destinationImage. newDestinationLabel: " << newDestinationLabel;
}
AccessFixedPixelTypeByItk_n(sourceImageAtTimeStep, TransferLabelContentAtTimeStepHelper, (Label::PixelType), (destinationImageAtTimeStep, destinationLabelSet, sourceBackground, destinationBackground, destinationBackgroundLocked, sourceLabel, newDestinationLabel, mergeStyle, overwriteStlye));
destinationLabelSet->ModifyLabelEvent.Send(newDestinationLabel);
}
destinationImage->Modified();
}
void mitk::TransferLabelContent(
const Image* sourceImage, Image* destinationImage, const mitk::LabelSet* destinationLabelSet, mitk::Label::PixelType sourceBackground,
mitk::Label::PixelType destinationBackground, bool destinationBackgroundLocked, std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping,
MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
{
if (nullptr == sourceImage)
{
mitkThrow() << "Invalid call of TransferLabelContent; sourceImage must not be null.";
}
if (nullptr == destinationImage)
{
mitkThrow() << "Invalid call of TransferLabelContent; destinationImage must not be null.";
}
const auto sourceTimeStepCount = sourceImage->GetTimeGeometry()->CountTimeSteps();
if (sourceTimeStepCount != destinationImage->GetTimeGeometry()->CountTimeSteps())
{
mitkThrow() << "Invalid call of TransferLabelContent; mismatch between images in number of time steps.";
}
for (mitk::TimeStepType i = 0; i < sourceTimeStepCount; ++i)
{
TransferLabelContentAtTimeStep(sourceImage, destinationImage, destinationLabelSet, i, sourceBackground,
destinationBackground, destinationBackgroundLocked, labelMapping, mergeStyle, overwriteStlye);
}
}
void mitk::TransferLabelContentAtTimeStep(
const LabelSetImage* sourceImage, LabelSetImage* destinationImage, const TimeStepType timeStep,
std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping,
MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
{
if (nullptr == sourceImage)
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage must not be null.";
}
const auto destinationLabelSet = destinationImage->GetLabelSet(destinationImage->GetActiveLayer());
for (const auto& mappingElement : labelMapping)
{
if (LabelSetImage::UnlabeledValue != mappingElement.first && !sourceImage->ExistLabel(mappingElement.first, sourceImage->GetActiveLayer()))
{
mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep. Defined source label does not exist in sourceImage. SourceLabel: " << mappingElement.first;
}
}
TransferLabelContentAtTimeStep(sourceImage, destinationImage, destinationLabelSet, timeStep, LabelSetImage::UnlabeledValue, LabelSetImage::UnlabeledValue, destinationImage->GetUnlabeledLabelLock(),
labelMapping, mergeStyle, overwriteStlye);
}
void mitk::TransferLabelContent(
const LabelSetImage* sourceImage, LabelSetImage* destinationImage,
std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping,
MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
{
if (nullptr == sourceImage)
{
mitkThrow() << "Invalid call of TransferLabelContent; sourceImage must not be null.";
}
if (nullptr == destinationImage)
{
mitkThrow() << "Invalid call of TransferLabelContent; destinationImage must not be null.";
}
const auto sourceTimeStepCount = sourceImage->GetTimeGeometry()->CountTimeSteps();
if (sourceTimeStepCount != destinationImage->GetTimeGeometry()->CountTimeSteps())
{
mitkThrow() << "Invalid call of TransferLabelContent; images have no equal number of time steps.";
}
for (mitk::TimeStepType i = 0; i < sourceTimeStepCount; ++i)
{
TransferLabelContentAtTimeStep(sourceImage, destinationImage, i, labelMapping, mergeStyle, overwriteStlye);
}
}
diff --git a/Modules/Multilabel/mitkLabelSetImage.h b/Modules/Multilabel/mitkLabelSetImage.h
index a0fe5a041d..bb8cd3a0ac 100644
--- a/Modules/Multilabel/mitkLabelSetImage.h
+++ b/Modules/Multilabel/mitkLabelSetImage.h
@@ -1,672 +1,672 @@
/*============================================================================
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 mitkLabelSetImage_h
#define mitkLabelSetImage_h
#include <mitkImage.h>
#include <mitkLabelSet.h>
#include <MitkMultilabelExports.h>
namespace mitk
{
//##Documentation
//## @brief LabelSetImage class for handling labels and layers in a segmentation session.
//##
//## Handles operations for adding, removing, erasing and editing labels and layers.
//## @ingroup Data
class MITKMULTILABEL_EXPORT LabelSetImage : public Image
{
public:
mitkClassMacro(LabelSetImage, Image);
itkNewMacro(Self);
typedef mitk::Label::PixelType PixelType;
/**
* \brief BeforeChangeLayerEvent (e.g. used for GUI integration)
* As soon as active labelset should be changed, the signal emits.
* Emitted by SetActiveLayer(int layer);
*/
Message<> BeforeChangeLayerEvent;
/**
* \brief AfterchangeLayerEvent (e.g. used for GUI integration)
* As soon as active labelset was changed, the signal emits.
* Emitted by SetActiveLayer(int layer);
*/
Message<> AfterChangeLayerEvent;
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// FUTURE MultiLabelSegmentation:
// Section that already contains declarations used in the new class.
// So this part of the interface will stay after refactoring towards
// the new MultiLabelSegmentation class (see T28524). This section was introduced
// because some of the planned features are already urgently needed.
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
using GroupIndexType = std::size_t;
using LabelValueType = mitk::Label::PixelType;
const static LabelValueType UnlabeledValue = 0;
using ConstLabelVectorType = std::vector<Label::ConstPointer>;
using LabelVectorType = std::vector<Label::Pointer>;
using LabelValueVectorType = std::vector<LabelValueType>;
/**
* @brief Removes the label with the given value.
* The label is removed from the labelset and
* the pixel with the value of the label are set to UnlabeledValue.
* @param labelValue the pixel value of the label to be removed
*/
void RemoveLabel(LabelValueType labelValue);
/**
* @brief Removes labels from the mitk::MultiLabelSegmentation.
* If a label value does not exist, it will be ignored.
* @param vectorOfLabelPixelValues a list of labels to be removed
*/
void RemoveLabels(const LabelValueVectorType& vectorOfLabelPixelValues);
/**
* @brief Removes a whole group including all its labels.
* @remark with removing a group all groups with greater index will be reindexed to
* close the gap. Hence externaly stored spatial group indices may become invalid.
* @param group Group index of the spatial group that should be removed. If the spatial group does not exist, an
* exception will be raised.
* @pre group index must be valid.
*/
void RemoveGroup(GroupIndexType group);
//future declaration (T28524) currently conflicted with old declaration
///**
// * \brief Returns true if the value exists in the MultiLabelSegmentation instance*/
//bool ExistLabel(LabelValueType value) const;
///**
// * @brief Checks if a label belongs in a certain spatial group
// * @param value the label value
// * @param groupIndex Indexp of the spacial group which should be checked for the label
// * @return true if the label exists otherwise false
// */
//bool ExistLabel(LabelValueType value, GroupIndexType groupIndex) const;
/**
* @brief Returns true if the spatial group exists in the MultiLabelSegmentation instance.
*
* @param index Group index of the group that should be checked for existance.
*/
bool ExistGroup(GroupIndexType index) const;
bool IsLabelInGroup(LabelValueType value) const;
bool IsLabelInGroup(LabelValueType value, GroupIndexType& groupIndex) const;
/** Returns the group id of the based label value.
* @pre label value must exists.
*/
GroupIndexType GetGroupIndexOfLabel(LabelValueType value) const;
/**
* @brief Returns the mitk::Label with the given value.
* @param value the pixel value of the label
* @return the mitk::Label if available otherwise nullptr
*/
const mitk::Label* GetLabel(LabelValueType value) const;
mitk::Label* GetLabel(LabelValueType value);
/** Returns the lock state of the label (including UnlabeledLabel value).
@pre Requested label does exist.*/
bool IsLabelLocked(LabelValueType value) const;
/** Returns a vector with all labels currently defined in the MultiLabelSegmentation
instance.*/
const ConstLabelVectorType GetLabels() const;
const LabelVectorType GetLabels();
/**
* @brief Returns a vector of all labels located on the specified group.
* @param index the index of the group for which the vector of labels should be retrieved.
* If an invalid index is passed an exception will be raised.
* @return the respective vector of labels.
* @pre group index must exist.
*/
const ConstLabelVectorType GetLabelsInGroup(GroupIndexType index) const;
const LabelVectorType GetLabelsInGroup(GroupIndexType index);
itkGetConstMacro(UnlabeledLabelLock, bool);
itkSetMacro(UnlabeledLabelLock, bool);
itkBooleanMacro(UnlabeledLabelLock);
////////////////////////////////////////////////////////////////////
//Message slots that allow to react to changes in an instance
using LabelEventType = Message1<LabelValueType>;
using LabelsEventType = Message1<LabelValueVectorType>;
using GroupEventType = Message1<GroupIndexType>;
/**
* \brief LabelAdded is emitted whenever a new label has been added.
*
* Observers should register to this event by calling this->AddLabelAddedListener(myObject,
* MyObject::MyMethod).
* After registering, myObject->MyMethod() will be called every time a new label has been added to the MultiLabelSegmentation.
* Observers should unregister by calling this->RemoveLabelAddedListener(myObject, MyObject::MyMethod).
* The registered method will be called with the label value of the added label.
* @remark the usage of the message object is thread safe.
*/
mitkNewMessage1Macro(LabelAdded, LabelValueType);
/**
* \brief LabelModified is emitted whenever a label has been modified.
*
* A label is modified if either its pixel content was changed, its spatial group or the label instance
* information.
* If you just want to get notified at the end of a MultiLabelSegmentation instance manipulation in the
* case that at least one label was modified (e.g. to avoid getting a signal for each label
* individually), use LabelsChanged instead.
* Observers should register to this event by calling this->AddLabelModifiedListener(myObject,
* MyObject::MyMethod).
* After registering, myObject->MyMethod() will be called every time a new label has been added to the MultiLabelSegmentation.
* Observers should unregister by calling this->RemoveLabelModifiedListener(myObject, MyObject::MyMethod).
* The registered method will be called with the label value of the modified label.
* @remark the usage of the message object is thread safe.
*/
mitkNewMessage1Macro(LabelModified, LabelValueType);
/**
* \brief LabelRemoved is emitted whenever a label has been removed.
*
* Observers should register to this event by calling this->AddLabelRemovedListener(myObject,
* MyObject::MyMethod).
* After registering, myObject->MyMethod() will be called every time a new label has been added to the MultiLabelSegmentation.
* Observers should unregister by calling this->RemoveLabelRemovedListener(myObject, MyObject::MyMethod).
* The registered method will be called with the label value of the removed label.*
* @remark the usage of the message object is thread safe.
*/
mitkNewMessage1Macro(LabelRemoved, LabelValueType);
/**
* \brief LabelsChanged is emitted when labels are changed (added, removed, modified).
*
* In difference to the other label events LabelsChanged is send only *one time* after the modification of the
* MultiLableImage instance is finished. So e.g. even if 4 labels are changed by a merge operation, this event will
* only be sent once (compared to LabelRemoved or LabelModified).
* Observers should register to this event by calling myMultiLabelSegmentation->AddLabelsChangedListener(myObject,
* MyObject::MyMethod).
* After registering, myObject->MyMethod() will be called every time a new label has been removed from the MultiLabelSegmentation.
* Observers should unregister by calling myMultiLabelSegmentation->RemoveLabelsChangedListener(myObject,
* MyObject::MyMethod).
* The registered method will be called with the vector of label values of the modified labels.*
* @remark the usage of the message object is thread safe.
*/
mitkNewMessage1Macro(LabelsChanged, LabelValueVectorType);
/**
* \brief GroupAdded is emitted whenever a new group has been added.
*
* Observers should register to this event by calling this->AddGroupAddedListener(myObject,
* MyObject::MyMethod).
* After registering, myObject->MyMethod() will be called every time a new group has been added to the MultiLabelSegmentation.
* Observers should unregister by calling this->RemoveGroupAddedListener(myObject, MyObject::MyMethod).
* The registered method will be called with the group index of the added group.
* @remark the usage of the message object is thread safe.
*/
mitkNewMessage1Macro(GroupAdded, GroupIndexType);
/**
* \brief GroupModified is emitted whenever a group has been modified.
*
* A group is modified if the set of labels associated with it are changed or the group's meta data.
* Observers should register to this event by calling this->AddGroupModifiedListener(myObject,
* MyObject::MyMethod).
* After registering, myObject->MyMethod() will be called every time a new label has been added to the MultiLabelSegmentation.
* Observers should unregister by calling this->RemoveGroupModifiedListener(myObject, MyObject::MyMethod).
* The registered method will be called with the group index of the added group.
* @remark the usage of the message object is thread safe.
*/
mitkNewMessage1Macro(GroupModified, GroupIndexType);
/**
* \brief GroupRemoved is emitted whenever a label has been removed.
*
* Observers should register to this event by calling this->AddGroupRemovedListener(myObject,
* MyObject::MyMethod).
* After registering, myObject->MyMethod() will be called every time a new label has been added to the MultiLabelSegmentation.
* Observers should unregister by calling this->RemoveGroupRemovedListener(myObject, MyObject::MyMethod).
* The registered method will be called with the group index of the removed group.*
* @remark the usage of the message object is thread safe.
*/
mitkNewMessage1Macro(GroupRemoved, GroupIndexType);
protected:
void OnLabelAdded(LabelValueType labelValue);
void AddLabelToMap(LabelValueType labelValue, mitk::Label* label, GroupIndexType groupID);
void OnLabelModified(LabelValueType labelValue);
void OnLabelRemoved(LabelValueType labelValue);
void OnGroupAdded(GroupIndexType groupIndex);
void OnGroupModified(GroupIndexType groupIndex);
void OnGroupRemoved(GroupIndexType groupIndex);
/** Reeinitalizes the internal maps based on the current layer/label content
* of the instance. */
void ReinitMaps();
using LabelMapType = std::map<LabelValueType, Label::Pointer>;
LabelMapType m_LabelMap;
/**This type is internally used to track which label is currently
* associated with which layer.*/
using GroupToLabelMapType = std::map<GroupIndexType, LabelValueVectorType>;
GroupToLabelMapType m_GroupToLabelMap;
using LabelToGroupMapType = std::map<LabelValueType, GroupIndexType>;
LabelToGroupMapType m_LabelToGroupMap;
private:
/** Indicates if the MultiLabelSegmentation allows to overwrite unlabeled pixels in normal pixel manipulation operations (e.g. TransferLabelConent).*/
bool m_UnlabeledLabelLock;
public:
/**
* \brief */
void UpdateCenterOfMass(PixelType pixelValue);
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// END FUTURE MultiLabelSegmentation
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
/**
* @brief Initialize an empty mitk::LabelSetImage using the information
* of an mitk::Image
* @param image the image which is used for initializing the mitk::LabelSetImage
*/
using mitk::Image::Initialize;
void Initialize(const mitk::Image *image) override;
/**
* \brief */
void ClearBuffer();
/**
* @brief Merges the mitk::Label with a given target value with the active label
*
* @param pixelValue the value of the label that should be the new merged label
* @param sourcePixelValue the value of the label that should be merged into the specified one
* @param layer the layer in which the merge should be performed
*/
void MergeLabel(PixelType pixelValue, PixelType sourcePixelValue, unsigned int layer = 0);
/**
* @brief Merges a list of mitk::Labels with the mitk::Label that has a specific value
*
* @param pixelValue the value of the label that should be the new merged label
* @param vectorOfSourcePixelValues the list of label values that should be merge into the specified one
* @param layer the layer in which the merge should be performed
*/
void MergeLabels(PixelType pixelValue, const std::vector<PixelType>& vectorOfSourcePixelValues, unsigned int layer = 0);
/**
* \brief */
void UpdateCenterOfMass(PixelType pixelValue, unsigned int layer);
/**
* @brief Erases the label with the given value from the labelset image.
* The label itself will not be erased from the respective mitk::LabelSet. In order to
* remove the label itself use mitk::LabelSetImage::RemoveLabels()
* @param pixelValue the pixel value of the label that will be erased from the labelset image
*/
void EraseLabel(PixelType pixelValue);
/**
* @brief Erases a list of labels with the given values from the labelset image.
* @param VectorOfLabelPixelValues the list of pixel values of the labels
* that will be erased from the labelset image
*/
void EraseLabels(const std::vector<PixelType> &VectorOfLabelPixelValues);
/**
* \brief Returns true if the value exists in one of the labelsets*/
//[[deprecated("Will be changed with T28524")]]
DEPRECATED(bool ExistLabel(PixelType pixelValue) const);
/**
* @brief Checks if a label exists in a certain layer
* @param pixelValue the label value
* @param layer the layer in which should be searched for the label
* @return true if the label exists otherwise false
*/
//[[deprecated("Will be changed with T28524")]]
DEPRECATED(bool ExistLabel(PixelType pixelValue, unsigned int layer) const);
/**
* \brief Returns true if the labelset exists*/
//[[deprecated("Will be removed with T28524")]]
DEPRECATED(bool ExistLabelSet(unsigned int layer) const);
/**
* @brief Returns the active label of a specific layer
* @param layer the layer ID for which the active label should be returned
* @return the active label of the specified layer
*/
//[[deprecated("Will be removed with T28524")]]
DEPRECATED(mitk::Label *GetActiveLabel(unsigned int layer = 0));
//[[deprecated("Will be removed with T28524")]]
DEPRECATED(const mitk::Label* GetActiveLabel(unsigned int layer = 0) const);
/**
* @brief Returns the mitk::Label with the given pixelValue and for the given layer
* @param pixelValue the pixel value of the label
* @param layer the layer in which the labels should be located
* @return the mitk::Label if available otherwise nullptr
*/
mitk::Label *GetLabel(PixelType pixelValue, unsigned int layer) const;
/**
* @brief Returns the currently active mitk::LabelSet
* @return the mitk::LabelSet of the active layer or nullptr if non is present
*/
//[[deprecated ("Will be removed with T28524")]]
DEPRECATED(mitk::LabelSet *GetActiveLabelSet());
//[[deprecated("Will be removed with T28524")]]
DEPRECATED(const mitk::LabelSet* GetActiveLabelSet() const);
/**
* @brief Gets the mitk::LabelSet for the given layer
* @param layer the layer for which the mitk::LabelSet should be retrieved
* @return the respective mitk::LabelSet or nullptr if non exists for the given layer
*/
mitk::LabelSet *GetLabelSet(unsigned int layer = 0);
const mitk::LabelSet *GetLabelSet(unsigned int layer = 0) const;
/**
* @brief Gets the ID of the currently active layer
* @return the ID of the active layer
*/
unsigned int GetActiveLayer() const;
/**
* @brief Get the number of all existing mitk::Labels for a given layer
* @param layer the layer ID for which the active mitk::Labels should be retrieved
* @return the number of all existing mitk::Labels for the given layer
*/
unsigned int GetNumberOfLabels(unsigned int layer = 0) const;
/**
* @brief Returns the number of all labels summed up across all layers
* @return the overall number of labels across all layers
*/
unsigned int GetTotalNumberOfLabels() const;
// This function will need to be ported to an external class
// it requires knowledge of pixeltype and dimension and includes
// too much algorithm to be sensibly part of a data class
///**
// * \brief */
// void SurfaceStamp(mitk::Surface* surface, bool forceOverwrite);
/**
* \brief */
mitk::Image::Pointer CreateLabelMask(PixelType index, bool useActiveLayer = true, unsigned int layer = 0);
/**
* @brief Initialize a new mitk::LabelSetImage by an given image.
* For all distinct pixel values of the parameter image new labels will
* be created. If the number of distinct pixel values exceeds mitk::Label::MAX_LABEL_VALUE
* a new layer will be created
* @param image the image which is used for initialization
*/
void InitializeByLabeledImage(mitk::Image::Pointer image);
/**
* \brief */
void MaskStamp(mitk::Image *mask, bool forceOverwrite);
/**
* \brief */
void SetActiveLayer(unsigned int layer);
/**
* \brief */
unsigned int GetNumberOfLayers() const;
/**
* \brief Adds a new layer to the LabelSetImage. The new layer will be set as the active one.
* \param labelSet a labelset that will be added to the new layer if provided
* \return the layer ID of the new layer
*/
unsigned int AddLayer(mitk::LabelSet::Pointer labelSet = nullptr);
/**
* \brief Adds a layer based on a provided mitk::Image.
* \param layerImage is added to the vector of label images
* \param labelSet a labelset that will be added to the new layer if provided
* \return the layer ID of the new layer
*/
unsigned int AddLayer(mitk::Image::Pointer layerImage, mitk::LabelSet::Pointer labelSet = nullptr);
/**
* \brief Add a cloned LabelSet to an existing layer
*
* Remark: The passed LabelSet instance will be cloned before added to ensure clear ownership
* of the new LabelSet addition.
*
* This will replace an existing labelSet if one exists. Throws an exceptions if you are trying
* to add a labelSet to a non-existing layer.
*
* If there are no labelSets for layers with an id less than layerIdx default ones will be added
* for them.
*
* \param layerIdx The index of the layer the LabelSet should be added to
* \param labelSet The LabelSet that should be added
*/
void AddLabelSetToLayer(const unsigned int layerIdx, const mitk::LabelSet* labelSet);
/**
* @brief Removes the active layer and the respective mitk::LabelSet and image information.
* The new active layer is the one below, if exists
*/
void RemoveLayer();
/**
* \brief */
mitk::Image *GetLayerImage(unsigned int layer);
const mitk::Image *GetLayerImage(unsigned int layer) const;
void OnLabelSetModified();
protected:
mitkCloneMacro(Self);
LabelSetImage();
LabelSetImage(const LabelSetImage &other);
~LabelSetImage() override;
template <typename TPixel, unsigned int VImageDimension>
void LayerContainerToImageProcessing(itk::Image<TPixel, VImageDimension> *source, unsigned int layer);
template <typename TPixel, unsigned int VImageDimension>
void ImageToLayerContainerProcessing(itk::Image<TPixel, VImageDimension> *source, unsigned int layer) const;
template <typename ImageType>
void CalculateCenterOfMassProcessing(ImageType *input, PixelType index, unsigned int layer);
template <typename ImageType>
void ClearBufferProcessing(ImageType *input);
template <typename ImageType>
void EraseLabelProcessing(ImageType *input, PixelType index);
template <typename ImageType>
void MergeLabelProcessing(ImageType *input, PixelType pixelValue, PixelType index);
template <typename ImageType>
void MaskStampProcessing(ImageType *input, mitk::Image *mask, bool forceOverwrite);
template <typename LabelSetImageType, typename ImageType>
void InitializeByLabeledImageProcessing(LabelSetImageType *input, ImageType *other);
/** helper needed for ensuring unique values in all layers until the refactoring is done.
returns a sorted list of all labels.*/
LabelValueVectorType GetUsedLabelValues() const;
//helper function that ensures
void RegisterLabelSet(mitk::LabelSet* ls);
void ReleaseLabelSet(mitk::LabelSet* ls);
std::vector<LabelSet::Pointer> m_LabelSetContainer;
std::vector<Image::Pointer> m_LayerContainer;
int m_ActiveLayer;
bool m_activeLayerInvalid;
};
/**
* @brief Equal A function comparing two label set images for beeing equal in meta- and imagedata
*
* @ingroup MITKTestingAPI
*
* Following aspects are tested for equality:
* - LabelSetImage members
* - working image data
* - layer image data
* - labels in label set
*
* @param rightHandSide An image to be compared
* @param leftHandSide An image to be compared
* @param eps Tolerance for comparison. You can use mitk::eps in most cases.
* @param verbose Flag indicating if the user wants detailed console output or not.
* @return true, if all subsequent comparisons are true, false otherwise
*/
MITKMULTILABEL_EXPORT bool Equal(const mitk::LabelSetImage &leftHandSide,
const mitk::LabelSetImage &rightHandSide,
ScalarType eps,
bool verbose);
/** temporery namespace that is used until the new class MultiLabelSegmentation is
introduced. It allows to already introduce/use some upcoming definitions, while
refactoring code.*/
namespace MultiLabelSegmentation
{
enum class MergeStyle
{
- Replace, //The old label content of a lable value will be replaced by its new label content.
+ Replace, //The old label content of a label value will be replaced by its new label content.
//Therefore pixels that are labeled might become unlabeled again.
//(This means that a lock of the value is also ignored).
Merge //The union of old and new label content will be generated.
};
enum class OverwriteStyle
{
RegardLocks, //Locked labels in the same spatial group will not be overwritten/changed.
IgnoreLocks //Label locks in the same spatial group will be ignored, so these labels might be changed.
};
}
/**Helper function that transfers pixels of the specified source label from source image to the destination image by using
a specified destination label for a specific timestep. Function processes the whole image volume of the specified time step.
@remark in its current implementation the function only transfers contents of the active layer of the passed LabelSetImages.
@remark the function assumes that it is only called with source and destination image of same geometry.
@remark CAUTION: The function is not save if sourceImage and destinationImage are the same instance and more than one label is transferred,
because the changes are made in-place for performance reasons in multiple passes. If a mapped value A equals an "old value"
that occurs later in the mapping, one ends up with a wrong transfer, as a pixel would be first mapped to A and then later again, because
it is also an "old" value in the mapping table.
@param sourceImage Pointer to the LabelSetImage which active layer should be used as source for the transfer.
@param destinationImage Pointer to the LabelSetImage which active layer should be used as destination for the transfer.
@param labelMapping Map that encodes the mappings of all label pixel transfers that should be done. First element is the
label in the source image. The second element is the label that transferred pixels should become in the destination image.
The order in which the labels will be transfered is the same order of elements in the labelMapping.
If you use a heterogeneous label mapping (e.g. (1,2); so changing the label while transfering), keep in mind that
for the MergeStyle and OverwriteStyle only the destination label (second element) is relevant (e.g. what should be
altered with MergeStyle Replace).
@param mergeStyle indicates how the transfer should be done (merge or replace). For more details see documentation of
MultiLabelSegmentation::MergeStyle.
@param overwriteStlye indicates if label locks in the destination image should be regarded or not. For more details see
documentation of MultiLabelSegmentation::OverwriteStyle.
@param timeStep indicate the time step that should be transferred.
@pre sourceImage and destinationImage must be valid
@pre sourceImage and destinationImage must contain the indicated timeStep
@pre sourceImage must contain all indicated sourceLabels in its active layer.
@pre destinationImage must contain all indicated destinationLabels in its active layer.*/
MITKMULTILABEL_EXPORT void TransferLabelContentAtTimeStep(const LabelSetImage* sourceImage, LabelSetImage* destinationImage,
const TimeStepType timeStep, std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping = { {1,1} },
MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
/**Helper function that transfers pixels of the specified source label from source image to the destination image by using
a specified destination label. Function processes the whole image volume for all time steps.
For more details please see TransferLabelContentAtTimeStep for LabelSetImages.
@sa TransferLabelContentAtTimeStep*/
MITKMULTILABEL_EXPORT void TransferLabelContent(const LabelSetImage* sourceImage, LabelSetImage* destinationImage, std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping = { {1,1} },
MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
/**Helper function that transfers pixels of the specified source label from source image to the destination image by using
a specified destination label for a specific timestep. Function processes the whole image volume of the specified time step.
@remark the function assumes that it is only called with source and destination image of same geometry.
@remark CAUTION: The function is not save, if sourceImage and destinationImage are the same instance and you transfer more then one
label, because the changes are made inplace for performance reasons but not in one pass. If a mapped value A equals a "old value"
that is later in the mapping, one ends up with a wrong transfer, as a pixel would be first mapped to A and then latter again, because
it is also an "old" value in the mapping table.
@param sourceImage Pointer to the image that should be used as source for the transfer.
@param destinationImage Pointer to the image that should be used as destination for the transfer.
@param destinationLabelSet Pointer to the label set specifying labels and lock states in the destination image. Unkown pixel
values in the destinationImage will be assumed to be unlocked.
@param sourceBackground Value indicating the background in the source image.
@param destinationBackground Value indicating the background in the destination image.
@param destinationBackgroundLocked Value indicating the lock state of the background in the destination image.
@param labelMapping Map that encodes the mappings of all label pixel transfers that should be done. First element is the
label in the source image. The second element is the label that transferred pixels should become in the destination image.
The order in which the labels will be transfered is the same order of elements in the labelMapping.
If you use a heterogeneous label mapping (e.g. (1,2); so changing the label while transfering), keep in mind that
for the MergeStyle and OverwriteStyle only the destination label (second element) is relevant (e.g. what should be
altered with MergeStyle Replace).
@param mergeStyle indicates how the transfer should be done (merge or replace). For more details see documentation of
MultiLabelSegmentation::MergeStyle.
@param overwriteStlye indicates if label locks in the destination image should be regarded or not. For more details see
documentation of MultiLabelSegmentation::OverwriteStyle.
@param timeStep indicate the time step that should be transferred.
@pre sourceImage, destinationImage and destinationLabelSet must be valid
@pre sourceImage and destinationImage must contain the indicated timeStep
@pre destinationLabelSet must contain all indicated destinationLabels for mapping.*/
MITKMULTILABEL_EXPORT void TransferLabelContentAtTimeStep(const Image* sourceImage, Image* destinationImage, const mitk::LabelSet* destinationLabelSet,
const TimeStepType timeStep, mitk::Label::PixelType sourceBackground = LabelSetImage::UnlabeledValue,
mitk::Label::PixelType destinationBackground = LabelSetImage::UnlabeledValue,
bool destinationBackgroundLocked = false,
std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping = { {1,1} },
MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
/**Helper function that transfers pixels of the specified source label from source image to the destination image by using
a specified destination label. Function processes the whole image volume for all time steps.
For more details please see TransferLabelContentAtTimeStep.
@sa TransferLabelContentAtTimeStep*/
MITKMULTILABEL_EXPORT void TransferLabelContent(const Image* sourceImage, Image* destinationImage, const mitk::LabelSet* destinationLabelSet,
mitk::Label::PixelType sourceBackground = LabelSetImage::UnlabeledValue,
mitk::Label::PixelType destinationBackground = LabelSetImage::UnlabeledValue,
bool destinationBackgroundLocked = false,
std::vector<std::pair<Label::PixelType, Label::PixelType> > labelMapping = { {1,1} },
MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
} // namespace mitk
#endif
diff --git a/Modules/OpenCL/mitkOclDataSet.cpp b/Modules/OpenCL/mitkOclDataSet.cpp
index 9d60645971..5337a5981d 100644
--- a/Modules/OpenCL/mitkOclDataSet.cpp
+++ b/Modules/OpenCL/mitkOclDataSet.cpp
@@ -1,172 +1,172 @@
/*============================================================================
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 "mitkOclDataSet.h"
#include "mitkCommon.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include "mitkOclUtils.h"
#include <fstream>
//#define SHOW_MEM_INFO
mitk::OclDataSet::OclDataSet() : m_gpuBuffer(nullptr), m_context(nullptr), m_bufferSize(0), m_gpuModified(false), m_cpuModified(false),
m_Data(nullptr), m_BpE(1)
{
}
mitk::OclDataSet::~OclDataSet()
{
MITK_DEBUG << "OclDataSet Destructor";
//release GMEM Image buffer
if (m_gpuBuffer) clReleaseMemObject(m_gpuBuffer);
}
cl_mem mitk::OclDataSet::CreateGPUBuffer()
{
MITK_DEBUG << "InitializeGPUBuffer call with: BPE=" << m_BpE;
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
m_context = resources->GetContext();
int clErr;
if (m_gpuBuffer) clReleaseMemObject(m_gpuBuffer);
m_gpuBuffer = clCreateBuffer(m_context, CL_MEM_READ_WRITE, m_bufferSize * (size_t)m_BpE, nullptr, &clErr);
#ifdef SHOW_MEM_INFO
MITK_INFO << "Created GPU Buffer Object of size: " << (size_t)m_BpE * m_bufferSize << " Bytes";
#endif
CHECK_OCL_ERR(clErr);
if (clErr != CL_SUCCESS)
mitkThrow() << "openCL Error when creating Buffer";
return m_gpuBuffer;
}
bool mitk::OclDataSet::IsModified(int _type)
{
if (_type) return m_cpuModified;
else return m_gpuModified;
}
void mitk::OclDataSet::Modified(int _type)
{
// defines... GPU: 0, CPU: 1
m_cpuModified = _type;
m_gpuModified = !_type;
}
int mitk::OclDataSet::TransferDataToGPU(cl_command_queue gpuComQueue)
{
cl_int clErr = 0;
// check whether an image present
if (m_Data == nullptr){
MITK_ERROR("ocl.DataSet") << "(mitk) No data present!\n";
return -1;
}
// there is a need for copy only if RAM-Data newer then GMEM data
if (m_cpuModified)
{
//check the buffer
if(m_gpuBuffer == nullptr)
{
CreateGPUBuffer();
}
if (m_gpuBuffer != nullptr)
{
clErr = clEnqueueWriteBuffer(gpuComQueue, m_gpuBuffer, CL_TRUE, 0, m_bufferSize * (size_t)m_BpE, m_Data, 0, NULL, NULL);
MITK_DEBUG << "Wrote Data to GPU Buffer Object.";
CHECK_OCL_ERR(clErr);
m_gpuModified = true;
if (clErr != CL_SUCCESS)
mitkThrow() << "openCL Error when writing Buffer";
}
else
{
MITK_ERROR << "No GPU buffer present!";
}
}
return clErr;
}
cl_mem mitk::OclDataSet::GetGPUBuffer()
{
// query image object info only if already initialized
if( this->m_gpuBuffer )
{
#ifdef SHOW_MEM_INFO
cl_int clErr = 0;
// clGetMemObjectInfo()
cl_mem_object_type memInfo;
clErr = clGetMemObjectInfo(this->m_gpuBuffer, CL_MEM_TYPE, sizeof(cl_mem_object_type), &memInfo, nullptr );
CHECK_OCL_ERR(clErr);
MITK_DEBUG << "Querying info for object, recieving: " << memInfo;
#endif
}
return m_gpuBuffer;
}
void* mitk::OclDataSet::TransferDataToCPU(cl_command_queue gpuComQueue)
{
cl_int clErr = 0;
// if image created on GPU, needs to create mitk::Image
if( m_gpuBuffer == nullptr ){
MITK_ERROR("ocl.DataSet") << "(mitk) No buffer present!\n";
return nullptr;
}
// check buffersize
char* data = new char[m_bufferSize * (size_t)m_BpE];
// debug info
#ifdef SHOW_MEM_INFO
oclPrintMemObjectInfo( m_gpuBuffer );
#endif
clErr = clEnqueueReadBuffer( gpuComQueue, m_gpuBuffer, CL_TRUE, 0, m_bufferSize * (size_t)m_BpE, data ,0, nullptr, nullptr);
CHECK_OCL_ERR(clErr);
if(clErr != CL_SUCCESS)
mitkThrow() << "openCL Error when reading Output Buffer";
clFlush( gpuComQueue );
// the cpu data is same as gpu
this->m_gpuModified = false;
return (void*) data;
}
void mitk::OclDataSet::SetBufferSize(size_t size)
{
m_bufferSize = size;
}
void mitk::OclDataSet::SetBpE(unsigned short BpE)
{
m_BpE = BpE;
}
diff --git a/Modules/OpenCL/mitkOclFilter.cpp b/Modules/OpenCL/mitkOclFilter.cpp
index c7c838e236..db9772822d 100644
--- a/Modules/OpenCL/mitkOclFilter.cpp
+++ b/Modules/OpenCL/mitkOclFilter.cpp
@@ -1,351 +1,351 @@
/*============================================================================
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.
============================================================================*/
//Ocl
#include "mitkOclFilter.h"
#include "mitkOclUtils.h"
#include "mitkOpenCLActivator.h"
//Mitk
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkConfig.h>
//usService
#include "usServiceReference.h"
#include <usServiceRegistration.h>
#include <usModuleContext.h>
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleResource.h>
#include <usModuleResourceStream.h>
//standard library
#include <thread>
mitk::OclFilter::OclFilter()
: m_ClCompilerFlags(""),
m_ClProgram(nullptr),
m_CommandQue(nullptr),
m_FilterID("mitkOclFilter"),
m_Preambel(" "),
m_Initialized(false)
{
}
mitk::OclFilter::OclFilter(const char* filename)
: m_ClCompilerFlags(""),
m_ClProgram(nullptr),
m_CommandQue(nullptr),
m_FilterID(filename),
m_Preambel(" "),
m_Initialized(false)
{
m_ClFiles.push_back(filename);
}
mitk::OclFilter::~OclFilter()
{
MITK_DEBUG << "OclFilter Destructor";
// release program
if (m_ClProgram)
{
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
// remove program from storage
resources->RemoveProgram(m_FilterID);
}
}
bool mitk::OclFilter::ExecuteKernel( cl_kernel kernel, unsigned int workSizeDim )
{
cl_int clErr = 0;
clErr = clEnqueueNDRangeKernel( this->m_CommandQue, kernel, workSizeDim,
nullptr, this->m_GlobalWorkSize, m_LocalWorkSize, 0, nullptr, nullptr);
CHECK_OCL_ERR( clErr );
return ( clErr == CL_SUCCESS );
}
bool mitk::OclFilter::ExecuteKernelChunks( cl_kernel kernel, unsigned int workSizeDim, size_t* chunksDim )
{
size_t offset[3] ={0, 0, 0};
cl_int clErr = 0;
if(workSizeDim == 2)
{
for(offset[0] = 0; offset[0] < m_GlobalWorkSize[0]; offset[0] += chunksDim[0])
{
for(offset[1] = 0; offset[1] < m_GlobalWorkSize[1]; offset[1] += chunksDim[1])
{
clErr |= clEnqueueNDRangeKernel(this->m_CommandQue, kernel, workSizeDim,
offset, chunksDim, m_LocalWorkSize, 0, nullptr, nullptr);
}
}
}
else if(workSizeDim == 3)
{
for(offset[0] = 0; offset[0] < m_GlobalWorkSize[0]; offset[0] += chunksDim[0])
{
for(offset[1] = 0; offset[1] < m_GlobalWorkSize[1]; offset[1] += chunksDim[1])
{
for(offset[2] = 0; offset[2] < m_GlobalWorkSize[2]; offset[2] += chunksDim[2])
{
clErr |= clEnqueueNDRangeKernel( this->m_CommandQue, kernel, workSizeDim,
offset, chunksDim, m_LocalWorkSize, 0, nullptr, nullptr);
}
}
}
}
CHECK_OCL_ERR(clErr);
return ( clErr == CL_SUCCESS );
}
bool mitk::OclFilter::ExecuteKernelChunksInBatches(cl_kernel kernel, unsigned int workSizeDim, size_t* chunksDim, size_t batchSize, int waitTimems)
{
size_t offset[3] = { 0, 0, 0 };
cl_int clErr = 0;
unsigned int currentChunk = 0;
cl_event* waitFor = new cl_event[batchSize];
if (workSizeDim == 2)
{
for (offset[0] = 0; offset[0] < m_GlobalWorkSize[0]; offset[0] += chunksDim[0])
{
for (offset[1] = 0; offset[1] < m_GlobalWorkSize[1]; offset[1] += chunksDim[1])
{
if (currentChunk % batchSize == 0 && currentChunk != 0)
{
clWaitForEvents(batchSize, &waitFor[0]);
std::this_thread::sleep_for(std::chrono::milliseconds(waitTimems));
clErr |= clEnqueueNDRangeKernel(this->m_CommandQue, kernel, workSizeDim,
offset, chunksDim, m_LocalWorkSize, 0, nullptr, &waitFor[0]);
}
else
{
clErr |= clEnqueueNDRangeKernel(this->m_CommandQue, kernel, workSizeDim,
offset, chunksDim, m_LocalWorkSize, 0, nullptr, &waitFor[currentChunk % batchSize]);
}
currentChunk++;
}
}
}
else if (workSizeDim == 3)
{
for (offset[0] = 0; offset[0] < m_GlobalWorkSize[0]; offset[0] += chunksDim[0])
{
for (offset[1] = 0; offset[1] < m_GlobalWorkSize[1]; offset[1] += chunksDim[1])
{
for (offset[2] = 0; offset[2] < m_GlobalWorkSize[2]; offset[2] += chunksDim[2])
{
if (currentChunk % batchSize == 0 && currentChunk != 0)
{
clWaitForEvents(batchSize, &waitFor[0]);
std::this_thread::sleep_for(std::chrono::milliseconds(waitTimems));
clErr |= clEnqueueNDRangeKernel(this->m_CommandQue, kernel, workSizeDim,
offset, chunksDim, m_LocalWorkSize, 0, nullptr, &waitFor[0]);
}
else
{
clErr |= clEnqueueNDRangeKernel(this->m_CommandQue, kernel, workSizeDim,
offset, chunksDim, m_LocalWorkSize, 0, nullptr, &waitFor[currentChunk % batchSize]);
}
currentChunk++;
}
}
}
}
CHECK_OCL_ERR(clErr);
return (clErr == CL_SUCCESS);
}
bool mitk::OclFilter::Initialize()
{
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
m_CommandQue = resources->GetCommandQueue();
cl_int clErr = 0;
m_Initialized = CHECK_OCL_ERR(clErr);
if ( m_ClFiles.empty())
{
MITK_ERROR<<"No OpenCL Source FILE specified";
return false;
}
if (m_ClProgram == nullptr)
{
try
{
this->m_ClProgram = resources->GetProgram( this->m_FilterID );
}
catch(const mitk::Exception& e)
{
MITK_INFO << "Program not stored in resource manager, compiling. " << e;
this->CompileSource();
}
}
return m_Initialized;
}
void mitk::OclFilter::LoadSourceFiles(CStringList &sourceCode, ClSizeList &sourceCodeSize)
{
for( CStringList::iterator it = m_ClFiles.begin(); it != m_ClFiles.end(); ++it )
{
MITK_DEBUG << "Load file :" << *it;
us::ModuleResource mdr = GetModule()->GetResource(*it);
if( !mdr.IsValid() )
MITK_WARN << "Could not load resource: " << mdr.GetName() << " is invalid!";
us::ModuleResourceStream rss(mdr);
// read resource file to a string
std::istreambuf_iterator<char> eos;
std::string source(std::istreambuf_iterator<char>(rss), eos);
// add preambel and build up string to compile
std::string src(m_Preambel);
src.append("\n");
src.append(source);
// allocate new char buffer
char* tmp = new char[src.size() + 1];
strcpy(tmp,src.c_str());
// add source to list
sourceCode.push_back((const char*)tmp);
sourceCodeSize.push_back(src.size());
}
}
void mitk::OclFilter::CompileSource()
{
// helper variable
int clErr = 0;
CStringList sourceCode;
ClSizeList sourceCodeSize;
if (m_ClFiles.empty())
{
MITK_ERROR("ocl.filter") << "No shader source file was set";
return;
}
//get a valid opencl context
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
cl_context gpuContext = resources->GetContext();
// load the program source from file
LoadSourceFiles(sourceCode, sourceCodeSize);
if ( !sourceCode.empty() )
{
// create program from all files in the file list
m_ClProgram = clCreateProgramWithSource(gpuContext, sourceCode.size(), &sourceCode[0], &sourceCodeSize[0], &clErr);
CHECK_OCL_ERR(clErr);
// build the source code
MITK_DEBUG << "Building Program Source";
std::string compilerOptions = "";
compilerOptions.append(m_ClCompilerFlags);
MITK_DEBUG("ocl.filter") << "cl compiler flags: " << compilerOptions.c_str();
clErr = clBuildProgram(m_ClProgram, 0, nullptr, compilerOptions.c_str(), nullptr, nullptr);
CHECK_OCL_ERR(clErr);
// if OpenCL Source build failed
if (clErr != CL_SUCCESS)
{
MITK_ERROR("ocl.filter") << "Failed to build source";
oclLogBuildInfo(m_ClProgram, resources->GetCurrentDevice() );
oclLogBinary(m_ClProgram, resources->GetCurrentDevice() );
m_Initialized = false;
}
// store the succesfully build program into the program storage provided by the resource service
resources->InsertProgram(m_ClProgram, m_FilterID, true);
// free the char buffers with the source code
for( CStringList::iterator it = sourceCode.begin(); it != sourceCode.end(); ++it )
{
delete[] *it;
}
}
else
{
MITK_ERROR("ocl.filter") << "Could not load from source";
m_Initialized = false;
}
}
void mitk::OclFilter::SetWorkingSize(unsigned int locx, unsigned int dimx, unsigned int locy, unsigned int dimy, unsigned int locz, unsigned int dimz)
{
// set the local work size
this->m_LocalWorkSize[0] = locx;
this->m_LocalWorkSize[1] = locy;
this->m_LocalWorkSize[2] = locz;
this->m_GlobalWorkSize[0] = dimx;
this->m_GlobalWorkSize[1] = dimy;
this->m_GlobalWorkSize[2] = dimz;
// estimate the global work size
this->m_GlobalWorkSize[0] = iDivUp( dimx, this->m_LocalWorkSize[0]) * this->m_LocalWorkSize[0];
if ( dimy > 1)
this->m_GlobalWorkSize[1] = iDivUp( dimy, this->m_LocalWorkSize[1]) * this->m_LocalWorkSize[1];
if( dimz > 1 )
this->m_GlobalWorkSize[2] = iDivUp( dimz, this->m_LocalWorkSize[2]) * this->m_LocalWorkSize[2];
}
void mitk::OclFilter::SetSourcePreambel(const char* preambel)
{
this->m_Preambel = preambel;
}
void mitk::OclFilter::AddSourceFile(const char* filename)
{
m_ClFiles.push_back(filename);
}
void mitk::OclFilter::SetCompilerFlags(const char* flags)
{
m_ClCompilerFlags = flags;
}
bool mitk::OclFilter::IsInitialized()
{
return m_Initialized;
}
unsigned long mitk::OclFilter::GetDeviceMemory()
{
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(GetModuleContext()->GetServiceReference<OclResourceService>());
auto device = resources->GetCurrentDevice();
return oclGetGlobalMemSize(device);
}
diff --git a/Modules/OpenCL/mitkOclImage.cpp b/Modules/OpenCL/mitkOclImage.cpp
index fc7acd3b4f..31aa963c8d 100644
--- a/Modules/OpenCL/mitkOclImage.cpp
+++ b/Modules/OpenCL/mitkOclImage.cpp
@@ -1,359 +1,359 @@
/*============================================================================
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 "mitkOclImage.h"
#include "mitkImageDataItem.h"
#include "mitkCommon.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include "mitkOclUtils.h"
#include <mitkImageReadAccessor.h>
#include <fstream>
mitk::OclImage::OclImage() : m_gpuImage(nullptr), m_context(nullptr), m_bufferSize(0), m_gpuModified(false), m_cpuModified(false),
m_Image(nullptr), m_dim(0), m_Dims(nullptr), m_BpE(1), m_formatSupported(false)
{
}
mitk::OclImage::~OclImage()
{
MITK_INFO << "OclImage Destructor";
//release GMEM Image buffer
if (m_gpuImage) clReleaseMemObject(m_gpuImage);
}
cl_mem mitk::OclImage::CreateGPUImage(unsigned int _wi, unsigned int _he, unsigned int _de,
unsigned int _bpp)
{
MITK_INFO << "CreateGPUImage call with: BPP=" << _bpp;
this->m_Dims = new unsigned int[MAX_DIMS];
m_Dims[0] = _wi;
m_Dims[1] = _he;
m_Dims[2] = _de;
for (unsigned int i=3; i<MAX_DIMS; i++)
m_Dims[i] = 1;
m_bufferSize = _wi * _he * _de;
m_BpE = _bpp;
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
cl_context gpuContext = resources->GetContext();
int clErr;
m_gpuImage = clCreateBuffer( gpuContext, CL_MEM_READ_WRITE, m_bufferSize * m_BpE, nullptr, &clErr);
CHECK_OCL_ERR(clErr);
return m_gpuImage;
}
void mitk::OclImage::InitializeByMitkImage(mitk::Image::Pointer _image)
{
this->m_Image = _image;
this->m_cpuModified = true;
this->m_gpuModified = false;
this->m_gpuImage = nullptr;
// compute the size of the GMEM buffer
this->m_dim = this->m_Image->GetDimension();
this->m_Dims = this->m_Image->GetDimensions();
MITK_INFO << "Image: " << this->m_Dims[0] <<"x"<< this->m_Dims[1] <<"x"<< this->m_Dims[2];
// get the dimensions
this->m_bufferSize = 1;
for (unsigned int i=0; i<this->m_dim; i++)
{
this->m_bufferSize *= this->m_Dims[i];
}
// multiply by sizeof(PixelType)
this->m_BpE = ( this->m_Image->GetPixelType().GetBpe() / 8);
}
bool mitk::OclImage::IsModified(int _type)
{
if (_type) return m_cpuModified;
else return m_gpuModified;
}
void mitk::OclImage::Modified(int _type)
{
// defines... GPU: 0, CPU: 1
m_cpuModified = _type;
m_gpuModified = !_type;
}
int mitk::OclImage::TransferDataToGPU(cl_command_queue gpuComQueue)
{
cl_int clErr = 0;
// check whether an image present
if (!m_Image->IsInitialized()){
MITK_ERROR("ocl.Image") << "(mitk) Image not initialized!\n";
return -1;
}
// there is a need for copy only if RAM-Data newer then GMEM data
if (m_cpuModified)
{
//check the buffer
if(m_gpuImage == nullptr)
{
clErr = this->AllocateGPUImage();
}
if (m_Image->IsInitialized() &&
(clErr == CL_SUCCESS))
{
const size_t origin[3] = {0, 0, 0};
const size_t region[3] = {m_Dims[0], m_Dims[1], m_Dims[2]};
if( this->m_formatSupported )
{
mitk::ImageReadAccessor accessor(m_Image);
clErr = clEnqueueWriteImage( gpuComQueue, m_gpuImage, CL_TRUE, origin, region, 0, 0, accessor.GetData(), 0, nullptr, nullptr);
}
else
{
MITK_ERROR << "Selected image format currently not supported...";
}
CHECK_OCL_ERR(clErr);
}
m_gpuModified = true;
}
return clErr;
}
cl_int mitk::OclImage::AllocateGPUImage()
{
cl_int clErr = 0;
us::ServiceReference<OclResourceService> ref = GetModuleContext()->GetServiceReference<OclResourceService>();
OclResourceService* resources = GetModuleContext()->GetService<OclResourceService>(ref);
cl_context gpuContext = resources->GetContext();
// initialize both proposed and supported format variables to same value
this->m_proposedFormat = this->ConvertPixelTypeToOCLFormat();
this->m_supportedFormat = this->m_proposedFormat;
// test the current format for HW support
this->m_formatSupported = resources->GetIsFormatSupported( &(this->m_supportedFormat) );
// create an transfer kernel object in case the proposed format is not supported
if( !(this->m_formatSupported) )
{
mitkThrowException(mitk::ImageTypeIsNotSupportedByGPU) << "Original format not supported on the installed graphics card.";
}
_cl_image_desc imageDescriptor;
imageDescriptor.image_width = *(m_Dims);
imageDescriptor.image_height = *(m_Dims + 1);
imageDescriptor.image_depth = *(m_Dims + 2);
imageDescriptor.image_array_size = 0;
imageDescriptor.image_row_pitch = 0;
imageDescriptor.image_slice_pitch = 0;
imageDescriptor.num_mip_levels = 0;
imageDescriptor.num_samples = 0;
imageDescriptor.buffer = nullptr;
// create new buffer
if( this->m_dim > 2)
{
//Create a 3D Image
imageDescriptor.image_type = CL_MEM_OBJECT_IMAGE3D;
}
else
{
//Create a 2D Image
imageDescriptor.image_type = CL_MEM_OBJECT_IMAGE2D;
}
m_gpuImage = clCreateImage(gpuContext, CL_MEM_READ_ONLY, &m_supportedFormat, &imageDescriptor, nullptr, &clErr);
CHECK_OCL_ERR(clErr);
return clErr;
}
cl_mem mitk::OclImage::GetGPUImage(cl_command_queue gpuComQueue)
{
// clGetMemObjectInfo()
cl_mem_object_type memInfo;
cl_int clErr = 0;
// query image object info only if already initialized
if( this->m_gpuImage )
{
clErr = clGetMemObjectInfo(this->m_gpuImage, CL_MEM_TYPE, sizeof(cl_mem_object_type), &memInfo, nullptr );
CHECK_OCL_ERR(clErr);
}
MITK_INFO << "Querying info for object, recieving: " << memInfo;
// test if m_gpuImage CL_MEM_IMAGE_2/3D
// if not, copy buffer to image
if (memInfo == CL_MEM_OBJECT_BUFFER)
{
MITK_WARN << " Passed oclImage is a buffer-object, creating image";
//hold a copy of the buffer gmem pointer
cl_mem tempBuffer = this->m_gpuImage;
const size_t origin[3] = {0, 0, 0};
size_t region[3] = {this->m_Dims[0], this->m_Dims[1], 1};
clErr = this->AllocateGPUImage();
this->m_dim = 3;
//copy last data to the image data
clErr = clEnqueueCopyBufferToImage( gpuComQueue, tempBuffer, m_gpuImage, 0, origin, region, 0, nullptr, nullptr);
CHECK_OCL_ERR(clErr);
//release pointer
clReleaseMemObject(tempBuffer);
}
return m_gpuImage;
}
void mitk::OclImage::SetPixelType(const cl_image_format *_image)
{
this->m_proposedFormat.image_channel_data_type = _image->image_channel_data_type;
this->m_proposedFormat.image_channel_order = _image->image_channel_order;
}
void* mitk::OclImage::TransferDataToCPU(cl_command_queue gpuComQueue)
{
cl_int clErr = 0;
// if image created on GPU, needs to create mitk::Image
if( m_Image.IsNull() ){
MITK_INFO << "Image not initialized, creating new one.";
m_Image = mitk::Image::New();
}
// check buffersize/image size
char* data = new char[m_bufferSize * m_BpE];
// debug info
oclPrintMemObjectInfo( m_gpuImage );
clErr = clEnqueueReadBuffer( gpuComQueue, m_gpuImage, CL_FALSE, 0, m_bufferSize * m_BpE, data ,0, nullptr, nullptr);
CHECK_OCL_ERR(clErr);
clFlush( gpuComQueue );
// the cpu data is same as gpu
this->m_gpuModified = false;
return (void*) data;
}
cl_image_format mitk::OclImage::ConvertPixelTypeToOCLFormat()
{
cl_image_format texFormat;
//single channel Gray-Valued Images
texFormat.image_channel_order = CL_R;
MITK_INFO << "Class own value: " << this->m_BpE;
switch ( this->m_BpE )
{
case 1:
texFormat.image_channel_data_type = CL_UNSIGNED_INT8;
MITK_INFO<< "PixelType: UCHAR => CLFormat: [CL_UNORM_INT8, CL_R]";
break;
case 2:
texFormat.image_channel_data_type = CL_SIGNED_INT16;
// texFormat.image_channel_order = CL_R;
MITK_INFO<< "PixelType: SHORT => CLFormat: [CL_SIGNED_INT16, CL_R]";
break;
case 4:
texFormat.image_channel_data_type = CL_FLOAT;
MITK_INFO<< "Choosing CL_FLOAT";
break;
default:
texFormat.image_channel_data_type = CL_UNORM_INT8;
texFormat.image_channel_order = CL_RG;
MITK_INFO<< "Choosing (default) short: 2-Channel UCHAR";
break;
}
return texFormat;
}
int mitk::OclImage::GetDimension(int idx) const
{
if (this->m_dim > idx)
{
return m_Dims[idx];
}
else
{
MITK_WARN << "Trying to access non-existing dimension.";
return 1;
}
}
void mitk::OclImage::SetDimensions(unsigned int* Dims)
{
m_Dims = Dims;
}
void mitk::OclImage::SetDimension(unsigned short dim)
{
m_dim = dim;
}
float mitk::OclImage::GetSpacing(int idx)
{
if (this->m_dim > idx)
{
const mitk::Vector3D imSpacing = m_Image->GetSlicedGeometry()->GetSpacing();
return imSpacing[idx];
}
else
{
MITK_WARN << "Trying to access non-existing dimension.";
return 1;
}
}
void mitk::OclImage::InitializeMITKImage()
{
this->m_Image = mitk::Image::New();
}
void mitk::OclImage::GetOffset(float* _imOffset) const
{
itk::Vector<float, 3> result2;
result2.Fill(0.0f);
result2 = this->m_Image->GetGeometry()->GetIndexToWorldTransform()->GetOffset();
_imOffset[0] = result2[0];
_imOffset[1] = result2[1];
_imOffset[2] = result2[2];
}
diff --git a/Modules/OpenCL/mitkOclImageFormats.h b/Modules/OpenCL/mitkOclImageFormats.h
index 092bf32949..08b5a4cd8d 100644
--- a/Modules/OpenCL/mitkOclImageFormats.h
+++ b/Modules/OpenCL/mitkOclImageFormats.h
@@ -1,118 +1,118 @@
/*============================================================================
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 mitkOclImageFormats_h
#define mitkOclImageFormats_h
//mitk
#include <mitkCommon.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
//itk
#include <itkLightObject.h>
#include <itkObjectFactory.h>
//ocl
#include "mitkOclUtils.h"
#include <MitkOpenCLExports.h>
#define MAX_FORMATS 10
#define MAX_DATA_TYPES 12
namespace mitk
{
/**
@class oclImageFormats
@brief A class handling the (un)supported OpenCL Image formats.
This class checks whether a format is supported or not and acts accordingly.
*/
class MITKOPENCL_EXPORT OclImageFormats : public itk::LightObject
{
public:
mitkClassMacroItkParent(OclImageFormats, itk::LightObject);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
/** @brief Checks if format supported.
@param format The image format to be checked for support.
@return True if the parameter is supported.
*/
bool IsFormatSupported(cl_image_format* format);
/** @brief Finds one supported image format similar to the given format.
In case the input format is supported, the output format will contain the same value.
@param inputformat The (unsupported) image format
@param outputformat A supported image format
@return True if a supported format was changed.
*/
bool GetNearestSupported(cl_image_format* inputformat, cl_image_format* outputformat);
/**
* @brief SetGPUContext Set the GPU context. Must be called before using this class!
* @param context GPU context in cl format.
*/
void SetGPUContext( cl_context context );
protected:
/** @brief Get and store all available infos
* @throw Throws an mitk::Exception if the GPU context was not defined.
*/
void CollectAvailableFormats();
/**
* @brief OclImageFormats Constructor
*/
OclImageFormats();
/** @brief Destructor (default) */
virtual ~OclImageFormats();
private:
/** @brief Store the given format into the table
* Todo: what table? Where? Why is it called sort?
@param formats A pointer to an array of image formats
Todo: What formats?
@param count Size of the formats array (i.e. how many formats are to be sorted).
@param val an intern value to distinguish between read/write/readwrite type
Todo: what is val?
@param dim Specifies the target image dimension (default IMAGE_2D).
*/
void SortFormats( cl_image_format* formats, cl_uint count, int val=1 , int dims = 2);
/** @brief Get the byte offset to the image support fields.
Todo: What means support field? What is this offset used for? In what unit is it returned?*/
unsigned int GetOffset( cl_image_format format );
using itk::LightObject::PrintSelf;
/** @brief Print all supported formats (in a table) for both 2D and 3D IMAGE */
void PrintSelf();
/** An array to hold the information about IMAGE_2D supported formats. */
unsigned char* m_Image2DSupport;
/** An array to hold the information about IMAGE_3D supported formats. */
unsigned char* m_Image3DSupport;
/** the OpenCL context */
cl_context m_GpuContext;
};
}
#endif
diff --git a/Modules/OpenCL/mitkOclUtils.cpp b/Modules/OpenCL/mitkOclUtils.cpp
index 29ba55113c..c12b659173 100644
--- a/Modules/OpenCL/mitkOclUtils.cpp
+++ b/Modules/OpenCL/mitkOclUtils.cpp
@@ -1,579 +1,579 @@
/*============================================================================
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 "mitkOclUtils.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <cstdio>
#include <cstring>
unsigned int iDivUp(unsigned int dividend, unsigned int divisor){
return (dividend % divisor == 0) ? (dividend / divisor) : (dividend / divisor + 1);
}
cl_int oclGetPlatformID(cl_platform_id* selectedPlatform)
{
cl_uint num_platforms = 0;
cl_platform_id* clPlatformIDs;
cl_int ciErrNum = 0;
ciErrNum = clGetPlatformIDs( 0, nullptr, &num_platforms);
if ( ciErrNum != CL_SUCCESS)
{
MITK_ERROR<<" Error " << ciErrNum << " in clGetPlatformIDs() \n";
throw std::bad_exception();
}
else
{
clPlatformIDs = new cl_platform_id[num_platforms];
ciErrNum = clGetPlatformIDs( num_platforms, clPlatformIDs, nullptr);
if(ciErrNum == CL_SUCCESS)
{
*selectedPlatform = clPlatformIDs[0];
}
}
return CL_SUCCESS;
}
void oclPrintMemObjectInfo(cl_mem memobj)
{
cl_int clErr = 0;
MITK_INFO << "Examining cl_mem object: " << memobj
<< "\n------------------\n";
// CL_MEM_TYPE
cl_mem_object_type objtype;
clErr = clGetMemObjectInfo( memobj, CL_MEM_TYPE, sizeof(cl_mem_object_type),&objtype, nullptr);
CHECK_OCL_ERR( clErr );
switch(objtype)
{
case CL_MEM_OBJECT_BUFFER:
MITK_INFO << "CL_MEM_TYPE \t" << "BUFFER_OBJ" << "\n";
break;
case CL_MEM_OBJECT_IMAGE2D:
MITK_INFO << "CL_MEM_TYPE \t" << "2D IMAGE" << "\n";
break;
case CL_MEM_OBJECT_IMAGE3D:
MITK_INFO << "CL_MEM_TYPE \t" << "3D IMAGE" << "\n";
break;
default:
MITK_INFO << "CL_MEM_TYPE \t" << "[could not resolve]" << "\n";
break;
}
// CL_MEM_FLAGS
cl_mem_flags flags;
clErr = clGetMemObjectInfo( memobj, CL_MEM_FLAGS, sizeof(cl_mem_flags),&flags, nullptr);
CHECK_OCL_ERR( clErr );
switch(flags)
{
case CL_MEM_READ_ONLY:
MITK_INFO << "CL_MEM_FLAGS \t" << "CL_MEM_READ_ONLY" << "\n";
break;
case CL_MEM_WRITE_ONLY:
MITK_INFO << "CL_MEM_FLAGS \t" << "CL_MEM_WRITE_ONLY" << "\n";
break;
case CL_MEM_READ_WRITE:
MITK_INFO << "CL_MEM_FLAGS \t" << "CL_MEM_READ_WRITE" << "\n";
break;
default:
MITK_INFO << "CL_MEM_FLAGS \t" << "not resolved, " << flags << "\n";
break;
}
// get CL_MEM_SIZE
size_t memsize;
clErr = clGetMemObjectInfo( memobj, CL_MEM_SIZE, sizeof(memsize),&memsize, nullptr);
CHECK_OCL_ERR( clErr );
MITK_INFO << "CL_MEM_SIZE \t" << memsize << "\n";
// get CL_MEM_HOST_PTR
float *hostptr;
clErr = clGetMemObjectInfo( memobj, CL_MEM_HOST_PTR, sizeof(void*), (void*) &hostptr, nullptr);
CHECK_OCL_ERR( clErr );
MITK_INFO << "CL_MEM_HOST_PTR \t" << hostptr << "\n";
// get CL_CONTEXT
cl_context gpuctxt;
clErr = clGetMemObjectInfo( memobj, CL_MEM_CONTEXT, sizeof(cl_context), &gpuctxt, nullptr);
CHECK_OCL_ERR( clErr );
MITK_INFO << "CL_CONTEXT \t\t" << gpuctxt << "\n";
// get CL_MEM_REFERENCE_COUNT
cl_uint refs;
clErr = clGetMemObjectInfo( memobj, CL_MEM_REFERENCE_COUNT, sizeof(cl_uint), &refs, nullptr);
CHECK_OCL_ERR(clErr);
MITK_INFO << "CL_REF_COUNT \t" << refs << "\n";
MITK_INFO << "================== \n" << std::endl;
}
void oclPrintDeviceInfo(cl_device_id device)
{
char device_string[1024];
clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_string), &device_string, nullptr);
MITK_INFO("ocl.log")<< " Device : " << device_string;
// CL_DEVICE_INFO
cl_device_type type;
clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(type), &type, nullptr);
if( type & CL_DEVICE_TYPE_CPU )
MITK_INFO("ocl.log")<<" CL_DEVICE_TYPE: CL_DEVICE_TYPE_CPU";
if( type & CL_DEVICE_TYPE_GPU )
MITK_INFO("ocl.log")<<" CL_DEVICE_TYPE: CL_DEVICE_TYPE_GPU";
if( type & CL_DEVICE_TYPE_ACCELERATOR )
MITK_INFO("ocl.log")<<" CL_DEVICE_TYPE: CL_DEVICE_TYPE_ACCELERATOR";
if( type & CL_DEVICE_TYPE_DEFAULT )
MITK_INFO("ocl.log")<<" CL_DEVICE_TYPE: CL_DEVICE_TYPE_DEFAULT";
// CL_DEVICE_MAX_COMPUTE_UNITS
cl_uint compute_units;
clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(compute_units), &compute_units, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_MAX_COMPUTE_UNITS:" << compute_units;
// CL_DEVICE_MAX_WORK_GROUP_SIZE
size_t workitem_size[3];
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(workitem_size), &workitem_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_MAX_WORK_ITEM_SIZES:\t"<< workitem_size[0]<< workitem_size[1]<< workitem_size[2];
// CL_DEVICE_MAX_WORK_GROUP_SIZE
size_t workgroup_size;
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(workgroup_size), &workgroup_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_MAX_WORK_GROUP_SIZE:" << workgroup_size;
// CL_DEVICE_MAX_CLOCK_FREQUENCY
cl_uint clock_frequency;
clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(clock_frequency), &clock_frequency, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_MAX_CLOCK_FREQUENCY:"<< clock_frequency / 1000;
// CL_DEVICE_IMAGE_SUPPORT
cl_bool image_support;
clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(image_support), &image_support, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_IMAGE_SUPPORT:\t" << image_support;
// CL_DEVICE_GLOBAL_MEM_SIZE
cl_ulong mem_size;
clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(mem_size), &mem_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t"<<(unsigned int)(mem_size / (1024 * 1024))<<"Mbytes";
// CL_DEVICE_LOCAL_MEM_SIZE
clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(mem_size), &mem_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_LOCAL_MEM_SIZE:\t\t"<< (unsigned int)(mem_size / (1024)) <<"KByte\n";
// CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(mem_size), &mem_size, nullptr);
MITK_INFO("ocl.log") << " CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t\t" << (unsigned int)(mem_size / (1024)) << "KByte";
//check for image support properties
clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(workgroup_size), &workgroup_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_IMAGE2D_MAX_WIDTH:\t" << workgroup_size;
clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(workgroup_size), &workgroup_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_IMAGE2D_MAX_HEIGHT:\t" << workgroup_size;
clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(workgroup_size), &workgroup_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_IMAGE3D_MAX_WIDTH:\t" << workgroup_size;
clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(workgroup_size), &workgroup_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_IMAGE3D_MAX_HEIGHT:\t" << workgroup_size;
clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(workgroup_size), &workgroup_size, nullptr);
MITK_INFO("ocl.log")<<" CL_DEVICE_IMAGE3D_MAX_DEPTH:\t" << workgroup_size;
// CL_DEVICE_QUEUE_PROPERTIES
cl_command_queue_properties queue_properties;
clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(queue_properties), &queue_properties, nullptr);
if( queue_properties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE )
MITK_INFO("ocl.log")<<" CL_DEVICE_QUEUE_PROPERTIES:\t\t"<< "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE";
if( queue_properties & CL_QUEUE_PROFILING_ENABLE )
MITK_INFO("ocl.log")<<" CL_DEVICE_QUEUE_PROPERTIES:\t\t"<< "CL_QUEUE_PROFILING_ENABLE";
}
cl_ulong oclGetGlobalMemSize(cl_device_id device)
{
cl_ulong mem_size;
clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(mem_size), &mem_size, nullptr);
return mem_size;
}
std::string GetOclErrorAsString( int _clErr )
{
std::string returnString("unkown error number: "+std::to_string(_clErr)+" \n");
switch(_clErr)
{
case CL_SUCCESS:
returnString = "CL_SUCCESS\n";
break;
case CL_DEVICE_NOT_FOUND:
returnString = "CL_DEVICE_NOT_FOUND\n";
break;
case CL_DEVICE_NOT_AVAILABLE:
returnString = "CL_DEVICE_NOT_AVAILABLE\n";
break;
/*case CL_DEVICE_COMPILER_NOT_AVAILABLE:
returnString = "CL_DEVICE_COMPILER_NOT_AVAILABLE\n";
break; */
case CL_MEM_OBJECT_ALLOCATION_FAILURE :
returnString = "CL_MEM_OBJECT_ALLOCATION_FAILURE\n";
break;
case CL_OUT_OF_RESOURCES:
returnString = "CL_OUT_OF_RESOURCES\n";
break;
case CL_OUT_OF_HOST_MEMORY:
returnString = "CL_OUT_OF_HOST_MEMORY\n";
break;
case CL_PROFILING_INFO_NOT_AVAILABLE:
returnString = "CL_PROFILING_INFO_NOT_AVAILABLE\n";
break;
case CL_MEM_COPY_OVERLAP:
returnString = "CL_MEM_COPY_OVERLAP\n";
break;
case CL_IMAGE_FORMAT_MISMATCH:
returnString = "CL_IMAGE_FORMAT_MISMATCH\n";
break;
case CL_IMAGE_FORMAT_NOT_SUPPORTED:
returnString = "CL_IMAGE_FORMAT_NOT_SUPPORTED\n";
break;
case CL_BUILD_PROGRAM_FAILURE:
returnString = "CL_BUILD_PROGRAM_FAILURE\n";
break;
case CL_MAP_FAILURE:
returnString = "CL_MAP_FAILURE\n";
break;
case CL_INVALID_VALUE:
returnString = "CL_INVALID_VALUE\n";
break;
case CL_INVALID_DEVICE_TYPE:
returnString = "CL_INVALID_DEVICE_TYPE\n";
break;
case CL_INVALID_PLATFORM:
returnString = "CL_INVALID_PLATFORM\n";
break;
case CL_INVALID_DEVICE:
returnString = "CL_INVALID_DEVICE\n";
break;
case CL_INVALID_CONTEXT :
returnString = "CL_INVALID_CONTEXT\n";
break;
case CL_INVALID_QUEUE_PROPERTIES:
returnString = "CL_INVALID_QUEUE_PROPERTIES\n";
break;
case CL_INVALID_COMMAND_QUEUE:
returnString = "CL_INVALID_COMMAND_QUEUE\n";
break;
case CL_INVALID_HOST_PTR:
returnString = "CL_INVALID_HOST_PTR\n";
break;
case CL_INVALID_MEM_OBJECT:
returnString = "CL_INVALID_MEM_OBJECT\n";
break;
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
returnString = "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR\n";
break;
case CL_INVALID_IMAGE_SIZE:
returnString = "CL_INVALID_IMAGE_SIZE\n";
break;
case CL_INVALID_SAMPLER :
returnString = "CL_INVALID_SAMPLER\n";
break;
case CL_INVALID_BINARY:
returnString = "CL_INVALID_BINARY\n";
break;
case CL_INVALID_BUILD_OPTIONS:
returnString = "CL_INVALID_BUILD_OPTIONS\n";
break;
case CL_INVALID_PROGRAM:
returnString = "CL_INVALID_PROGRAM\n";
break;
case CL_INVALID_PROGRAM_EXECUTABLE:
returnString = "CL_INVALID_PROGRAM_EXECUTABLE\n";
break;
case CL_INVALID_KERNEL_NAME:
returnString = "CL_INVALID_KERNEL_NAME\n";
break;
case CL_INVALID_KERNEL_DEFINITION:
returnString = "CL_INVALID_KERNEL_DEFINITION\n";
break;
case CL_INVALID_KERNEL :
returnString = "CL_INVALID_KERNEL\n";
break;
case CL_INVALID_ARG_INDEX :
returnString = "CL_INVALID_ARG_INDEX\n";
break;
case CL_INVALID_ARG_VALUE :
returnString = "CL_INVALID_ARG_VALUE\n";
break;
case CL_INVALID_ARG_SIZE :
returnString = "CL_INVALID_ARG_SIZE\n";
break;
case CL_INVALID_KERNEL_ARGS :
returnString = "CL_INVALID_KERNEL_ARGS\n";
break;
case CL_INVALID_WORK_DIMENSION:
returnString = "CL_INVALID_WORK_DIMENSION\n";
break;
case CL_INVALID_WORK_GROUP_SIZE:
returnString = "CL_INVALID_WORK_GROUP_SIZE\n";
break;
case CL_INVALID_WORK_ITEM_SIZE:
returnString = "CL_INVALID_WORK_ITEM_SIZE\n";
break;
case CL_INVALID_GLOBAL_OFFSET:
returnString = "CL_INVALID_GLOBAL_OFFSET\n";
break;
case CL_INVALID_EVENT_WAIT_LIST:
returnString = "CL_INVALID_EVENT_WAIT_LIST\n";
break;
case CL_INVALID_EVENT:
returnString = "CL_INVALID_EVENT\n";
break;
case CL_INVALID_OPERATION:
returnString = "CL_INVALID_OPERATION\n";
break;
case CL_INVALID_GL_OBJECT:
returnString = "CL_INVALID_GL_OBJECT\n";
break;
case CL_INVALID_BUFFER_SIZE :
returnString = "CL_INVALID_BUFFER_SIZE\n";
break;
case CL_INVALID_MIP_LEVEL :
returnString = "CL_INVALID_MIP_LEVEL\n";
break;
default:
break;
}
return returnString;
}
void GetOclError(int _clErr)
{
if(_clErr == CL_SUCCESS)
MITK_WARN << "Called GetOclErr() with no error value: [CL_SUCCESS]";
else
MITK_ERROR << GetOclErrorAsString(_clErr);
}
bool oclCheckError(int _err, const char* filepath, int lineno)
{
if (_err)
{
MITK_ERROR<< "OpenCL Error at " << filepath <<":"<< lineno;
GetOclError(_err);
return 0;
}
return 1;
}
void GetSupportedImageFormats(cl_context _context, cl_mem_object_type _type)
{
const unsigned int entries = 500;
cl_image_format* formats = new cl_image_format[entries];
cl_uint _written = 0;
// OpenCL constant to catch error IDs
cl_int ciErr1;
// Get list of supported image formats for READ_ONLY access
ciErr1 = clGetSupportedImageFormats( _context, CL_MEM_READ_ONLY, _type, entries, formats, &_written);
CHECK_OCL_ERR(ciErr1);
MITK_INFO << "Supported Image Formats, Image: CL_MEM_READ_ONLY \n";
for (unsigned int i=0; i<_written; i++)
{
MITK_INFO<< "ChannelType: " << GetImageTypeAsString(formats[i].image_channel_data_type) << "| ChannelOrder: "<< GetImageTypeAsString(formats[i].image_channel_order) <<"\n";
}
_written = 0;
// Get list of supported image formats for READ_WRITE access
ciErr1 = clGetSupportedImageFormats( _context, CL_MEM_READ_WRITE, _type, entries, formats, &_written);
CHECK_OCL_ERR(ciErr1);
MITK_INFO << "Supported Image Formats, Image: CL_MEM_READ_WRITE (found: " << _written <<") \n";
for (unsigned int i=0; i<_written; i++)
{
MITK_INFO<< "ChannelType: " << GetImageTypeAsString(formats[i].image_channel_data_type) << "| ChannelOrder: "<< GetImageTypeAsString(formats[i].image_channel_order) <<"\n";
}
_written = 0;
// Get list of supported image formats for WRITE_ONLY access
ciErr1 = clGetSupportedImageFormats( _context, CL_MEM_WRITE_ONLY, _type, entries, formats, &_written);
CHECK_OCL_ERR(ciErr1);
MITK_INFO << "Supported Image Formats, Image: CL_MEM_WRITE_ONLY (found: " << _written <<") \n";
for (unsigned int i=0; i<_written; i++)
{
MITK_INFO<< "ChannelType: " << GetImageTypeAsString(formats[i].image_channel_data_type) << "| ChannelOrder: "<< GetImageTypeAsString(formats[i].image_channel_order) <<"\n";
}
}
std::string GetImageTypeAsString( const unsigned int _in)
{
switch(_in)
{
case CL_R:
return "CL_R ";
break;
case CL_A:
return "CL_A ";
break;
case CL_RG:
return "CL_RG ";
break;
case CL_RA:
return "CL_RA ";
break;
case CL_RGB:
return "CL_RGB ";
break;
case CL_RGBA:
return "CL_RGBA ";
break;
case CL_BGRA:
return "CL_BGRA ";
break;
case CL_ARGB:
return "CL_ARGB ";
break;
case CL_INTENSITY:
return "CL_INTENSITY ";
break;
case CL_LUMINANCE:
return "CL_LUMINANCE ";
break;
case CL_SNORM_INT8:
return "CL_SNORM_INT8 ";
break;
case CL_SNORM_INT16:
return "CL_SNORM_INT16 ";
break;
case CL_UNORM_INT8:
return "CL_UNORM_INT8 ";
break;
case CL_UNORM_INT16:
return "CL_UNORM_INT16 ";
break;
case CL_UNORM_SHORT_565:
return "CL_UNORM_SHORT_565 ";
break;
case CL_UNORM_SHORT_555:
return "CL_UNORM_SHORT_555 ";
break;
case CL_UNORM_INT_101010:
return "CL_UNORM_INT_101010 ";
break;
case CL_SIGNED_INT8:
return "CL_SIGNED_INT8 ";
break;
case CL_SIGNED_INT16:
return "CL_SIGNED_INT16 ";
break;
case CL_SIGNED_INT32:
return "CL_SIGNED_INT32 ";
break;
case CL_UNSIGNED_INT8:
return "CL_UNSIGNED_INT8 ";
break;
case CL_UNSIGNED_INT16:
return "CL_UNSIGNED_INT16 ";
break;
case CL_UNSIGNED_INT32:
return "CL_UNSIGNED_INT32 ";
break;
case CL_HALF_FLOAT:
return "CL_HALF_FLOAT ";
break;
case CL_FLOAT:
return "CL_FLOAT ";
break;
default:
return "--";
break;
}
}
void oclLogBinary(cl_program clProg, cl_device_id clDev)
{
// Grab the number of devices associated with the program
cl_uint num_devices;
clGetProgramInfo(clProg, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &num_devices, nullptr);
// Grab the device ids
cl_device_id* devices = (cl_device_id*) malloc(num_devices * sizeof(cl_device_id));
clGetProgramInfo(clProg, CL_PROGRAM_DEVICES, num_devices * sizeof(cl_device_id), devices, 0);
// Grab the sizes of the binaries
size_t* binary_sizes = (size_t*)malloc(num_devices * sizeof(size_t));
clGetProgramInfo(clProg, CL_PROGRAM_BINARY_SIZES, num_devices * sizeof(size_t), binary_sizes, nullptr);
// Now get the binaries
char** ptx_code = (char**)malloc(num_devices * sizeof(char*));
for( unsigned int i=0; i<num_devices; ++i)
{
ptx_code[i] = (char*)malloc(binary_sizes[i]);
}
clGetProgramInfo(clProg, CL_PROGRAM_BINARIES, 0, ptx_code, nullptr);
// Find the index of the device of interest
unsigned int idx = 0;
while((idx < num_devices) && (devices[idx] != clDev))
{
++idx;
}
// If the index is associated, log the result
if( idx < num_devices )
{
MITK_INFO<< "\n ---------------- \n Program Binary: \n -----------------------\n";
MITK_INFO<< ptx_code[idx];
}
free( devices );
free( binary_sizes );
for(unsigned int i=0; i<num_devices; ++i)
{
free(ptx_code[i]);
}
free( ptx_code );
}
void oclLogBuildInfo(cl_program clProg, cl_device_id clDev)
{
char cBuildLog[10240];
clGetProgramBuildInfo(clProg, clDev, CL_PROGRAM_BUILD_LOG, sizeof(cBuildLog), cBuildLog, nullptr);
MITK_INFO<< "\n Program Build Log: \n -----------------------\n";
MITK_INFO<< cBuildLog;
}
diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSource.h b/Modules/OpenIGTLink/mitkIGTLMessageSource.h
index 60584b57ce..f3996c6cf6 100644
--- a/Modules/OpenIGTLink/mitkIGTLMessageSource.h
+++ b/Modules/OpenIGTLink/mitkIGTLMessageSource.h
@@ -1,207 +1,207 @@
/*============================================================================
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 mitkIGTLMessageSource_h
#define mitkIGTLMessageSource_h
#include <itkProcessObject.h>
#include "mitkPropertyList.h"
#include "MitkOpenIGTLinkExports.h"
#include "mitkIGTLMessage.h"
// Microservices
#include <mitkServiceInterface.h>
#include <usServiceRegistration.h>
#include <mutex>
namespace mitk {
/**
* \brief OpenIGTLink message source
*
* Base class for all OpenIGTLink filters that produce OpenIGTLink message
* objects as output. This class defines the output-interface for
* OpenIGTLinkMessageFilters.
* \warning: if Update() is called on any output object, all IGTLMessage filters
* will generate new output data for all outputs, not just the one on which
* Update() was called.
*
*/
class MITKOPENIGTLINK_EXPORT IGTLMessageSource : public itk::ProcessObject
{
public:
mitkClassMacroItkParent(IGTLMessageSource, itk::ProcessObject);
/** @return Returns a human readable name of this source. There will be a
* default name, or you can set the name with the method SetName() if you
* want to change it.
*/
itkGetMacro(Name,std::string);
/** @brief Sets the human readable name of this source. There is also a
* default name, but you can use this method if you need to define it on your
* own.
*/
itkSetMacro(Name,std::string);
/** @return Returns a human readable type of this source. There will be a
* default type, or you can set the name with the method SetType(). You have
* to set this parameter otherwise it will not be found by the message
* provider.
*/
itkGetMacro(Type,std::string);
- /** @return Returns a human readable type of this source. There will be a
+ /** @brief Sets the human readable type of this source. There will be a
* default type, or you can set the name with the method SetType(). You have
* to set this parameter otherwise it will not be found by the message
* provider.
*/
itkSetMacro(Type,std::string);
/**
*\brief return the output (output with id 0) of the filter
*/
IGTLMessage* GetOutput(void);
/**
*\brief return the output with id idx of the filter
*/
IGTLMessage* GetOutput(DataObjectPointerArraySizeType idx);
/**
*\brief return the output with name messageName of the filter
*/
IGTLMessage* GetOutput(const std::string& messageName);
/**
*\brief return the index of the output with name messageName, -1 if no output
* with that name was found
*
* \warning if a subclass has outputs that have different data type than
* igtl::MessageBase, they have to overwrite this method
*/
DataObjectPointerArraySizeType GetOutputIndex(std::string messageName);
/**
*\brief Registers this object as a Microservice, making it available to every
* module and/or plugin. To unregister, call UnregisterMicroservice().
*/
virtual void RegisterAsMicroservice();
/**
*\brief Registers this object as a Microservice, making it available to every
* module and/or plugin.
*/
virtual void UnRegisterMicroservice();
/**
*\brief Returns the id that this device is registered with. The id will only
* be valid, if the IGTLMessageSource has been registered using
* RegisterAsMicroservice().
*/
std::string GetMicroserviceID();
/**
*\brief These Constants are used in conjunction with Microservices
*/
static const std::string US_INTERFACE_NAME;
static const std::string US_PROPKEY_DEVICENAME;
static const std::string US_PROPKEY_DEVICETYPE;
static const std::string US_PROPKEY_ID;
static const std::string US_PROPKEY_ISACTIVE; //NOT IMPLEMENTED YET!
/**
*\brief Graft the specified DataObject onto this ProcessObject's output.
*
* See itk::ImageSource::GraftNthOutput for details
*/
virtual void GraftNthOutput(unsigned int idx, itk::DataObject *graft);
/**
* \brief Graft the specified DataObject onto this ProcessObject's output.
*
* See itk::ImageSource::Graft Output for details
*/
virtual void GraftOutput(itk::DataObject *graft);
/**
* Allocates a new output object and returns it. Currently the
* index idx is not evaluated.
* @param idx the index of the output for which an object should be created
* @returns the new object
*/
itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ) override;
/**
* This is a default implementation to make sure we have something.
* Once all the subclasses of ProcessObject provide an appopriate
* MakeOutput(), then ProcessObject::MakeOutput() can be made pure
* virtual.
*/
itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name) override;
/**
* \brief Set all filter parameters as the PropertyList p
*
* This method allows to set all parameters of a filter with one
* method call. For the names of the parameters, take a look at
* the GetParameters method of the filter
* This method has to be overwritten by each MITK-IGT filter.
*/
virtual void SetParameters(const mitk::PropertyList*){};
/**
* \brief Get all filter parameters as a PropertyList
*
* This method allows to get all parameters of a filter with one
* method call. The returned PropertyList must be assigned to a
* SmartPointer immediately, or else it will get destroyed.
* Every filter must overwrite this method to create a filter-specific
* PropertyList. Note that property names must be unique over all
* MITK-IGT filters. Therefore each filter should use its name as a prefix
* for each property name.
* Secondly, each filter should list the property names and data types
* in the method documentation.
*/
virtual mitk::PropertyList::ConstPointer GetParameters() const;
/**
*\brief Sets the fps used for streaming this source
*/
void SetFPS(unsigned int fps);
/**
*\brief Gets the fps used for streaming this source
*/
unsigned int GetFPS();
protected:
IGTLMessageSource();
~IGTLMessageSource() override;
std::string m_Name;
std::string m_Type;
/** mutex to control access to m_StreamingFPS */
std::mutex m_StreamingFPSMutex;
/** The frames per second used for streaming */
unsigned int m_StreamingFPS;
us::ServiceRegistration<Self> m_ServiceRegistration;
};
} // namespace mitk
// This is the microservice declaration. Do not meddle!
MITK_DECLARE_SERVICE_INTERFACE(mitk::IGTLMessageSource, "org.mitk.services.IGTLMessageSource")
#endif
diff --git a/Modules/Pharmacokinetics/include/mitkConvertToConcentrationTurboFlashFunctor.h b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationTurboFlashFunctor.h
index 7d2015d1f7..7b990088f9 100644
--- a/Modules/Pharmacokinetics/include/mitkConvertToConcentrationTurboFlashFunctor.h
+++ b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationTurboFlashFunctor.h
@@ -1,67 +1,69 @@
/*============================================================================
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 mitkConvertToConcentrationTurboFlashFunctor_h
#define mitkConvertToConcentrationTurboFlashFunctor_h
#include "MitkPharmacokineticsExports.h"
namespace mitk {
template <class TInputPixel1, class TInputPixel2, class TOutputpixel>
class MITKPHARMACOKINETICS_EXPORT ConvertToConcentrationTurboFlashFunctor
{
+ private:
+ double m_Trec;
+ double m_alpha;
+ double m_T10;
+
public:
ConvertToConcentrationTurboFlashFunctor() : m_Trec(0), m_alpha(0), m_T10(0) {};
~ConvertToConcentrationTurboFlashFunctor() {};
void initialize(double relaxationtime, double relaxivity, double recoverytime)
{
- m_Trec = relaxationtime;
+ m_Trec = recoverytime;
m_alpha = relaxivity;
- m_T10 = recoverytime;
+ m_T10 = relaxationtime;
}
bool operator!=( const ConvertToConcentrationTurboFlashFunctor & other)const
{
return !(*this == other);
}
bool operator==( const ConvertToConcentrationTurboFlashFunctor & other) const
{
return (this->m_Trec == other.m_Trec) && (this->m_alpha == other.m_alpha) && (this->m_T10 == other.m_T10);
}
inline TOutputpixel operator()( const TInputPixel1 & value, const TInputPixel2 & baseline)
{
TOutputpixel concentration(0);
//Only for TurboFLASH sequencen
if (baseline != 0 && ((double)value/baseline - exp(m_Trec/m_T10) * ((double)value/baseline - 1)) > 0 )
{
concentration = -1 / (m_Trec * m_alpha) * log((double)value/baseline - exp(m_Trec/m_T10) * ((double)value/baseline - 1));
}
return concentration;
}
- private:
- double m_Trec;
- double m_alpha;
- double m_T10;
+
};
}
#endif
diff --git a/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModel.h b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModel.h
index 3a56cc2536..818cc01427 100644
--- a/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModel.h
+++ b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModel.h
@@ -1,131 +1,131 @@
/*============================================================================
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 mitkDescriptivePharmacokineticBrixModel_h
#define mitkDescriptivePharmacokineticBrixModel_h
#include <iostream>
#include "mitkModelBase.h"
#include "MitkPharmacokineticsExports.h"
namespace mitk
{
class MITKPHARMACOKINETICS_EXPORT DescriptivePharmacokineticBrixModel : public ModelBase
{
public:
typedef DescriptivePharmacokineticBrixModel Self;
typedef ModelBase Superclass;
typedef itk::SmartPointer< Self > Pointer;
typedef itk::SmartPointer< const Self > ConstPointer;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(DescriptivePharmacokineticBrixModel, ModelBase);
static const std::string MODEL_DISPLAY_NAME;
static const std::string NAME_PARAMETER_A;
static const std::string NAME_PARAMETER_kep;
static const std::string NAME_PARAMETER_kel;
static const std::string NAME_PARAMETER_tlag;
static const std::string NAME_STATIC_PARAMETER_Tau;
static const std::string NAME_STATIC_PARAMETER_S0;
static const std::string UNIT_PARAMETER_A;
static const std::string UNIT_PARAMETER_kep;
static const std::string UNIT_PARAMETER_kel;
static const std::string UNIT_PARAMETER_tlag;
static const std::string UNIT_STATIC_PARAMETER_Tau;
static const std::string UNIT_STATIC_PARAMETER_S0;
static const unsigned int POSITION_PARAMETER_A;
static const unsigned int POSITION_PARAMETER_kep;
static const unsigned int POSITION_PARAMETER_kel;
//tlag in minutes
static const unsigned int POSITION_PARAMETER_tlag;
static const unsigned int NUMBER_OF_PARAMETERS;
itkSetMacro(Tau, double);
itkGetConstReferenceMacro(Tau, double);
itkSetMacro(S0, double);
itkGetConstReferenceMacro(S0, double);
std::string GetModelDisplayName() const override;
std::string GetModelType() const override;
std::string GetXAxisName() const override;
std::string GetXAxisUnit() const override;
std::string GetYAxisName() const override;
std::string GetYAxisUnit() const override;
ParameterNamesType GetParameterNames() const override;
ParametersSizeType GetNumberOfParameters() const override;
ParamterUnitMapType GetParameterUnits() const override;
ParameterNamesType GetStaticParameterNames() const override;
ParametersSizeType GetNumberOfStaticParameters() const override;
ParamterUnitMapType GetStaticParameterUnits() const override;
protected:
DescriptivePharmacokineticBrixModel();
~DescriptivePharmacokineticBrixModel() override;
/**
* Actual implementation of the clone method. This method should be reimplemeted
* in subclasses to clone the extra required parameters.
*/
itk::LightObject::Pointer InternalClone() const override;
ModelResultType ComputeModelfunction(const ParametersType& parameters) const override;
void SetStaticParameter(const ParameterNameType& name,
- const StaticParameterValuesType& values) override;
+ const StaticParameterValuesType& values) override;
+
StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const
override;
-
void PrintSelf(std::ostream& os, ::itk::Indent indent) const override;
private:
/**injection time Tau in minutes [min]*/
double m_Tau;
/**Value of the first time step, thus base value to scale the signal.
* Default is 1.*/
double m_S0;
//No copy constructor allowed
DescriptivePharmacokineticBrixModel(const Self& source);
void operator=(const Self&); //purposely not implemented
};
}
#endif
diff --git a/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h
index 71758e63b5..bdfc6a7cff 100644
--- a/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h
+++ b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h
@@ -1,123 +1,125 @@
/*============================================================================
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 mitkThreeStepLinearModel_h
#define mitkThreeStepLinearModel_h
#include "mitkModelBase.h"
#include "MitkPharmacokineticsExports.h"
namespace mitk
{
class MITKPHARMACOKINETICS_EXPORT ThreeStepLinearModel : public mitk::ModelBase
{
public:
typedef ThreeStepLinearModel Self;
typedef mitk::ModelBase Superclass;
typedef itk::SmartPointer< Self > Pointer;
typedef itk::SmartPointer< const Self > ConstPointer;
typedef Superclass::ParameterNameType ParameterNameType;
typedef Superclass::ParametersSizeType ParametersSizeType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(ThreeStepLinearModel, ModelBase);
static const std::string MODEL_DISPLAY_NAME;
- static const std::string NAME_PARAMETER_S0;
+ static const std::string NAME_PARAMETER_s0;
static const std::string NAME_PARAMETER_t1;
static const std::string NAME_PARAMETER_t2;
static const std::string NAME_PARAMETER_a1;
static const std::string NAME_PARAMETER_a2;
static const std::string NAME_PARAMETER_b1;
static const std::string NAME_PARAMETER_b2;
- static const std::string UNIT_PARAMETER_S0;
+ static const std::string UNIT_PARAMETER_s0;
static const std::string UNIT_PARAMETER_t1;
static const std::string UNIT_PARAMETER_t2;
static const std::string UNIT_PARAMETER_a1;
static const std::string UNIT_PARAMETER_a2;
static const std::string UNIT_PARAMETER_b1;
static const std::string UNIT_PARAMETER_b2;
- static const unsigned int POSITION_PARAMETER_S0;
+ static const unsigned int POSITION_PARAMETER_s0;
static const unsigned int POSITION_PARAMETER_t1;
static const unsigned int POSITION_PARAMETER_t2;
static const unsigned int POSITION_PARAMETER_a1;
static const unsigned int POSITION_PARAMETER_a2;
static const unsigned int POSITION_PARAMETER_b1;
static const unsigned int POSITION_PARAMETER_b2;
static const unsigned int NUMBER_OF_PARAMETERS;
std::string GetModelDisplayName() const override;
std::string GetModelType() const override;
FunctionStringType GetFunctionString() const override;
std::string GetXName() const override;
ParameterNamesType GetParameterNames() const override;
ParametersSizeType GetNumberOfParameters() const override;
ParamterUnitMapType GetParameterUnits() const override;
ParameterNamesType GetStaticParameterNames() const override;
ParametersSizeType GetNumberOfStaticParameters() const override;
ParameterNamesType GetDerivedParameterNames() const override;
ParametersSizeType GetNumberOfDerivedParameters() const override;
ParamterUnitMapType GetDerivedParameterUnits() const override;
protected:
ThreeStepLinearModel() {};
~ThreeStepLinearModel() override{};
/**
* Actual implementation of the clone method. This method should be reimplemeted
* in subclasses to clone the extra required parameters.
*/
itk::LightObject::Pointer InternalClone() const override;
ModelResultType ComputeModelfunction(const ParametersType& parameters) const override;
DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType&
parameters) const override;
void SetStaticParameter(const ParameterNameType& name,
const StaticParameterValuesType& values) override;
StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const override;
+ static double ComputeSignalFromParameters(double x, double s0, double t1, double t2, double a1, double a2, double b1, double b2);
+
private:
//No copy constructor allowed
ThreeStepLinearModel(const Self& source);
void operator=(const Self&); //purposely not implemented
};
}
#endif
diff --git a/Modules/Pharmacokinetics/include/mitkTwoStepLinearModel.h b/Modules/Pharmacokinetics/include/mitkTwoStepLinearModel.h
index 2bda168be5..92b03e5903 100644
--- a/Modules/Pharmacokinetics/include/mitkTwoStepLinearModel.h
+++ b/Modules/Pharmacokinetics/include/mitkTwoStepLinearModel.h
@@ -1,105 +1,106 @@
/*============================================================================
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 mitkTwoStepLinearModel_h
#define mitkTwoStepLinearModel_h
#include "mitkModelBase.h"
#include "MitkPharmacokineticsExports.h"
namespace mitk
{
class MITKPHARMACOKINETICS_EXPORT TwoStepLinearModel : public mitk::ModelBase
{
public:
typedef TwoStepLinearModel Self;
typedef mitk::ModelBase Superclass;
typedef itk::SmartPointer< Self > Pointer;
typedef itk::SmartPointer< const Self > ConstPointer;
typedef Superclass::ParameterNameType ParameterNameType;
typedef Superclass::ParametersSizeType ParametersSizeType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(TwoStepLinearModel, ModelBase)
static const std::string MODELL_NAME;
static const std::string NAME_PARAMETER_y1;
static const std::string NAME_PARAMETER_t;
static const std::string NAME_PARAMETER_a1;
static const std::string NAME_PARAMETER_a2;
static const unsigned int POSITION_PARAMETER_y1;
static const unsigned int POSITION_PARAMETER_t;
static const unsigned int POSITION_PARAMETER_a1;
static const unsigned int POSITION_PARAMETER_a2;
static const unsigned int NUMBER_OF_PARAMETERS;
virtual std::string GetModelDisplayName() const override;
virtual std::string GetModelType() const override;
virtual FunctionStringType GetFunctionString() const override;
virtual std::string GetXName() const override;
virtual ParameterNamesType GetParameterNames() const override;
virtual ParametersSizeType GetNumberOfParameters() const override;
virtual ParameterNamesType GetStaticParameterNames() const override;
virtual ParametersSizeType GetNumberOfStaticParameters() const override;
virtual ParameterNamesType GetDerivedParameterNames() const override;
virtual ParametersSizeType GetNumberOfDerivedParameters() const override;
protected:
TwoStepLinearModel() {};
virtual ~TwoStepLinearModel(){};
/**
* Actual implementation of the clone method. This method should be reimplemeted
* in subclasses to clone the extra required parameters.
*/
virtual itk::LightObject::Pointer InternalClone() const;
virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const;
virtual DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType&
parameters) const;
virtual void SetStaticParameter(const ParameterNameType& name,
const StaticParameterValuesType& values);
virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const;
+ static double ComputeSignalFromParameters(double x, double t, double a1, double a2, double b1, double b2);
+
private:
//No copy constructor allowed
TwoStepLinearModel(const Self& source);
void operator=(const Self&); //purposely not implemented
-
};
}
#endif
diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp
index b6bea643ef..45958b3029 100644
--- a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp
+++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp
@@ -1,50 +1,48 @@
/*============================================================================
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 "mitkAreaUnderFirstMomentDescriptionParameter.h"
const std::string mitk::AreaUnderFirstMomentDescriptionParameter::PARAMETER_NAME = "AreaUnderFirstMoment";
mitk::AreaUnderFirstMomentDescriptionParameter::AreaUnderFirstMomentDescriptionParameter()
{
}
mitk::AreaUnderFirstMomentDescriptionParameter::~AreaUnderFirstMomentDescriptionParameter()
{
}
mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::AreaUnderFirstMomentDescriptionParameter::GetDescriptionParameterName() const
{
DescriptionParameterNamesType result = { PARAMETER_NAME };
return result;
}
mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::AreaUnderFirstMomentDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const
{
DescriptionParameterResultsType results;
CurveDescriptionParameterResultType aumc = 0;
auto steps = grid.GetSize();
for (CurveGridType::size_type i = 0; i < steps - 1; ++i)
{
double deltaX = grid(i + 1) - grid(i);
double deltaY = curve(i + 1)*grid(i + 1) - curve(i)*grid(i);
double Yi = curve(i)*grid(i);
- double intI = 1 / 2 * deltaX * deltaY + Yi * deltaX;
-
+ double intI = 0.5 * deltaX * deltaY + Yi * deltaX;
aumc += std::abs(intI);
-
}
results.push_back(aumc);
return results;
}
diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp
index e7e1a40351..556b67ce7f 100644
--- a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp
+++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp
@@ -1,51 +1,48 @@
/*============================================================================
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 "mitkAreaUnderTheCurveDescriptionParameter.h"
const std::string mitk::AreaUnderTheCurveDescriptionParameter::PARAMETER_NAME = "AreaUnderCurve";
mitk::AreaUnderTheCurveDescriptionParameter::AreaUnderTheCurveDescriptionParameter()
{
}
mitk::AreaUnderTheCurveDescriptionParameter::~AreaUnderTheCurveDescriptionParameter()
{
}
mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::AreaUnderTheCurveDescriptionParameter::GetDescriptionParameterName() const
{
DescriptionParameterNamesType result = { PARAMETER_NAME };
return result;
}
mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::AreaUnderTheCurveDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const
{
DescriptionParameterResultsType results;
CurveDescriptionParameterResultType auc = 0;
auto steps = grid.GetSize();
for (CurveGridType::size_type i = 0; i < steps - 1; ++i)
{
double deltaX = grid(i + 1) - grid(i);
double deltaY = curve(i + 1) - curve(i);
double Yi = curve(i);
-
- double intI = 1 / 2 * deltaX * deltaY + Yi * deltaX;
-
+ double intI = 0.5 * deltaX * deltaY + Yi * deltaX;
auc += std::abs(intI);
-
}
results.push_back(auc);
return results;
}
diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp
index d1edcc2092..4d29bc8b0b 100644
--- a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp
+++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp
@@ -1,63 +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 "mitkMeanResidenceTimeDescriptionParameter.h"
const std::string mitk::MeanResidenceTimeDescriptionParameter::PARAMETER_NAME = "MeanResidenceTime";
mitk::MeanResidenceTimeDescriptionParameter::MeanResidenceTimeDescriptionParameter()
{
}
mitk::MeanResidenceTimeDescriptionParameter::~MeanResidenceTimeDescriptionParameter()
{
}
mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::MeanResidenceTimeDescriptionParameter::GetDescriptionParameterName() const
{
DescriptionParameterNamesType result = { PARAMETER_NAME };
return result;
}
mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::MeanResidenceTimeDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const
{
DescriptionParameterResultsType results;
CurveDescriptionParameterResultType aumc = 0;
CurveDescriptionParameterResultType auc = 0;
CurveDescriptionParameterResultType mrt = 0;
auto steps = grid.GetSize();
for (CurveGridType::size_type i = 0; i < steps - 1; ++i)
{
double deltaX = grid(i + 1) - grid(i);
double deltaY1 = curve(i + 1)*grid(i + 1) - curve(i)*grid(i);
double Y1 = curve(i)*grid(i);
- double intI1 = 1 / 2 * deltaX * deltaY1 + Y1 * deltaX;
+ double intI1 = 0.5 * deltaX * deltaY1 + Y1 * deltaX;
aumc += std::abs(intI1);
double deltaY2 = curve(i + 1) - curve(i);
double Y2 = curve(i);
- double intI2 = 1 / 2 * deltaX * deltaY2 + Y2 * deltaX;
+ double intI2 = 0.5 * deltaX * deltaY2 + Y2 * deltaX;
auc += std::abs(intI2);
}
if(auc != 0)
{
mrt = aumc/auc;
}
results.push_back(mrt);
return results;
}
diff --git a/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModel.cpp
index 345f5894a9..3c7483f464 100644
--- a/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModel.cpp
+++ b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModel.cpp
@@ -1,237 +1,275 @@
/*============================================================================
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 "mitkThreeStepLinearModel.h"
+#include <mitkIOUtil.h>
+
const std::string mitk::ThreeStepLinearModel::MODEL_DISPLAY_NAME = "Three Step Linear Model";
-const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_S0 = "Baseline";
+const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_s0 = "Baseline";
const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_t1 = "Time_point_1";
const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_t2 = "Time_point_2";
const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_a1 = "Slope_1";
const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_a2 = "Slope_2";
// Assuming that Model is calculated on Signal intensities I
-const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_S0 = "I";
+const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_s0 = "I";
const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_t1 = "s";
const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_t2 = "s";
const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_a1 = "I/s";
const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_a2 = "I/s";
-const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_S0 = 0;
+const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_s0 = 0;
const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_t1 = 1;
const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_t2 = 2;
const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_a1 = 3;
const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_a2 = 4;
const unsigned int mitk::ThreeStepLinearModel::NUMBER_OF_PARAMETERS = 5;
std::string mitk::ThreeStepLinearModel::GetModelDisplayName() const
{
return MODEL_DISPLAY_NAME;
};
std::string mitk::ThreeStepLinearModel::GetModelType() const
{
return "Generic";
};
mitk::ThreeStepLinearModel::FunctionStringType mitk::ThreeStepLinearModel::GetFunctionString() const
{
return "Baseline if t<Time_point_1; Slope_1*t+Y_intercept_1 if Time_point_1<=t<=Time_point_2; Slope_2*t+Y_intercept_2 if Time_point_2<t";
};
std::string mitk::ThreeStepLinearModel::GetXName() const
{
return "x";
};
mitk::ThreeStepLinearModel::ParameterNamesType
mitk::ThreeStepLinearModel::GetParameterNames() const
{
ParameterNamesType result;
- result.push_back(NAME_PARAMETER_S0);
+ result.push_back(NAME_PARAMETER_s0);
result.push_back(NAME_PARAMETER_t1);
result.push_back(NAME_PARAMETER_t2);
result.push_back(NAME_PARAMETER_a1);
result.push_back(NAME_PARAMETER_a2);
return result;
};
mitk::ThreeStepLinearModel::ParametersSizeType
mitk::ThreeStepLinearModel::GetNumberOfParameters() const
{
return NUMBER_OF_PARAMETERS;
};
mitk::ThreeStepLinearModel::ParamterUnitMapType
mitk::ThreeStepLinearModel::GetParameterUnits() const
{
ParamterUnitMapType result;
- result.insert(std::make_pair(NAME_PARAMETER_S0, UNIT_PARAMETER_S0));
+ result.insert(std::make_pair(NAME_PARAMETER_s0, UNIT_PARAMETER_s0));
result.insert(std::make_pair(NAME_PARAMETER_t1, UNIT_PARAMETER_t1));
result.insert(std::make_pair(NAME_PARAMETER_t2, UNIT_PARAMETER_t2));
result.insert(std::make_pair(NAME_PARAMETER_a1, UNIT_PARAMETER_a1));
result.insert(std::make_pair(NAME_PARAMETER_a2, UNIT_PARAMETER_a2));
return result;
};
mitk::ThreeStepLinearModel::ParameterNamesType
mitk::ThreeStepLinearModel::GetDerivedParameterNames() const
{
ParameterNamesType result;
result.push_back("AUC");
result.push_back("FinalTimePoint");
result.push_back("FinalUptake");
result.push_back("Smax");
- result.push_back("y-intercept2");
result.push_back("y-intercept1");
+ result.push_back("y-intercept2");
return result;
};
mitk::ThreeStepLinearModel::ParametersSizeType
mitk::ThreeStepLinearModel::GetNumberOfDerivedParameters() const
{
return 6;
};
+double mitk::ThreeStepLinearModel::ComputeSignalFromParameters(double x, double s0, double t1, double t2, double a1, double a2, double b1, double b2)
+{
+ double signal = 0.0;
+
+ if (x < t1)
+ {
+ signal = s0;
+ }
+ else if (x >= t1 && x <= t2)
+ {
+ signal = a1 * x + b1;
+ }
+ else
+ {
+ signal = a2 * x + b2;
+ }
+
+
+ return signal;
+};
+
mitk::ThreeStepLinearModel::ParamterUnitMapType mitk::ThreeStepLinearModel::GetDerivedParameterUnits() const
{
ParamterUnitMapType result;
result.insert(std::make_pair("AUC", "I*s"));
result.insert(std::make_pair("FinalTimePoint", "s"));
result.insert(std::make_pair("FinalUptake", "I"));
result.insert(std::make_pair("Smax", "I"));
result.insert(std::make_pair("y-intercept1", "I"));
result.insert(std::make_pair("y-intercept2", "I"));
return result;
};
mitk::ThreeStepLinearModel::ModelResultType
mitk::ThreeStepLinearModel::ComputeModelfunction(const ParametersType& parameters) const
{
//Model Parameters
- double S0 = (double) parameters[POSITION_PARAMETER_S0];
- double t1 = (double) parameters[POSITION_PARAMETER_t1] ;
- double t2 = (double) parameters[POSITION_PARAMETER_t2] ;
- double a1 = (double) parameters[POSITION_PARAMETER_a1] ;
- double a2 = (double) parameters[POSITION_PARAMETER_a2] ;
-
+ const double s0 = (double) parameters[POSITION_PARAMETER_s0];
+ const double t1 = (double) parameters[POSITION_PARAMETER_t1] ;
+ const double t2 = (double) parameters[POSITION_PARAMETER_t2] ;
+ const double a1 = (double) parameters[POSITION_PARAMETER_a1] ;
+ const double a2 = (double) parameters[POSITION_PARAMETER_a2] ;
- double b1 = S0-a1*t1 ;
- double b2 = (a1*t2+ b1) - (a2*t2);
+ double b1 = s0 - a1 * t1;
+ double b2 = (a1 * t2 + b1) - (a2 * t2);
ModelResultType signal(m_TimeGrid.GetSize());
TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end();
+
ModelResultType::iterator signalPos = signal.begin();
for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd; ++gridPos, ++signalPos)
{
- if((*gridPos) < t1)
- {
- *signalPos = S0;
- }
- else if ((*gridPos) >= t1 && (*gridPos) <= t2)
- {
- *signalPos = a1*(*gridPos)+b1;
- }
- else
- {
- *signalPos = a2*(*gridPos)+b2;
- }
+ *signalPos = ComputeSignalFromParameters(*gridPos, s0, t1, t2, a1, a2, b1, b2);
}
return signal;
};
mitk::ThreeStepLinearModel::ParameterNamesType mitk::ThreeStepLinearModel::GetStaticParameterNames() const
{
ParameterNamesType result;
return result;
}
mitk::ThreeStepLinearModel::ParametersSizeType mitk::ThreeStepLinearModel::GetNumberOfStaticParameters() const
{
return 0;
}
void mitk::ThreeStepLinearModel::SetStaticParameter(const ParameterNameType&,
const StaticParameterValuesType&)
{
//do nothing
};
mitk::ThreeStepLinearModel::StaticParameterValuesType mitk::ThreeStepLinearModel::GetStaticParameterValue(
const ParameterNameType&) const
{
StaticParameterValuesType result;
//do nothing
return result;
};
mitk::ModelBase::DerivedParameterMapType mitk::ThreeStepLinearModel::ComputeDerivedParameters(
const mitk::ModelBase::ParametersType& parameters) const
{
- double S0 = (double) parameters[POSITION_PARAMETER_S0];
- double tau = (double) parameters[POSITION_PARAMETER_t1] ;
- double tmax = (double) parameters[POSITION_PARAMETER_t2] ;
- double s1 = (double) parameters[POSITION_PARAMETER_a1] ;
- double s2 = (double) parameters[POSITION_PARAMETER_a2] ;
+ const double s0 = (double) parameters[POSITION_PARAMETER_s0];
+ const double t1 = (double) parameters[POSITION_PARAMETER_t1] ;
+ const double t2 = (double) parameters[POSITION_PARAMETER_t2] ;
+ const double a1 = (double) parameters[POSITION_PARAMETER_a1] ;
+ const double a2 = (double) parameters[POSITION_PARAMETER_a2] ;
+
+ const double b1 = s0 - a1 * t1;
+ const double b2 = (a1 * t2 + b1) - (a2 * t2);
unsigned int timeSteps = m_TimeGrid.GetSize();
- double Taq = 0;
- Taq = m_TimeGrid.GetElement(timeSteps-1);
+ const double taq = (m_TimeGrid.empty() == false) ? (m_TimeGrid.GetElement(timeSteps - 1)) : ( mitkThrow() << "An exception occured because time grid is empty, method can't continue.");
+
+ const double sfin = a2 * taq + b2;
+
+ double smax = sfin;
+ if ((a1 >= 0) && (a2 >= 0))
+ smax = sfin;
+ else if ((a1 < 0) && (a2 < 0))
+ smax = s0;
+ else if ((a1 > 0) && (a2 < 0))
+ smax = (a1 * t2 + b1);
+ else
+ {
+ if (abs(a1 * (t2 - t1)) >= abs(a2 * (taq - t2)))
+ smax = s0;
+ else smax = sfin;
+ }
+
+ double auc = 0.0;
+ TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end();
+
+ for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd - 1; ++gridPos)
+ {
+ double currentGridPos = *gridPos;
+ double nextGridPos = *(++gridPos);
+ double deltaX = nextGridPos - currentGridPos;
+ double deltaY = ComputeSignalFromParameters(nextGridPos, s0, t1, t2, a1, a2, b1, b2) - ComputeSignalFromParameters(currentGridPos, s0, t1, t2, a1, a2, b1, b2);
+ double Yi = ComputeSignalFromParameters(currentGridPos, s0, t1, t2, a1, a2, b1, b2 );
+ double intI = 0.5 * deltaX * deltaY + Yi * deltaX;
+ auc += std::abs(intI);
+ --gridPos;
+ }
- double b1 = S0-s1*tau;
- double Smax = s1*tmax+b1;
- double b2 = Smax-s2*tmax;
- double AUC = s1/2*(tmax*tmax-tau*tau)
- +(b1-S0)*(tmax-tau)
- +s2/2*(Taq*Taq-tmax*tmax)
- +(b2-S0)*(Taq-tmax);
- double Sfin = s2*Taq+b2;
DerivedParameterMapType result;
- result.insert(std::make_pair("AUC", AUC));
- result.insert(std::make_pair("FinalTimePoint", Taq));
- result.insert(std::make_pair("FinalUptake", Sfin));
- result.insert(std::make_pair("Smax", Smax));
+ result.insert(std::make_pair("AUC", auc));
+ result.insert(std::make_pair("FinalTimePoint", taq));
+ result.insert(std::make_pair("FinalUptake", sfin));
+ result.insert(std::make_pair("Smax", smax));
result.insert(std::make_pair("y-intercept1", b1));
result.insert(std::make_pair("y-intercept2", b2));
+
return result;
};
itk::LightObject::Pointer mitk::ThreeStepLinearModel::InternalClone() const
{
ThreeStepLinearModel::Pointer newClone = ThreeStepLinearModel::New();
newClone->SetTimeGrid(this->m_TimeGrid);
return newClone.GetPointer();
};
diff --git a/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelParameterizer.cpp
index ec0226fbf4..6eb6bcf471 100644
--- a/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelParameterizer.cpp
+++ b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelParameterizer.cpp
@@ -1,29 +1,29 @@
/*============================================================================
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 "mitkThreeStepLinearModelParameterizer.h"
mitk::ThreeStepLinearModelParameterizer::ParametersType
mitk::ThreeStepLinearModelParameterizer::GetDefaultInitialParameterization() const
{
ParametersType initialParameters;
initialParameters.SetSize(5);
- initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_S0] = 0.0;
- initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_t1] = 50;
- initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_t2] = 100;
+ initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_s0] = 0.0;
+ initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_t1] = 50.0;
+ initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_t2] = 100.0;
initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_a1] = 1.0;
initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_a2] = -1.0;
return initialParameters;
};
diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoStepLinearModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoStepLinearModel.cpp
index 6a5b96262b..19191106fa 100644
--- a/Modules/Pharmacokinetics/src/Models/mitkTwoStepLinearModel.cpp
+++ b/Modules/Pharmacokinetics/src/Models/mitkTwoStepLinearModel.cpp
@@ -1,184 +1,209 @@
/*============================================================================
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 "mitkTwoStepLinearModel.h"
#include <mitkIOUtil.h>
const std::string mitk::TwoStepLinearModel::MODELL_NAME = "Two Step Linear Model";
const std::string mitk::TwoStepLinearModel::NAME_PARAMETER_y1 = "BaseValue";
const std::string mitk::TwoStepLinearModel::NAME_PARAMETER_a1 = "Slope_1";
const std::string mitk::TwoStepLinearModel::NAME_PARAMETER_t = "Change_Point";
const std::string mitk::TwoStepLinearModel::NAME_PARAMETER_a2 = "Slope_2";
const unsigned int mitk::TwoStepLinearModel::POSITION_PARAMETER_y1 = 0;
const unsigned int mitk::TwoStepLinearModel::POSITION_PARAMETER_t = 1;
const unsigned int mitk::TwoStepLinearModel::POSITION_PARAMETER_a1 = 2;
const unsigned int mitk::TwoStepLinearModel::POSITION_PARAMETER_a2 = 3;
const unsigned int mitk::TwoStepLinearModel::NUMBER_OF_PARAMETERS = 4;
std::string mitk::TwoStepLinearModel::GetModelDisplayName() const
{
return MODELL_NAME;
};
std::string mitk::TwoStepLinearModel::GetModelType() const
{
return "Generic";
};
mitk::TwoStepLinearModel::FunctionStringType mitk::TwoStepLinearModel::GetFunctionString() const
{
return "Slope_1*t+Y_intercept_1 if t<Change_Point; Slope_2*t+Y_intercept_2 if ChangePoint<=t";
};
std::string mitk::TwoStepLinearModel::GetXName() const
{
return "x";
};
mitk::TwoStepLinearModel::ParameterNamesType
mitk::TwoStepLinearModel::GetParameterNames() const
{
ParameterNamesType result;
result.push_back(NAME_PARAMETER_y1);
result.push_back(NAME_PARAMETER_t);
result.push_back(NAME_PARAMETER_a1);
result.push_back(NAME_PARAMETER_a2);
return result;
};
mitk::TwoStepLinearModel::ParametersSizeType
mitk::TwoStepLinearModel::GetNumberOfParameters() const
{
return NUMBER_OF_PARAMETERS;
};
mitk::TwoStepLinearModel::ParameterNamesType
mitk::TwoStepLinearModel::GetDerivedParameterNames() const
{
ParameterNamesType result;
result.push_back("AUC");
result.push_back("FinalUptake");
result.push_back("Smax");
result.push_back("y-intercept2");
return result;
};
mitk::TwoStepLinearModel::ParametersSizeType
mitk::TwoStepLinearModel::GetNumberOfDerivedParameters() const
{
return 4;
};
+double mitk::TwoStepLinearModel::ComputeSignalFromParameters(double x, double t, double a1, double a2, double b1, double b2)
+{
+ return (x < t) ? (a1 * x + b1) : (a2 * x + b2);
+};
+
+
+
+
mitk::TwoStepLinearModel::ModelResultType
mitk::TwoStepLinearModel::ComputeModelfunction(const ParametersType& parameters) const
{
//Model Parameters
const auto t = parameters[POSITION_PARAMETER_t] ;
const auto a1 = parameters[POSITION_PARAMETER_a1] ;
const auto a2 = parameters[POSITION_PARAMETER_a2] ;
const auto b1 = parameters[POSITION_PARAMETER_y1] ;
- const auto b2 = (a1 - a2)*t + b1;
+
+ double b2 = (a1 - a2) * t + b1;
ModelResultType signal(m_TimeGrid.GetSize());
TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end();
+
ModelResultType::iterator signalPos = signal.begin();
for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd; ++gridPos, ++signalPos)
{
- if((*gridPos) < t)
- {
- *signalPos = a1*(*gridPos)+b1;
- }
- else
- {
- *signalPos = a2*(*gridPos)+b2;
- }
+ *signalPos = ComputeSignalFromParameters(*gridPos, t, a1, a2, b1, b2);
}
return signal;
};
mitk::TwoStepLinearModel::ParameterNamesType mitk::TwoStepLinearModel::GetStaticParameterNames() const
{
ParameterNamesType result;
return result;
}
mitk::TwoStepLinearModel::ParametersSizeType mitk::TwoStepLinearModel::GetNumberOfStaticParameters() const
{
return 0;
}
void mitk::TwoStepLinearModel::SetStaticParameter(const ParameterNameType& /*name*/,
const StaticParameterValuesType& /*values*/)
{
//do nothing
};
mitk::TwoStepLinearModel::StaticParameterValuesType mitk::TwoStepLinearModel::GetStaticParameterValue(
const ParameterNameType& /*name*/) const
{
StaticParameterValuesType result;
//do nothing
return result;
};
mitk::ModelBase::DerivedParameterMapType mitk::TwoStepLinearModel::ComputeDerivedParameters(
const mitk::ModelBase::ParametersType& parameters) const
{
const auto t = parameters[POSITION_PARAMETER_t] ;
const auto a1 = parameters[POSITION_PARAMETER_a1] ;
const auto a2 = parameters[POSITION_PARAMETER_a2] ;
const auto b1 = parameters[POSITION_PARAMETER_y1] ;
const auto b2 = (a1 - a2) * t + b1;
unsigned int timeSteps = m_TimeGrid.GetSize();
-
const double taq = (m_TimeGrid.empty() == false) ? (m_TimeGrid.GetElement(timeSteps - 1)) : (mitkThrow() << "An exception occured because time grid is empty, method can't continue.");
const double sfin = a2 * taq + b2;
- const double smax = (a2 <= 0) ? (a1 * t + b1) : (sfin);
-
- const double auc = a1/2*(t*t)+b1*t
- +a2/2*(taq*taq-t*t)+b2*(taq-t);
+ double smax = sfin;
+ if ((a1 >= 0) && (a2 >= 0))
+ smax = sfin;
+ else if ((a1 < 0) && (a2 < 0))
+ smax = b1;
+ else if ((a1 > 0) && (a2 < 0))
+ smax = (a1 * t + b1);
+ else
+ {
+ if (abs(a1 * t) >= abs(a2 * (taq - t)))
+ smax = b1;
+ else smax = sfin;
+ }
+
+ double auc = 0.0;
+ TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end();
+ for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd -1; ++gridPos)
+ {
+ double currentGridPos = *gridPos;
+ double nextGridPos = *(++gridPos);
+ double deltaX = nextGridPos - currentGridPos;
+ double deltaY = ComputeSignalFromParameters(nextGridPos, t, a1, a2, b1, b2) - ComputeSignalFromParameters(currentGridPos, t, a1, a2, b1, b2);
+ double Yi = ComputeSignalFromParameters(currentGridPos, t, a1, a2, b1, b2);
+ double intI = 0.5 * deltaX * deltaY + Yi * deltaX;
+ auc += std::abs(intI);
+ --gridPos;
+ }
DerivedParameterMapType result;
result.insert(std::make_pair("AUC", auc));
result.insert(std::make_pair("FinalUptake", sfin));
result.insert(std::make_pair("Smax", smax));
result.insert(std::make_pair("y-intercept2", b2));
return result;
};
itk::LightObject::Pointer mitk::TwoStepLinearModel::InternalClone() const
{
TwoStepLinearModel::Pointer newClone = TwoStepLinearModel::New();
newClone->SetTimeGrid(this->m_TimeGrid);
return newClone.GetPointer();
};
diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoStepLinearModelTest.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoStepLinearModelTest.cpp
new file mode 100644
index 0000000000..de8b2e160f
--- /dev/null
+++ b/Modules/Pharmacokinetics/src/Models/mitkTwoStepLinearModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+ //Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkTwoStepLinearModel.h"
+
+
+ class mitkTwoStepLinearModelTestSuite : public mitk::mitkModelTestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkTwoStepLinearModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::TwoStepLinearModel::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoStepLinearModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoStepLinearModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::TwoStepLinearModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkTwoStepLinearModel)
diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModel.cpp
index 0e5ef41ce8..c7c36c53b5 100644
--- a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModel.cpp
+++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModel.cpp
@@ -1,156 +1,155 @@
/*============================================================================
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 "mitkTwoTissueCompartmentFDGModel.h"
#include "mitkConvolutionHelper.h"
#include <fstream>
const std::string mitk::TwoTissueCompartmentFDGModel::MODEL_DISPLAY_NAME = "Two Tissue Compartment Model for FDG (Sokoloff Model)";
const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_K1 = "K1";
const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_k2 = "k2";
const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_k3 = "k3";
const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_VB = "V_B";
const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_K1 = "1/min";
const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_k2 = "1/min";
const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_k3 = "1/min";
const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_VB = "ml/ml";
const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_K1 = 0;
const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_k2 = 1;
const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_k3 = 2;
const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_VB = 3;
const unsigned int mitk::TwoTissueCompartmentFDGModel::NUMBER_OF_PARAMETERS = 4;
std::string mitk::TwoTissueCompartmentFDGModel::GetModelDisplayName() const
{
return MODEL_DISPLAY_NAME;
};
std::string mitk::TwoTissueCompartmentFDGModel::GetModelType() const
{
return "Dynamic.PET";
};
mitk::TwoTissueCompartmentFDGModel::TwoTissueCompartmentFDGModel()
{
}
mitk::TwoTissueCompartmentFDGModel::~TwoTissueCompartmentFDGModel()
{
}
mitk::TwoTissueCompartmentFDGModel::ParameterNamesType
mitk::TwoTissueCompartmentFDGModel::GetParameterNames() const
{
ParameterNamesType result;
result.push_back(NAME_PARAMETER_K1);
result.push_back(NAME_PARAMETER_k2);
result.push_back(NAME_PARAMETER_k3);
result.push_back(NAME_PARAMETER_VB);
return result;
}
mitk::TwoTissueCompartmentFDGModel::ParametersSizeType
mitk::TwoTissueCompartmentFDGModel::GetNumberOfParameters() const
{
return NUMBER_OF_PARAMETERS;
}
mitk::TwoTissueCompartmentFDGModel::ParamterUnitMapType
mitk::TwoTissueCompartmentFDGModel::GetParameterUnits() const
{
ParamterUnitMapType result;
result.insert(std::make_pair(NAME_PARAMETER_K1, UNIT_PARAMETER_K1));
result.insert(std::make_pair(NAME_PARAMETER_k2, UNIT_PARAMETER_k2));
result.insert(std::make_pair(NAME_PARAMETER_k3, UNIT_PARAMETER_k3));
result.insert(std::make_pair(NAME_PARAMETER_VB, UNIT_PARAMETER_VB));
return result;
};
mitk::TwoTissueCompartmentFDGModel::ModelResultType
mitk::TwoTissueCompartmentFDGModel::ComputeModelfunction(const ParametersType& parameters) const
{
if (this->m_TimeGrid.GetSize() == 0)
{
itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal");
}
AterialInputFunctionType aterialInputFunction;
aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid);
unsigned int timeSteps = this->m_TimeGrid.GetSize();
//Model Parameters
double k1 = (double)parameters[POSITION_PARAMETER_K1] / 60.0;
double k2 = (double)parameters[POSITION_PARAMETER_k2] / 60.0;
double k3 = (double)parameters[POSITION_PARAMETER_k3] / 60.0;
double VB = parameters[POSITION_PARAMETER_VB];
double lambda = k2+k3;
- //double lambda2 = -alpha2;
+
mitk::ModelBase::ModelResultType exp = mitk::convoluteAIFWithExponential(this->m_TimeGrid,
aterialInputFunction, lambda);
mitk::ModelBase::ModelResultType CA = mitk::convoluteAIFWithConstant(this->m_TimeGrid, aterialInputFunction, k3);
-
//Signal that will be returned by ComputeModelFunction
mitk::ModelBase::ModelResultType signal(timeSteps);
signal.fill(0.0);
mitk::ModelBase::ModelResultType::const_iterator expPos = exp.begin();
mitk::ModelBase::ModelResultType::const_iterator CAPos = CA.begin();
AterialInputFunctionType::const_iterator aifPos = aterialInputFunction.begin();
for (mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin();
signalPos != signal.end(); ++expPos, ++signalPos, ++aifPos)
{
double Ci = k1 * k2 /lambda *(*expPos) + k1*k3/lambda*(*CAPos);
*signalPos = VB * (*aifPos) + (1 - VB) * Ci;
}
return signal;
}
itk::LightObject::Pointer mitk::TwoTissueCompartmentFDGModel::InternalClone() const
{
TwoTissueCompartmentFDGModel::Pointer newClone = TwoTissueCompartmentFDGModel::New();
newClone->SetTimeGrid(this->m_TimeGrid);
return newClone.GetPointer();
}
void mitk::TwoTissueCompartmentFDGModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
}
diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModel.cpp
index b7bffd8965..a00a006665 100644
--- a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModel.cpp
+++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModel.cpp
@@ -1,172 +1,170 @@
/*============================================================================
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 "mitkTwoTissueCompartmentModel.h"
#include "mitkConvolutionHelper.h"
#include <fstream>
const std::string mitk::TwoTissueCompartmentModel::MODEL_DISPLAY_NAME = "Two Tissue Compartment Model";
const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_K1 = "K1";
const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k2 = "k2";
const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k3 = "k3";
const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k4 = "k4";
const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_VB = "V_B";
const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_K1 = "1/min";
const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_k2 = "1/min";
const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_k3 = "1/min";
const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_k4 = "1/min";
const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_VB = "ml/ml";
const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_K1 = 0;
const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k2 = 1;
const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k3 = 2;
const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k4 = 3;
const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_VB = 4;
const unsigned int mitk::TwoTissueCompartmentModel::NUMBER_OF_PARAMETERS = 5;
inline double square(double a)
{
return a * a;
}
std::string mitk::TwoTissueCompartmentModel::GetModelDisplayName() const
{
return MODEL_DISPLAY_NAME;
};
std::string mitk::TwoTissueCompartmentModel::GetModelType() const
{
return "Dynamic.PET";
};
mitk::TwoTissueCompartmentModel::TwoTissueCompartmentModel()
{
}
mitk::TwoTissueCompartmentModel::~TwoTissueCompartmentModel()
{
}
mitk::TwoTissueCompartmentModel::ParameterNamesType
mitk::TwoTissueCompartmentModel::GetParameterNames() const
{
ParameterNamesType result;
result.push_back(NAME_PARAMETER_K1);
result.push_back(NAME_PARAMETER_k2);
result.push_back(NAME_PARAMETER_k3);
result.push_back(NAME_PARAMETER_k4);
result.push_back(NAME_PARAMETER_VB);
return result;
}
mitk::TwoTissueCompartmentModel::ParametersSizeType
mitk::TwoTissueCompartmentModel::GetNumberOfParameters() const
{
return NUMBER_OF_PARAMETERS;
}
mitk::TwoTissueCompartmentModel::ParamterUnitMapType
mitk::TwoTissueCompartmentModel::GetParameterUnits() const
{
ParamterUnitMapType result;
result.insert(std::make_pair(NAME_PARAMETER_K1, UNIT_PARAMETER_K1));
result.insert(std::make_pair(NAME_PARAMETER_k2, UNIT_PARAMETER_k2));
result.insert(std::make_pair(NAME_PARAMETER_k3, UNIT_PARAMETER_k3));
result.insert(std::make_pair(NAME_PARAMETER_k4, UNIT_PARAMETER_k4));
result.insert(std::make_pair(NAME_PARAMETER_VB, UNIT_PARAMETER_VB));
return result;
};
mitk::TwoTissueCompartmentModel::ModelResultType
mitk::TwoTissueCompartmentModel::ComputeModelfunction(const ParametersType& parameters) const
{
if (this->m_TimeGrid.GetSize() == 0)
{
itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal");
}
AterialInputFunctionType aterialInputFunction;
aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid);
unsigned int timeSteps = this->m_TimeGrid.GetSize();
//Model Parameters
double k1 = (double)parameters[POSITION_PARAMETER_K1] / 60.0;
double k2 = (double)parameters[POSITION_PARAMETER_k2] / 60.0;
double k3 = (double)parameters[POSITION_PARAMETER_k3] / 60.0;
double k4 = (double)parameters[POSITION_PARAMETER_k4] / 60.0;
double VB = parameters[POSITION_PARAMETER_VB];
double alpha1 = 0.5 * ((k2 + k3 + k4) - sqrt(square(k2 + k3 + k4) - 4 * k2 * k4));
double alpha2 = 0.5 * ((k2 + k3 + k4) + sqrt(square(k2 + k3 + k4) - 4 * k2 * k4));
- //double lambda1 = -alpha1;
- //double lambda2 = -alpha2;
mitk::ModelBase::ModelResultType exp1 = mitk::convoluteAIFWithExponential(this->m_TimeGrid,
aterialInputFunction, alpha1);
mitk::ModelBase::ModelResultType exp2 = mitk::convoluteAIFWithExponential(this->m_TimeGrid,
aterialInputFunction, alpha2);
//Signal that will be returned by ComputeModelFunction
mitk::ModelBase::ModelResultType signal(timeSteps);
signal.fill(0.0);
mitk::ModelBase::ModelResultType::const_iterator exp1Pos = exp1.begin();
mitk::ModelBase::ModelResultType::const_iterator exp2Pos = exp2.begin();
AterialInputFunctionType::const_iterator aifPos = aterialInputFunction.begin();
for (mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin();
signalPos != signal.end(); ++exp1Pos, ++exp2Pos, ++signalPos, ++aifPos)
{
double Ci = k1 / (alpha2 - alpha1) * ((k4 - alpha1 + k3) * (*exp1Pos) + (alpha2 - k4 - k3) *
(*exp2Pos));
*signalPos = VB * (*aifPos) + (1 - VB) * Ci;
}
return signal;
}
itk::LightObject::Pointer mitk::TwoTissueCompartmentModel::InternalClone() const
{
TwoTissueCompartmentModel::Pointer newClone = TwoTissueCompartmentModel::New();
newClone->SetTimeGrid(this->m_TimeGrid);
return newClone.GetPointer();
}
void mitk::TwoTissueCompartmentModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
}
diff --git a/Modules/Pharmacokinetics/test/ConvertToConcentrationTest.cpp b/Modules/Pharmacokinetics/test/ConvertToConcentrationTest.cpp
deleted file mode 100644
index 2b8d8ee05d..0000000000
--- a/Modules/Pharmacokinetics/test/ConvertToConcentrationTest.cpp
+++ /dev/null
@@ -1,138 +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 <iostream>
-#include "mitkTestingMacros.h"
-
-#include "itkImage.h"
-#include "itkImageRegionIterator.h"
-
-#include "itkBinaryFunctorImageFilter.h"
-
-#include "mitkConvertToConcentrationFunctor.h"
-
-
-int ConvertToConcentrationTest(int argc , char* argv[])
-{
- // always start with this!
- MITK_TEST_BEGIN("ConvertToConcentration");
-
- //Initialization Parameters
- double RelaxationTime = 1.2;
- double RecoveryTime = 0.125;
- double Relaxivity = 4.3;
-
-
-
- //Test1: Functor calculation
- mitk::ConvertToConcentrationFunctor<double,double,double> testFunctor;
- testFunctor.initialize(RelaxationTime, Relaxivity, RecoveryTime);
-
-
- double s0 = 197.0;
- double sCM = 278.0;
- MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.009,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 1");
- s0 = 157.0;
- sCM = 207.0;
- MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.0069,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 2");
- s0 = 195.0;
- sCM = 270.0;
- MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.0084,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 3");
- s0 = 177.0;
- sCM = 308.0;
- MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.0164,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 4");
-
- //Test2: Filter usage with Functor
-
- typedef itk::Image<double,3> ImageType;
- typedef mitk::ConvertToConcentrationFunctor <double, double, double> ConversionFunctorType;
- typedef itk::BinaryFunctorImageFilter<ImageType, ImageType, ImageType, ConversionFunctorType> FilterType;
-
- //Definition of testimages
- ImageType::Pointer image = ImageType::New();
- ImageType::Pointer BaselineImage = ImageType::New();
- ImageType::IndexType start;
- start[0] = 0; // first index on X
- start[1] = 0; // first index on Y
- start[2] = 0; // first index on Z
- ImageType::SizeType size;
- size[0] = 2; // size along X
- size[1] = 2; // size along Y
- size[2] = 2; // size along Z
- ImageType::RegionType region;
- region.SetSize( size );
- region.SetIndex( start );
- image->SetRegions( region );
- image->Allocate();
- BaselineImage->SetRegions( region );
- BaselineImage->Allocate();
- itk::ImageRegionIterator<ImageType> it = itk::ImageRegionIterator<ImageType>(image,image->GetLargestPossibleRegion());
- itk::ImageRegionIterator<ImageType> Bit = itk::ImageRegionIterator<ImageType>(BaselineImage,BaselineImage->GetLargestPossibleRegion());
- int count = 0;
- while (!it.IsAtEnd()&& !Bit.IsAtEnd())
- {
- Bit.Set(150);
- it.Set(count*50+150);
- ++it;
- ++Bit;
- ++count;
- }
- //Filterinitialization
- FilterType::Pointer ConversionFilter = FilterType::New();
- ConversionFilter->SetFunctor(testFunctor);
- ConversionFilter->SetInput1(image);
- ConversionFilter->SetInput2(BaselineImage);
-
- ConversionFilter->Update();
- ImageType::Pointer convertedImage = ImageType::New();
- convertedImage = ConversionFilter->GetOutput();
-
- MITK_TEST_EQUAL(image->GetImageDimension(),convertedImage->GetImageDimension(),"Check dimensions of result image");
-
- itk::Index<3> idx;
- idx[0]=0;
- idx[1]=0;
- idx[2]=0;
- MITK_TEST_EQUAL(0,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,0,0>");
- idx[0]=1;
- idx[1]=0;
- idx[2]=0;
- MITK_TEST_EQUAL(0.0072,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,0,0>");
- idx[0]=0;
- idx[1]=1;
- idx[2]=0;
- MITK_TEST_EQUAL(0.0147,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,1,0>");
- idx[0]=1;
- idx[1]=1;
- idx[2]=0;
- MITK_TEST_EQUAL(0.0225,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,1,0>");
- idx[0]=0;
- idx[1]=0;
- idx[2]=1;
- MITK_TEST_EQUAL(0.0307 ,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,0,1>");
- idx[0]=1;
- idx[1]=0;
- idx[2]=1;
- MITK_TEST_EQUAL(0.0392,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,0,1>");
- idx[0]=0;
- idx[1]=1;
- idx[2]=1;
- MITK_TEST_EQUAL(0.0480,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,1,1>");
- idx[0]=1;
- idx[1]=1;
- idx[2]=1;
- MITK_TEST_EQUAL(0.0574,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,1,1>");
-
-
-
- MITK_TEST_END()
-}
diff --git a/Modules/Pharmacokinetics/test/files.cmake b/Modules/Pharmacokinetics/test/files.cmake
index d6ce07a366..41a9258c17 100644
--- a/Modules/Pharmacokinetics/test/files.cmake
+++ b/Modules/Pharmacokinetics/test/files.cmake
@@ -1,7 +1,14 @@
SET(MODULE_TESTS
mitkDescriptivePharmacokineticBrixModelTest.cpp
mitkStandardToftsModelTest.cpp
- #ConvertToConcentrationTest.cpp
mitkTwoCompartmentExchangeModelTest.cpp
mitkExtendedToftsModelTest.cpp
+ mitkConvertSignalToConcentrationTest.cpp
+ mitkCurveDescriptiveParametersTest.cpp
+ mitkTwoStepLinearModelTest.cpp
+ mitkThreeStepLinearModelTest.cpp
+ mitkOneTissueCompartmentModelTest.cpp
+ mitkExtendedOneTissueCompartmentModelTest.cpp
+ mitkTwoTissueCompartmentModelTest.cpp
+ mitkTwoTissueCompartmentFDGModelTest.cpp
)
diff --git a/Modules/Pharmacokinetics/test/mitkConvertSignalToConcentrationTest.cpp b/Modules/Pharmacokinetics/test/mitkConvertSignalToConcentrationTest.cpp
new file mode 100644
index 0000000000..771d25e57b
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkConvertSignalToConcentrationTest.cpp
@@ -0,0 +1,217 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+// Testing
+#include "mitkTestingMacros.h"
+#include "mitkTestFixture.h"
+
+//MITK includes
+#include "mitkConcentrationCurveGenerator.h"
+#include "mitkTestDynamicImageGenerator.h"
+#include "mitkImagePixelReadAccessor.h"
+
+
+class mitkConvertSignalToConcentrationTestSuite : public mitk::TestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkConvertSignalToConcentrationTestSuite);
+ MITK_TEST(GetConvertedImageAbsoluteEnhancementTest);
+ MITK_TEST(GetConvertedImageAbsoluteEnhancementAveragedBaselineTest);
+ MITK_TEST(GetConvertedImageRelativeEnhancementTest);
+ MITK_TEST(GetConvertedImageturboFLASHTest);
+ MITK_TEST(GetConvertedImageVFATest);
+ MITK_TEST(GetConvertedImageT2Test);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::Image::Pointer m_dynamicImage;
+ mitk::Image::Pointer m_convertedImage;
+ mitk::ConcentrationCurveGenerator::Pointer m_concentrationGen;
+ std::vector <itk::Index<4>> m_testIndices;
+
+public:
+ void setUp() override
+ {
+ m_dynamicImage = mitk::GenerateDynamicTestImageMITK();
+ m_concentrationGen = mitk::ConcentrationCurveGenerator::New();
+ m_concentrationGen->SetDynamicImage(m_dynamicImage);
+ itk::Index<4> testIndex0 = { { 0, 0, 0, 0 } };
+ itk::Index<4> testIndex1 = { { 0, 2, 2, 3 } };
+ itk::Index<4> testIndex2 = { { 2, 2, 1, 9 } };
+ itk::Index<4> testIndex3 = { { 0, 3, 2, 1 } };
+ itk::Index<4> testIndex4 = { { 2, 2, 2, 4 } };
+ m_testIndices.push_back(testIndex0);
+ m_testIndices.push_back(testIndex1);
+ m_testIndices.push_back(testIndex2);
+ m_testIndices.push_back(testIndex3);
+ m_testIndices.push_back(testIndex4);
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetConvertedImageAbsoluteEnhancementTest()
+ {
+ m_concentrationGen->SetAbsoluteSignalEnhancement(true);
+ m_concentrationGen->SetFactor(1.0);
+ m_concentrationGen->SetBaselineStartTimeStep(0);
+ m_concentrationGen->SetBaselineEndTimeStep(0);
+ m_convertedImage = m_concentrationGen->GetConvertedImage();
+ mitk::ImagePixelReadAccessor<double, 4> readAccess(m_convertedImage, m_convertedImage->GetSliceData(4));
+ std::vector <double> refValues;
+ refValues.push_back(0.0);
+ refValues.push_back(90.0);
+ refValues.push_back(360.0);
+ refValues.push_back(0.0);
+ refValues.push_back(160.0);
+
+ std::stringstream ss;
+ for (long unsigned int i = 0; i < m_testIndices.size(); i++)
+ {
+ ss << "Checking value of image converted using absolute enhancement at test index " << i << ".";
+ std::string message = ss.str();
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(refValues.at(i), readAccess.GetPixelByIndex(m_testIndices.at(i)), 1e-6, true) == true);
+ }
+ }
+
+ void GetConvertedImageAbsoluteEnhancementAveragedBaselineTest()
+ {
+ m_concentrationGen->SetAbsoluteSignalEnhancement(true);
+ m_concentrationGen->SetFactor(1.0);
+ m_concentrationGen->SetBaselineStartTimeStep(1);
+ m_concentrationGen->SetBaselineEndTimeStep(3);
+ m_convertedImage = m_concentrationGen->GetConvertedImage();
+ mitk::ImagePixelReadAccessor<double, 4> readAccess(m_convertedImage, m_convertedImage->GetSliceData(4));
+ std::vector <double> refValues;
+ refValues.push_back(0.0);
+ refValues.push_back(30.0);
+ refValues.push_back(280.0);
+ refValues.push_back(0.0);
+ refValues.push_back(80.0);
+
+ std::stringstream ss;
+ for (long unsigned int i = 0; i < m_testIndices.size(); i++)
+ {
+ ss << "Checking value of image converted using absolute enhancement with averaged baseline at test index " << i << ".";
+ std::string message = ss.str();
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(refValues.at(i), readAccess.GetPixelByIndex(m_testIndices.at(i)), 1e-6, true) == true);
+ }
+ }
+
+ void GetConvertedImageRelativeEnhancementTest()
+ {
+ m_concentrationGen->SetRelativeSignalEnhancement(true);
+ m_concentrationGen->SetFactor(1.0);
+ m_concentrationGen->SetBaselineStartTimeStep(0);
+ m_concentrationGen->SetBaselineEndTimeStep(0);
+ m_convertedImage = m_concentrationGen->GetConvertedImage();
+ mitk::ImagePixelReadAccessor<double, 4> readAccess(m_convertedImage, m_convertedImage->GetSliceData(4));
+ std::vector <double> refValues;
+ refValues.push_back(0.0);
+ refValues.push_back(3.461538);
+ refValues.push_back(20.0);
+ refValues.push_back(0.0);
+ refValues.push_back(5.714286);
+
+ std::stringstream ss;
+ for (long unsigned int i = 0; i < m_testIndices.size(); i++)
+ {
+ ss << "Checking value of image converted using relative enhancement at test index " << i << ".";
+ std::string message = ss.str();
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(refValues.at(i), readAccess.GetPixelByIndex(m_testIndices.at(i)), 1e-6, true) == true);
+ }
+ }
+
+ void GetConvertedImageturboFLASHTest()
+ {
+ m_concentrationGen->SetisTurboFlashSequence(true);
+ m_concentrationGen->SetRecoveryTime(1.0);
+ m_concentrationGen->SetRelaxationTime(1.0);
+ m_concentrationGen->SetRelaxivity(1.0);
+ m_concentrationGen->SetBaselineStartTimeStep(0);
+ m_concentrationGen->SetBaselineEndTimeStep(0);
+ m_convertedImage = m_concentrationGen->GetConvertedImage();
+ mitk::ImagePixelReadAccessor<double, 4> readAccess(m_convertedImage, m_convertedImage->GetSliceData(4));
+ std::vector <double> refValues;
+ refValues.push_back(0.0);
+ refValues.push_back(0.0);
+ refValues.push_back(0.0);
+ refValues.push_back(0.0);
+ refValues.push_back(0.0);
+
+ std::stringstream ss;
+ for (long unsigned int i = 0; i < m_testIndices.size(); i++)
+ {
+ ss << "Checking value of image converted using the turboFLASH model at test index " << i << ".";
+ std::string message = ss.str();
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(refValues.at(i), readAccess.GetPixelByIndex(m_testIndices.at(i)), 1e-6, true) == true);
+ }
+ }
+
+ void GetConvertedImageVFATest()
+ {
+ mitk::Image::Pointer PDWImage;
+ PDWImage = mitk::GenerateTestFrame(1.0);
+ m_concentrationGen->SetUsingT1Map(true);
+ m_concentrationGen->SetRecoveryTime(1.0);
+ m_concentrationGen->SetRelaxivity(1.0);
+ m_concentrationGen->SetT10Image(PDWImage);
+ m_concentrationGen->SetFlipAngle(1.0);
+ m_concentrationGen->SetBaselineStartTimeStep(0);
+ m_concentrationGen->SetBaselineEndTimeStep(0);
+ m_convertedImage = m_concentrationGen->GetConvertedImage();
+ mitk::ImagePixelReadAccessor<double, 4> readAccess(m_convertedImage, m_convertedImage->GetSliceData(4));
+ std::vector <double> refValues;
+ refValues.push_back(0.0);
+ refValues.push_back(2.956868);
+ refValues.push_back(0.0);
+ refValues.push_back(0.0);
+ refValues.push_back(3.989374);
+
+ std::stringstream ss;
+ for (long unsigned int i = 0; i < m_testIndices.size(); i++)
+ {
+ ss << "Checking value of image converted using the VFA method at test index " << i << ".";
+ std::string message = ss.str();
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(refValues.at(i), readAccess.GetPixelByIndex(m_testIndices.at(i)), 1e-6, true) == true);
+ }
+ }
+
+ void GetConvertedImageT2Test()
+ {
+ m_concentrationGen->SetisT2weightedImage(true);
+ m_concentrationGen->SetT2Factor(1.0);
+ m_concentrationGen->SetT2EchoTime(1.0);
+ m_concentrationGen->SetBaselineStartTimeStep(0);
+ m_concentrationGen->SetBaselineEndTimeStep(0);
+ m_convertedImage = m_concentrationGen->GetConvertedImage();
+ mitk::ImagePixelReadAccessor<double, 4> readAccess(m_convertedImage, m_convertedImage->GetSliceData(4));
+ std::vector <double> refValues;
+ refValues.push_back(0.0);
+ refValues.push_back(-1.495494);
+ refValues.push_back(-3.044522);
+ refValues.push_back(0.0);
+ refValues.push_back(-1.904237);
+
+ std::stringstream ss;
+ for (long unsigned int i = 0; i < m_testIndices.size(); i++)
+ {
+ ss << "Checking value of converted T2 image at test index " << i << ".";
+ std::string message = ss.str();
+ CPPUNIT_ASSERT_MESSAGE(message, mitk::Equal(refValues.at(i), readAccess.GetPixelByIndex(m_testIndices.at(i)), 1e-6, true) == true);
+ }
+ }
+
+};
+MITK_TEST_SUITE_REGISTRATION(mitkConvertSignalToConcentration)
+
+
diff --git a/Modules/Pharmacokinetics/test/mitkCurveDescriptiveParametersTest.cpp b/Modules/Pharmacokinetics/test/mitkCurveDescriptiveParametersTest.cpp
new file mode 100644
index 0000000000..a6167bdaff
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkCurveDescriptiveParametersTest.cpp
@@ -0,0 +1,124 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+// Testing
+#include "mitkTestingMacros.h"
+#include "mitkTestFixture.h"
+
+//MITK includes
+#include "mitkVector.h"
+#include "mitkMaximumCurveDescriptionParameter.h"
+#include "mitkMeanResidenceTimeDescriptionParameter.h"
+#include "mitkAreaUnderTheCurveDescriptionParameter.h"
+#include "mitkAreaUnderFirstMomentDescriptionParameter.h"
+#include "mitkTimeToPeakCurveDescriptionParameter.h"
+
+class mitkCurveDescriptiveParametersTestSuite : public mitk::TestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkCurveDescriptiveParametersTestSuite);
+ MITK_TEST(MaximumCurveDescriptionParameterTest);
+ MITK_TEST(AreaUnderTheCurveDescriptionParameterTest);
+ MITK_TEST(AreaUnderFirstMomentDescriptionParameterTest);
+ MITK_TEST(MeanResidenceTimeDescriptionParameterTest);
+ MITK_TEST(TimeToPeakDescriptionParameterTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_maxParameter;
+ mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_aucParameter;
+ mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_aumcParameter;
+ mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_mrtParameter;
+ mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_ttpParameter;
+
+public:
+ void setUp() override
+ {
+ mitk::ModelBase::TimeGridType m_grid(22);
+ for (int i = 0; i < 22; ++i)
+ {
+ // time grid in seconds, 14s between frames
+ m_grid[i] = (double)14 * i;
+ }
+
+ static const double t = 100.0;
+ static const double b1 = 0.0;
+ static const double a1 = 5.0;
+ static const double a2 = -3.0;
+ const auto b2 = (a1-a2) * t + b1;
+
+
+ mitk::ModelBase::ModelResultType signal(m_grid.GetSize());
+ mitk::ModelBase::TimeGridType::const_iterator timeGridEnd = m_grid.end();
+ mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin();
+
+ for (mitk::ModelBase::ModelResultType::const_iterator gridPos = m_grid.begin(); gridPos != timeGridEnd; ++gridPos, ++signalPos)
+ {
+ if ((*gridPos) < t)
+ {
+ *signalPos = a1 * (*gridPos) + b1;
+ }
+ else
+ {
+ *signalPos = a2 * (*gridPos) + b2;
+ }
+ }
+
+ mitk::CurveDescriptionParameterBase::Pointer maxParameterFunction = mitk::MaximumCurveDescriptionParameter::New().GetPointer();
+ m_maxParameter = maxParameterFunction->GetCurveDescriptionParameter(signal, m_grid);
+
+ mitk::CurveDescriptionParameterBase::Pointer aucParameterFunction = mitk::AreaUnderTheCurveDescriptionParameter::New().GetPointer();
+ m_aucParameter = aucParameterFunction->GetCurveDescriptionParameter(signal, m_grid);
+
+ mitk::CurveDescriptionParameterBase::Pointer aumcParameterFunction = mitk::AreaUnderFirstMomentDescriptionParameter::New().GetPointer();
+ m_aumcParameter = aumcParameterFunction->GetCurveDescriptionParameter(signal, m_grid);
+
+ mitk::CurveDescriptionParameterBase::Pointer mrtParameterFunction = mitk::MeanResidenceTimeDescriptionParameter::New().GetPointer();
+ m_mrtParameter = mrtParameterFunction->GetCurveDescriptionParameter(signal, m_grid);
+
+ mitk::CurveDescriptionParameterBase::Pointer ttpParameterFunction = mitk::TimeToPeakCurveDescriptionParameter::New().GetPointer();
+ m_ttpParameter = ttpParameterFunction->GetCurveDescriptionParameter(signal, m_grid);
+ }
+
+
+ void tearDown() override
+ {
+
+ }
+
+ void MaximumCurveDescriptionParameterTest()
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking maximum value.", mitk::Equal(490.0, m_maxParameter[0], 1e-6, true) == true);
+ }
+
+ void AreaUnderTheCurveDescriptionParameterTest()
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking auc value.", mitk::Equal(67690.0, m_aucParameter[0], 1e-6, true) == true);
+ }
+
+ void AreaUnderFirstMomentDescriptionParameterTest()
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking aumc value.", mitk::Equal(8459948.0, m_aumcParameter[0], 1e-6, true) == true);
+ }
+
+ void MeanResidenceTimeDescriptionParameterTest()
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking mrt value.", mitk::Equal(124.980765253, m_mrtParameter[0], 1e-6, true) == true);
+ }
+
+ void TimeToPeakDescriptionParameterTest()
+ {
+ CPPUNIT_ASSERT_MESSAGE("Checking ttp value.", mitk::Equal(98.0, m_ttpParameter[0], 1e-6, true) == true);
+ }
+};
+MITK_TEST_SUITE_REGISTRATION(mitkCurveDescriptiveParameters)
+
+
diff --git a/Modules/Pharmacokinetics/test/mitkDescriptivePharmacokineticBrixModelTest.cpp b/Modules/Pharmacokinetics/test/mitkDescriptivePharmacokineticBrixModelTest.cpp
index acb5b64ca1..18944ba53d 100644
--- a/Modules/Pharmacokinetics/test/mitkDescriptivePharmacokineticBrixModelTest.cpp
+++ b/Modules/Pharmacokinetics/test/mitkDescriptivePharmacokineticBrixModelTest.cpp
@@ -1,165 +1,66 @@
/*============================================================================
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.
============================================================================*/
-// Testing
-#include "mitkTestingMacros.h"
-#include "mitkTestFixture.h"
+ //Testing
+#include "mitkModelTestFixture.h"
//MITK includes
-#include "mitkVector.h"
#include "mitkDescriptivePharmacokineticBrixModel.h"
-class mitkDescriptivePharmacokineticBrixModelTestSuite : public mitk::TestFixture
+
+ class mitkDescriptivePharmacokineticBrixModelTestSuite : public mitk::mitkModelTestFixture
{
CPPUNIT_TEST_SUITE(mitkDescriptivePharmacokineticBrixModelTestSuite);
- MITK_TEST(GetModelDisplayNameTest);
- MITK_TEST(GetModelTypeTest);
- MITK_TEST(GetXAxisNameTest);
- MITK_TEST(GetXAxisUnitTest);
- MITK_TEST(GetYAxisNameTest);
- MITK_TEST(GetYAxisUnitTest);
- MITK_TEST(GetParameterNamesTest);
- MITK_TEST(GetNumberOfParametersTest);
- MITK_TEST(GetParameterUnitsTest);
- MITK_TEST(GetStaticParameterNamesTest);
- MITK_TEST(GetNumberOfStaticParametersTest);
- MITK_TEST(GetStaticParameterUnitsTest);
+ MITK_TEST(GetModelInfoTest);
MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
CPPUNIT_TEST_SUITE_END();
- private:
- mitk::DescriptivePharmacokineticBrixModel::Pointer m_testmodel;
- std::string NAME_PARAMETER_A, POSITION_PARAMETER_kep, POSITION_PARAMETER_kel, POSITION_PARAMETER_tlag;
- mitk::ModelBase::ModelResultType m_output;
-
- public:
- void setUp() override
- {
- mitk::ModelBase::TimeGridType m_grid(22);
- mitk::ModelBase::ParametersType m_testparameters(4);
-
- m_testparameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_A] = 1.25;
- m_testparameters(mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kep) = 3.89;
- m_testparameters(mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kel) = 0.12;
- m_testparameters(mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_tlag) = 1.14;
-
- for (int i = 0; i < 22; ++i)
- {
- // time grid in seconds, 14s between frames
- m_grid[i] = (double)14 * i;
- }
- //injection time in minutes --> 30s
- double m_injectiontime = 0.5;
- m_testmodel = mitk::DescriptivePharmacokineticBrixModel::New();
- m_testmodel->SetTimeGrid(m_grid);
- m_testmodel->SetTau(m_injectiontime);
-
- //ComputeModelfunction is called within GetSignal(), therefore no explicit testing of ComputeModelFunction()
- m_output = m_testmodel->GetSignal(m_testparameters);
- }
-
- void tearDown() override
- {
- m_testmodel = nullptr;
- NAME_PARAMETER_A = "";
- POSITION_PARAMETER_kep = "";
- POSITION_PARAMETER_kel = "";
- POSITION_PARAMETER_tlag = "";
- m_output.clear();
- }
-
- void GetModelDisplayNameTest()
- {
- m_testmodel->GetModelDisplayName();
- CPPUNIT_ASSERT_MESSAGE("Checking model display name.", m_testmodel->GetModelDisplayName() == "Descriptive Pharmacokinetic Brix Model");
- }
-
- void GetModelTypeTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking model type.", m_testmodel->GetModelType() == "Perfusion.MR");
- }
-
- void GetXAxisNameTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking x-axis name.", m_testmodel->GetXAxisName() == "Time");
- }
-
- void GetXAxisUnitTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking x-axis unit", m_testmodel->GetXAxisUnit() == "s");
- }
-
- void GetYAxisNameTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking y-axis name.", m_testmodel->GetYAxisName() == "");
- }
-
- void GetYAxisUnitTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking y-axis unit", m_testmodel->GetYAxisUnit() == "");
- }
-
- void GetParameterNamesTest()
- {
- mitk::DescriptivePharmacokineticBrixModel::ParameterNamesType parameterNames;
- parameterNames.push_back("A");
- parameterNames.push_back("kep");
- parameterNames.push_back("kel");
- parameterNames.push_back("tlag");
- CPPUNIT_ASSERT_MESSAGE("Checking parameter names.", m_testmodel->GetParameterNames() == parameterNames);
- }
-
- void GetNumberOfParametersTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking number of parameters in model.", m_testmodel->GetNumberOfParameters() == 4);
- }
-
- void GetParameterUnitsTest()
- {
- mitk::DescriptivePharmacokineticBrixModel::ParamterUnitMapType parameterUnitMap;
- parameterUnitMap.insert(std::make_pair("A", "a.u."));
- parameterUnitMap.insert(std::make_pair("kep", "1/min"));
- parameterUnitMap.insert(std::make_pair("kel", "1/min"));
- parameterUnitMap.insert(std::make_pair("tlag", "min"));
- CPPUNIT_ASSERT_MESSAGE("Checking parameter unit map.", m_testmodel->GetParameterUnits() == parameterUnitMap);
- }
-
- void GetStaticParameterNamesTest()
- {
- mitk::DescriptivePharmacokineticBrixModel::ParameterNamesType staticParameterNames;
- staticParameterNames.push_back("Tau");
- staticParameterNames.push_back("S0");
- CPPUNIT_ASSERT_MESSAGE("Checking static parameter names.", m_testmodel->GetStaticParameterNames() == staticParameterNames);
- }
-
- void GetNumberOfStaticParametersTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking number of static parameters.", m_testmodel->GetNumberOfStaticParameters() == 2);
- }
-
- void GetStaticParameterUnitsTest()
- {
- mitk::DescriptivePharmacokineticBrixModel::ParamterUnitMapType staticParameterUnitMap;
- staticParameterUnitMap.insert(std::make_pair("Tau", "min"));
- staticParameterUnitMap.insert(std::make_pair("S0", "I"));
- CPPUNIT_ASSERT_MESSAGE("Checking static parameters units.", m_testmodel->GetStaticParameterUnits() == staticParameterUnitMap);
- }
-
- void ComputeModelfunctionTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking signal of parameter set 1 at time frame 0.", mitk::Equal(1, m_output[0], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal of parameter set 1 at time frame 10.",mitk::Equal(2.113611, m_output[10], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal of parameter set 1 at time frame 20.", mitk::Equal(1.870596, m_output[20], 1e-6, true) == true);
- }
+private:
+ mitk::DescriptivePharmacokineticBrixModel::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkDescriptivePharmacokineticBrixModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkDescriptivePharmacokineticBrixModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::DescriptivePharmacokineticBrixModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
};
MITK_TEST_SUITE_REGISTRATION(mitkDescriptivePharmacokineticBrixModel)
diff --git a/Modules/Pharmacokinetics/test/mitkExtendedOneTissueCompartmentModelTest.cpp b/Modules/Pharmacokinetics/test/mitkExtendedOneTissueCompartmentModelTest.cpp
new file mode 100644
index 0000000000..e85625e206
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkExtendedOneTissueCompartmentModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+ //Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkExtendedOneTissueCompartmentModel.h"
+
+
+ class mitkExtendedOneTissueCompartmentModelTestSuite : public mitk::mitkModelTestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkExtendedOneTissueCompartmentModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::AIFBasedModelBase::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkExtendedOneTissueCompartmentModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkExtendedOneTissueCompartmentModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::ExtendedOneTissueCompartmentModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkExtendedOneTissueCompartmentModel)
diff --git a/Modules/Pharmacokinetics/test/mitkExtendedToftsModelTest.cpp b/Modules/Pharmacokinetics/test/mitkExtendedToftsModelTest.cpp
index 5bd2a350e1..5533e39f56 100644
--- a/Modules/Pharmacokinetics/test/mitkExtendedToftsModelTest.cpp
+++ b/Modules/Pharmacokinetics/test/mitkExtendedToftsModelTest.cpp
@@ -1,164 +1,66 @@
/*============================================================================
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.
============================================================================*/
-// Testing
-#include "mitkTestingMacros.h"
-#include "mitkTestFixture.h"
-#include "math.h"
+ //Testing
+#include "mitkModelTestFixture.h"
//MITK includes
-#include "mitkVector.h"
#include "mitkExtendedToftsModel.h"
-#include "mitkAIFBasedModelBase.h"
-class mitkExtendedToftsModelTestSuite : public mitk::TestFixture
+
+ class mitkExtendedToftsModelTestSuite : public mitk::mitkModelTestFixture
{
CPPUNIT_TEST_SUITE(mitkExtendedToftsModelTestSuite);
- MITK_TEST(GetModelDisplayNameTest);
- MITK_TEST(GetModelTypeTest);
- MITK_TEST(GetParameterNamesTest);
- MITK_TEST(GetNumberOfParametersTest);
- MITK_TEST(GetParameterUnitsTest);
- MITK_TEST(GetDerivedParameterNamesTest);
- MITK_TEST(GetNumberOfDerivedParametersTest);
- MITK_TEST(GetDerivedParameterUnitsTest);
+ MITK_TEST(GetModelInfoTest);
MITK_TEST(ComputeModelfunctionTest);
MITK_TEST(ComputeDerivedParametersTest);
CPPUNIT_TEST_SUITE_END();
private:
- mitk::ExtendedToftsModel::Pointer m_testmodel;
- mitk::ModelBase::ModelResultType m_output;
- mitk::ModelBase::DerivedParameterMapType m_derivedParameters;
+ mitk::AIFBasedModelBase::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
public:
void setUp() override
{
- mitk::ModelBase::TimeGridType m_grid(60);
- mitk::ModelBase::ParametersType m_testparameters(3);
- mitk::AIFBasedModelBase::AterialInputFunctionType m_arterialInputFunction (60);
-
- m_testparameters[mitk::ExtendedToftsModel::POSITION_PARAMETER_Ktrans] = 35.0;
- m_testparameters(mitk::ExtendedToftsModel::POSITION_PARAMETER_ve) = 0.5;
- m_testparameters[mitk::ExtendedToftsModel::POSITION_PARAMETER_vp] = 0.05;
-
- for (int i = 0; i < 22; ++i)
- {
- // time grid in seconds, 14s between frames
- m_grid[i] = (double)14 * i;
- }
-
- // AIF from Weinmann, H. J., Laniado, M., and W.Mützel (1984). Pharmacokinetics of GD - DTPA / dimeglumine after intravenous injection into healthy volunteers. Phys Chem Phys Med NMR, 16(2) : 167–72.
- int D = 1;
- double a1 = 3.99;
- double m1 = 0.144;
- double a2 = 4.78;
- double m2 = 0.0111;
- for (int i = 0; i < 22; ++i)
- {
- m_arterialInputFunction[i] = D * (a1 * exp(-m1 * m_grid[i]) + a2 * exp(-m2 * m_grid[i]));
- }
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkExtendedToftsModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkExtendedToftsModelTest_modelValues.json");
+ // Generate test model
m_testmodel = mitk::ExtendedToftsModel::New();
- m_testmodel->SetTimeGrid(m_grid);
- m_testmodel->SetAterialInputFunctionValues(m_arterialInputFunction);
- m_testmodel->SetAterialInputFunctionTimeGrid(m_grid);
-
- //ComputeModelfunction is called within GetSignal(), therefore no explicit testing of ComputeModelFunction()
- m_output = m_testmodel->GetSignal(m_testparameters);
- m_derivedParameters = m_testmodel->GetDerivedParameters(m_testparameters);
- }
+ }
void tearDown() override
{
- m_testmodel = nullptr;
- m_output.clear();
- m_derivedParameters.clear();
}
- void GetModelDisplayNameTest()
+ void GetModelInfoTest()
{
- m_testmodel->GetModelDisplayName();
- CPPUNIT_ASSERT_MESSAGE("Checking model display name.", m_testmodel->GetModelDisplayName() == "Extended Tofts Model");
- }
-
-
- void GetModelTypeTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking model type.", m_testmodel->GetModelType() == "Perfusion.MR");
- }
-
-
- void GetParameterNamesTest()
- {
- mitk::ExtendedToftsModel::ParameterNamesType parameterNames;
- parameterNames.push_back("KTrans");
- parameterNames.push_back("ve");
- parameterNames.push_back("vp");
- CPPUNIT_ASSERT_MESSAGE("Checking parameter names.", m_testmodel->GetParameterNames() == parameterNames);
- }
-
- void GetNumberOfParametersTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking number of parameters in model.", m_testmodel->GetNumberOfParameters() == 3);
- }
-
-
- void GetParameterUnitsTest()
- {
- mitk::ExtendedToftsModel::ParamterUnitMapType parameterUnits;
- parameterUnits.insert(std::make_pair("KTrans", "ml/min/100ml"));
- parameterUnits.insert(std::make_pair("vp", "ml/ml"));
- parameterUnits.insert(std::make_pair("ve","ml/ml"));
-
- CPPUNIT_ASSERT_MESSAGE("Checking parameter units.", m_testmodel->GetParameterUnits() == parameterUnits);
- }
-
- void GetDerivedParameterNamesTest()
- {
- mitk::ExtendedToftsModel::ParameterNamesType derivedParameterNames;
-
- derivedParameterNames.push_back("kep");
-
- CPPUNIT_ASSERT_MESSAGE("Checking derived parameter names.", m_testmodel->GetDerivedParameterNames() == derivedParameterNames);
- }
-
- void GetNumberOfDerivedParametersTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking number of parameters in model.", m_testmodel->GetNumberOfDerivedParameters() == 1);
- }
-
- void GetDerivedParameterUnitsTest()
- {
- mitk::ExtendedToftsModel::ParamterUnitMapType derivedParameterUnits;
- derivedParameterUnits.insert(std::make_pair("kep", "1/min"));
-
- CPPUNIT_ASSERT_MESSAGE("Checking parameter units.", m_testmodel->GetDerivedParameterUnits() == derivedParameterUnits);
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
}
void ComputeModelfunctionTest()
{
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 0.", mitk::Equal(0.438500, m_output[0], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 5.", mitk::Equal(1.094436, m_output[5], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 10", mitk::Equal(0.890956, m_output[10], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 15", mitk::Equal(0.580996, m_output[15], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 20", mitk::Equal(0.342851, m_output[20], 1e-6, true) == true);
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
}
void ComputeDerivedParametersTest()
{
- CPPUNIT_ASSERT_MESSAGE("Checking kep.", mitk::Equal(70.00, m_derivedParameters["kep"], 1e-6, true) == true);
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
}
-
};
MITK_TEST_SUITE_REGISTRATION(mitkExtendedToftsModel)
diff --git a/Modules/Pharmacokinetics/test/mitkOneTissueCompartmentModelTest.cpp b/Modules/Pharmacokinetics/test/mitkOneTissueCompartmentModelTest.cpp
new file mode 100644
index 0000000000..84a4eccc9c
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkOneTissueCompartmentModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+ //Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkOneTissueCompartmentModel.h"
+
+
+ class mitkOneTissueCompartmentModelTestSuite : public mitk::mitkModelTestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkOneTissueCompartmentModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::AIFBasedModelBase::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkOneTissueCompartmentModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkOneTissueCompartmentModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::OneTissueCompartmentModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkOneTissueCompartmentModel)
diff --git a/Modules/Pharmacokinetics/test/mitkStandardToftsModelTest.cpp b/Modules/Pharmacokinetics/test/mitkStandardToftsModelTest.cpp
index 5b0c907166..ead04087e4 100644
--- a/Modules/Pharmacokinetics/test/mitkStandardToftsModelTest.cpp
+++ b/Modules/Pharmacokinetics/test/mitkStandardToftsModelTest.cpp
@@ -1,162 +1,66 @@
/*============================================================================
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.
============================================================================*/
-// Testing
-#include "mitkTestingMacros.h"
-#include "mitkTestFixture.h"
+ //Testing
+#include "mitkModelTestFixture.h"
//MITK includes
-#include "mitkVector.h"
#include "mitkStandardToftsModel.h"
-#include "mitkAIFBasedModelBase.h"
-class mitkStandardToftsModelTestSuite : public mitk::TestFixture
+
+ class mitkStandardToftsModelTestSuite : public mitk::mitkModelTestFixture
{
CPPUNIT_TEST_SUITE(mitkStandardToftsModelTestSuite);
- MITK_TEST(GetModelDisplayNameTest);
- MITK_TEST(GetModelTypeTest);
- MITK_TEST(GetParameterNamesTest);
- MITK_TEST(GetNumberOfParametersTest);
- MITK_TEST(GetParameterUnitsTest);
- MITK_TEST(GetDerivedParameterNamesTest);
- MITK_TEST(GetNumberOfDerivedParametersTest);
- MITK_TEST(GetDerivedParameterUnitsTest);
+ MITK_TEST(GetModelInfoTest);
MITK_TEST(ComputeModelfunctionTest);
MITK_TEST(ComputeDerivedParametersTest);
CPPUNIT_TEST_SUITE_END();
private:
- mitk::StandardToftsModel::Pointer m_testmodel;
- mitk::ModelBase::ModelResultType m_output;
- mitk::ModelBase::DerivedParameterMapType m_derivedParameters;
+ mitk::AIFBasedModelBase::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
public:
void setUp() override
{
- mitk::ModelBase::TimeGridType m_grid(22);
- mitk::ModelBase::ParametersType m_testparameters(2);
- mitk::AIFBasedModelBase::AterialInputFunctionType m_arterialInputFunction (22);
-
- m_testparameters[mitk::StandardToftsModel::POSITION_PARAMETER_Ktrans] = 35.0;
- m_testparameters(mitk::StandardToftsModel::POSITION_PARAMETER_ve) = 0.5;
-
- for (int i = 0; i < 22; ++i)
- {
- // time grid in seconds, 14s between frames
- m_grid[i] = (double)14 * i;
- }
-
- // AIF from Weinmann, H. J., Laniado, M., and W.Mützel (1984). Pharmacokinetics of GD - DTPA / dimeglumine after intravenous injection into healthy volunteers. Phys Chem Phys Med NMR, 16(2) : 167–72.
- int D = 1;
- double a1 = 3.99;
- double m1 = 0.144;
- double a2 = 4.78;
- double m2 = 0.0111;
- for (int i = 0; i < 22; ++i)
- {
- if (i < 5)
- m_arterialInputFunction[i] = 0;
- else
- m_arterialInputFunction[i] = D * (a1 * exp(-m1 * m_grid[i]) + a2 * exp(-m2 * m_grid[i]));
- }
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkStandardToftsModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkStandardToftsModelTest_modelValues.json");
+ // Generate test model
m_testmodel = mitk::StandardToftsModel::New();
- m_testmodel->SetTimeGrid(m_grid);
- m_testmodel->SetAterialInputFunctionValues(m_arterialInputFunction);
- m_testmodel->SetAterialInputFunctionTimeGrid(m_grid);
-
- //ComputeModelfunction is called within GetSignal(), therefore no explicit testing of ComputeModelFunction()
- m_output = m_testmodel->GetSignal(m_testparameters);
- m_derivedParameters = m_testmodel->GetDerivedParameters(m_testparameters);
- }
+ }
void tearDown() override
{
- m_testmodel = nullptr;
- m_output.clear();
- m_derivedParameters.clear();
}
- void GetModelDisplayNameTest()
+ void GetModelInfoTest()
{
- m_testmodel->GetModelDisplayName();
- CPPUNIT_ASSERT_MESSAGE("Checking model display name.", m_testmodel->GetModelDisplayName() == "Standard Tofts Model");
- }
-
-
- void GetModelTypeTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking model type.", m_testmodel->GetModelType() == "Perfusion.MR");
- }
-
-
- void GetParameterNamesTest()
- {
- mitk::StandardToftsModel::ParameterNamesType parameterNames;
- parameterNames.push_back("KTrans");
- parameterNames.push_back("ve");
- CPPUNIT_ASSERT_MESSAGE("Checking parameter names.", m_testmodel->GetParameterNames() == parameterNames);
- }
-
- void GetNumberOfParametersTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking number of parameters in model.", m_testmodel->GetNumberOfParameters() == 2);
- }
-
-
- void GetParameterUnitsTest()
- {
- mitk::StandardToftsModel::ParamterUnitMapType parameterUnits;
- parameterUnits.insert(std::make_pair("KTrans", "ml/min/100ml"));
- parameterUnits.insert(std::make_pair("ve", "ml/ml"));
-
- CPPUNIT_ASSERT_MESSAGE("Checking parameter units.", m_testmodel->GetParameterUnits() == parameterUnits);
- }
-
- void GetDerivedParameterNamesTest()
- {
- mitk::StandardToftsModel::ParameterNamesType derivedParameterNames;
-
- derivedParameterNames.push_back("kep");
-
- CPPUNIT_ASSERT_MESSAGE("Checking derived parameter names.", m_testmodel->GetDerivedParameterNames() == derivedParameterNames);
- }
-
- void GetNumberOfDerivedParametersTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking number of parameters in model.", m_testmodel->GetNumberOfDerivedParameters() == 1);
- }
-
- void GetDerivedParameterUnitsTest()
- {
- mitk::StandardToftsModel::ParamterUnitMapType derivedParameterUnits;
- derivedParameterUnits.insert(std::make_pair("kep", "1/min"));
-
- CPPUNIT_ASSERT_MESSAGE("Checking parameter units.", m_testmodel->GetDerivedParameterUnits() == derivedParameterUnits);
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
}
void ComputeModelfunctionTest()
{
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 0.", mitk::Equal(0.0, m_output[0], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 5.", mitk::Equal(0.085056, m_output[5], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 10.", mitk::Equal(0.442948, m_output[10], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 20.", mitk::Equal(0.254551, m_output[20], 1e-6, true) == true);
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
}
void ComputeDerivedParametersTest()
{
- CPPUNIT_ASSERT_MESSAGE("Checking kep.", mitk::Equal(70.0, m_derivedParameters["kep"], 1e-6, true) == true);
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
}
-
};
MITK_TEST_SUITE_REGISTRATION(mitkStandardToftsModel)
diff --git a/Modules/Pharmacokinetics/test/mitkThreeStepLinearModelTest.cpp b/Modules/Pharmacokinetics/test/mitkThreeStepLinearModelTest.cpp
new file mode 100644
index 0000000000..074f783c6b
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkThreeStepLinearModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+ //Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkThreeStepLinearModel.h"
+
+
+ class mitkThreeStepLinearModelTestSuite : public mitk::mitkModelTestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkThreeStepLinearModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::ThreeStepLinearModel::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkThreeStepLinearModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkThreeStepLinearModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::ThreeStepLinearModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkThreeStepLinearModel)
diff --git a/Modules/Pharmacokinetics/test/mitkTwoCompartmentExchangeModelTest.cpp b/Modules/Pharmacokinetics/test/mitkTwoCompartmentExchangeModelTest.cpp
index 652198ec20..e9b8068def 100644
--- a/Modules/Pharmacokinetics/test/mitkTwoCompartmentExchangeModelTest.cpp
+++ b/Modules/Pharmacokinetics/test/mitkTwoCompartmentExchangeModelTest.cpp
@@ -1,137 +1,66 @@
/*============================================================================
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.
============================================================================*/
-// Testing
-#include "mitkTestingMacros.h"
-#include "mitkTestFixture.h"
+ //Testing
+#include "mitkModelTestFixture.h"
//MITK includes
-#include "mitkVector.h"
#include "mitkTwoCompartmentExchangeModel.h"
-#include "mitkAIFBasedModelBase.h"
-class mitkTwoCompartmentExchangeModelTestSuite : public mitk::TestFixture
+
+ class mitkTwoCompartmentExchangeModelTestSuite : public mitk::mitkModelTestFixture
{
CPPUNIT_TEST_SUITE(mitkTwoCompartmentExchangeModelTestSuite);
- MITK_TEST(GetModelDisplayNameTest);
- MITK_TEST(GetModelTypeTest);
- MITK_TEST(GetParameterNamesTest);
- MITK_TEST(GetNumberOfParametersTest);
- MITK_TEST(GetParameterUnitsTest);
+ MITK_TEST(GetModelInfoTest);
MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
CPPUNIT_TEST_SUITE_END();
private:
mitk::TwoCompartmentExchangeModel::Pointer m_testmodel;
- mitk::ModelBase::ModelResultType m_output;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
public:
void setUp() override
{
- mitk::ModelBase::TimeGridType m_grid(22);
- mitk::ModelBase::ParametersType m_testparameters(4);
- mitk::AIFBasedModelBase::AterialInputFunctionType m_arterialInputFunction (22);
-
- m_testparameters[mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_F] = 35.0;
- m_testparameters(mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_PS) = 5.0;
- m_testparameters(mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_ve) = 0.5;
- m_testparameters(mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_vp) = 0.05;
-
-
- for (int i = 0; i < 22; ++i)
- {
- // time grid in seconds, 14s between frames
- m_grid[i] = (double)14 * i;
- }
-
- // AIF from Weinmann, H. J., Laniado, M., and W.Mützel (1984). Pharmacokinetics of GD - DTPA / dimeglumine after intravenous injection into healthy volunteers. Phys Chem Phys Med NMR, 16(2) : 167–72.
- int D = 1;
- double a1 = 3.99;
- double m1 = 0.144;
- double a2 = 4.78;
- double m2 = 0.0111;
-
- for (int i = 0; i < 22; ++i)
- {
- if (i < 5)
- m_arterialInputFunction[i] = 0;
- else
- m_arterialInputFunction[i] = D * (a1 * exp(-m1 * m_grid[i]) + a2 * exp(-m2 * m_grid[i]));
- }
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoCompartmentExchangeModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoCompartmentExchangeModelTest_modelValues.json");
+ // Generate test model
m_testmodel = mitk::TwoCompartmentExchangeModel::New();
- m_testmodel->SetTimeGrid(m_grid);
- m_testmodel->SetAterialInputFunctionValues(m_arterialInputFunction);
- m_testmodel->SetAterialInputFunctionTimeGrid(m_grid);
+ }
- //ComputeModelfunction is called within GetSignal(), therefore no explicit testing of ComputeModelFunction()
- m_output = m_testmodel->GetSignal(m_testparameters);
- }
void tearDown() override
{
- m_testmodel = nullptr;
- m_output.clear();
- }
-
- void GetModelDisplayNameTest()
- {
- m_testmodel->GetModelDisplayName();
- CPPUNIT_ASSERT_MESSAGE("Checking model display name.", m_testmodel->GetModelDisplayName() == "Two Compartment Exchange Model");
- }
-
-
- void GetModelTypeTest()
- {
- CPPUNIT_ASSERT_MESSAGE("Checking model type.", m_testmodel->GetModelType() == "Perfusion.MR");
}
-
- void GetParameterNamesTest()
- {
- mitk::TwoCompartmentExchangeModel::ParameterNamesType parameterNames;
- parameterNames.push_back("F");
- parameterNames.push_back("PS");
- parameterNames.push_back("ve");
- parameterNames.push_back("vp");
- CPPUNIT_ASSERT_MESSAGE("Checking parameter names.", m_testmodel->GetParameterNames() == parameterNames);
- }
-
-
- void GetNumberOfParametersTest()
+ void GetModelInfoTest()
{
- CPPUNIT_ASSERT_MESSAGE("Checking number of parameters in model.", m_testmodel->GetNumberOfParameters() == 4);
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
}
-
- void GetParameterUnitsTest()
+ void ComputeModelfunctionTest()
{
- mitk::TwoCompartmentExchangeModel::ParamterUnitMapType parameterUnits;
- parameterUnits.insert(std::make_pair("F", "ml/min/100ml"));
- parameterUnits.insert(std::make_pair("PS", "ml/min/100ml"));
- parameterUnits.insert(std::make_pair("ve", "ml/ml"));
- parameterUnits.insert(std::make_pair("vp", "ml/ml"));
-
- CPPUNIT_ASSERT_MESSAGE("Checking parameter units.", m_testmodel->GetParameterUnits() == parameterUnits);
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
}
- void ComputeModelfunctionTest()
+ void ComputeDerivedParametersTest()
{
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 0.", mitk::Equal(0.0, m_output[0], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 5.", mitk::Equal(0.057246, m_output[5], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 10.", mitk::Equal(0.127806, m_output[10], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 15.", mitk::Equal(0.131465, m_output[15], 1e-6, true) == true);
- CPPUNIT_ASSERT_MESSAGE("Checking signal at time frame 20.", mitk::Equal(0.126101, m_output[20], 1e-6, true) == true);
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
}
-
};
MITK_TEST_SUITE_REGISTRATION(mitkTwoCompartmentExchangeModel)
diff --git a/Modules/Pharmacokinetics/test/mitkTwoStepLinearModelTest.cpp b/Modules/Pharmacokinetics/test/mitkTwoStepLinearModelTest.cpp
new file mode 100644
index 0000000000..de8b2e160f
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkTwoStepLinearModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+ //Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkTwoStepLinearModel.h"
+
+
+ class mitkTwoStepLinearModelTestSuite : public mitk::mitkModelTestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkTwoStepLinearModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::TwoStepLinearModel::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoStepLinearModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoStepLinearModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::TwoStepLinearModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkTwoStepLinearModel)
diff --git a/Modules/Pharmacokinetics/test/mitkTwoTissueCompartmentFDGModelTest.cpp b/Modules/Pharmacokinetics/test/mitkTwoTissueCompartmentFDGModelTest.cpp
new file mode 100644
index 0000000000..37e77c8ff1
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkTwoTissueCompartmentFDGModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+ //Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkTwoTissueCompartmentFDGModel.h"
+
+
+ class mitkTwoTissueCompartmentFDGModelTestSuite : public mitk::mitkModelTestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkTwoTissueCompartmentFDGModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::AIFBasedModelBase::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoTissueCompartmentFDGModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoTissueCompartmentFDGModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::TwoTissueCompartmentFDGModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkTwoTissueCompartmentFDGModel)
diff --git a/Modules/Pharmacokinetics/test/mitkTwoTissueCompartmentModelTest.cpp b/Modules/Pharmacokinetics/test/mitkTwoTissueCompartmentModelTest.cpp
new file mode 100644
index 0000000000..a1c265c996
--- /dev/null
+++ b/Modules/Pharmacokinetics/test/mitkTwoTissueCompartmentModelTest.cpp
@@ -0,0 +1,66 @@
+/*============================================================================
+
+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.
+
+============================================================================*/
+
+ //Testing
+#include "mitkModelTestFixture.h"
+
+//MITK includes
+#include "mitkTwoTissueCompartmentModel.h"
+
+
+ class mitkTwoTissueCompartmentModelTestSuite : public mitk::mitkModelTestFixture
+{
+ CPPUNIT_TEST_SUITE(mitkTwoTissueCompartmentModelTestSuite);
+ MITK_TEST(GetModelInfoTest);
+ MITK_TEST(ComputeModelfunctionTest);
+ MITK_TEST(ComputeDerivedParametersTest);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ mitk::AIFBasedModelBase::Pointer m_testmodel;
+
+ json m_profile_json_obj;
+ json m_modelValues_json_obj;
+
+public:
+ void setUp() override
+ {
+ // Parse JSON files
+ m_profile_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoTissueCompartmentModelTest_profile.json");
+ m_modelValues_json_obj = ParseJSONFile("Pharmacokinetics/mitkTwoTissueCompartmentModelTest_modelValues.json");
+
+ // Generate test model
+ m_testmodel = mitk::TwoTissueCompartmentModel::New();
+ }
+
+ void tearDown() override
+ {
+ }
+
+ void GetModelInfoTest()
+ {
+ // comparison of reference and testmodel profile
+ CompareModelAndReferenceProfile(m_testmodel, m_profile_json_obj);
+ }
+
+ void ComputeModelfunctionTest()
+ {
+ CompareModelAndReferenceSignal(m_testmodel, m_modelValues_json_obj, m_profile_json_obj);
+ }
+
+ void ComputeDerivedParametersTest()
+ {
+ CompareModelAndReferenceDerivedParameters(m_testmodel, m_modelValues_json_obj);
+ }
+};
+
+MITK_TEST_SUITE_REGISTRATION(mitkTwoTissueCompartmentModel)
diff --git a/Modules/QtWidgets/include/QmitkMxNMultiWidget.h b/Modules/QtWidgets/include/QmitkMxNMultiWidget.h
index 103e6de46a..9ae1bc0ab7 100644
--- a/Modules/QtWidgets/include/QmitkMxNMultiWidget.h
+++ b/Modules/QtWidgets/include/QmitkMxNMultiWidget.h
@@ -1,136 +1,131 @@
/*============================================================================
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 QmitkMxNMultiWidget_h
#define QmitkMxNMultiWidget_h
#include "MitkQtWidgetsExports.h"
// qt widgets module
#include "QmitkAbstractMultiWidget.h"
#include <QmitkSynchronizedNodeSelectionWidget.h>
#include <QmitkSynchronizedWidgetConnector.h>
#include <nlohmann/json.hpp>
class QSplitter;
/**
* @brief The 'QmitkMxNMultiWidget' is a 'QmitkAbstractMultiWidget' that is used to display multiple render windows at once.
* Render windows can dynamically be added and removed to change the layout of the multi widget. This
* is done by using the 'SetLayout'-function to define a layout. This will automatically add or remove
* the appropriate number of render window widgets.
*/
class MITKQTWIDGETS_EXPORT QmitkMxNMultiWidget : public QmitkAbstractMultiWidget
{
Q_OBJECT
public:
QmitkMxNMultiWidget(QWidget* parent = nullptr,
Qt::WindowFlags f = 0,
const QString& multiWidgetName = "mxn");
~QmitkMxNMultiWidget();
void InitializeMultiWidget() override;
void Synchronize(bool synchronized) override;
QmitkRenderWindow* GetRenderWindow(const QString& widgetName) const override;
QmitkRenderWindow* GetRenderWindow(const mitk::AnatomicalPlane& orientation) const override;
void SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget) override;
/**
* @brief Initialize the active render windows of the MxNMultiWidget to the given geometry.
*
* @param geometry The geometry to be used to initialize / update the
* active render window's time and slice navigation controller.
* @param resetCamera If true, the camera and crosshair will be reset to the default view (centered, no zoom).
* If false, the current crosshair position and the camera zoom will be stored and reset
* after the reference geometry has been updated.
*/
void InitializeViews(const mitk::TimeGeometry* geometry, bool resetCamera) override;
/**
* @brief Forward the given time geometry to all base renderers, so that they can store it as their
* interaction reference geometry.
* This will update the alignment status of the reference geometry for each base renderer.
* For more details, see 'BaseRenderer::SetInteractionReferenceGeometry'.
* Overridem from 'QmitkAbstractMultiWidget'.
*/
void SetInteractionReferenceGeometry(const mitk::TimeGeometry* referenceGeometry) override;
/**
* @brief Returns true if the render windows are coupled; false if not.
*
* For the MxNMultiWidget the render windows are typically decoupled.
*/
bool HasCoupledRenderWindows() const override;
void SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) override;
const mitk::Point3D GetSelectedPosition(const QString& widgetName) const override;
void SetCrosshairVisibility(bool visible) override;
bool GetCrosshairVisibility() const override;
void SetCrosshairGap(unsigned int gapSize) override;
void ResetCrosshair() override;
void SetWidgetPlaneMode(int userMode) override;
mitk::SliceNavigationController* GetTimeNavigationController();
void EnableCrosshair();
void DisableCrosshair();
public Q_SLOTS:
// mouse events
void wheelEvent(QWheelEvent* e) override;
void mousePressEvent(QMouseEvent* e) override;
void moveEvent(QMoveEvent* e) override;
void LoadLayout(const nlohmann::json* jsonData);
void SaveLayout(std::ostream* outStream);
Q_SIGNALS:
void WheelMoved(QWheelEvent *);
void Moved();
void UpdateUtilityWidgetViewPlanes();
void LayoutChanged();
-protected:
-
- void RemoveRenderWindowWidget() override;
-
private:
void SetLayoutImpl() override;
void SetInteractionSchemeImpl() override { }
QmitkAbstractMultiWidget::RenderWindowWidgetPointer CreateRenderWindowWidget();
void SetInitialSelection();
void ToggleSynchronization(QmitkSynchronizedNodeSelectionWidget* synchronizedWidget);
static nlohmann::json BuildJSONFromLayout(const QSplitter* splitter);
QSplitter* BuildLayoutFromJSON(const nlohmann::json* jsonData, unsigned int* windowCounter, QSplitter* parentSplitter = nullptr);
- mitk::SliceNavigationController* m_TimeNavigationController;
std::unique_ptr<QmitkSynchronizedWidgetConnector> m_SynchronizedWidgetConnector;
bool m_CrosshairVisibility;
};
#endif
diff --git a/Modules/QtWidgets/include/QmitkStdMultiWidget.h b/Modules/QtWidgets/include/QmitkStdMultiWidget.h
index ce22931e50..9c6f0e34d0 100644
--- a/Modules/QtWidgets/include/QmitkStdMultiWidget.h
+++ b/Modules/QtWidgets/include/QmitkStdMultiWidget.h
@@ -1,176 +1,173 @@
/*============================================================================
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 QmitkStdMultiWidget_h
#define QmitkStdMultiWidget_h
// qt widgets module
#include "MitkQtWidgetsExports.h"
#include "QmitkAbstractMultiWidget.h"
/**
* @brief The 'QmitkStdMultiWidget' is a 'QmitkAbstractMultiWidget' that is used to display multiple render windows at once.
* Render windows are predefined in a 2x2 design with 3 different 2D view planes and a 3D render window.
*/
class MITKQTWIDGETS_EXPORT QmitkStdMultiWidget : public QmitkAbstractMultiWidget
{
Q_OBJECT
public:
QmitkStdMultiWidget(
QWidget *parent = nullptr,
Qt::WindowFlags f = nullptr,
const QString &name = "stdmulti");
~QmitkStdMultiWidget() override;
virtual void InitializeMultiWidget() override;
virtual QmitkRenderWindow* GetRenderWindow(const QString& widgetName) const override;
virtual QmitkRenderWindow* GetRenderWindow(const mitk::AnatomicalPlane& orientation) const override;
/**
* @brief Initialize all render windows of the StdMultiWidget to the given geometry.
* Overridem from 'QmitkAbstractMultiWidget'.
*
* @param geometry The geometry to be used to initialize / update all
* render window's time and slice navigation controller.
* @param resetCamera If true, the camera and crosshair will be reset to the default view (centered, no zoom).
* If false, the current crosshair position and the camera zoom will be stored and reset
* after the reference geometry has been updated.
*/
void InitializeViews(const mitk::TimeGeometry* geometry, bool resetCamera) override;
/**
* @brief Not implemented in this class.
* Overridem from 'QmitkAbstractMultiWidget'.
*/
void SetInteractionReferenceGeometry(const mitk::TimeGeometry* referenceGeometry) override;
/**
* @brief Returns true if the render windows are coupled; false if not.
*
* For the StdMultiWidget the render windows are typically coupled.
*/
bool HasCoupledRenderWindows() const override;
virtual void SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) override;
virtual const mitk::Point3D GetSelectedPosition(const QString& widgetName) const override;
virtual void SetCrosshairVisibility(bool) override;
virtual bool GetCrosshairVisibility() const override;
void SetCrosshairGap(unsigned int gapSize) override;
virtual void ResetCrosshair() override;
virtual void SetWidgetPlaneMode(int mode) override;
- mitk::SliceNavigationController* GetTimeNavigationController();
void AddPlanesToDataStorage();
void RemovePlanesFromDataStorage();
/**
* @brief Convenience method to get a render window widget.
* @param number of the widget (0-3)
* @return The render window widget
*/
QmitkRenderWindow* GetRenderWindow(unsigned int number) const;
QmitkRenderWindow* GetRenderWindow1() const;
QmitkRenderWindow* GetRenderWindow2() const;
QmitkRenderWindow* GetRenderWindow3() const;
QmitkRenderWindow* GetRenderWindow4() const;
/**
* @brief Convenience method to get a widget plane.
* @param number of the widget plane (1-3)
* @return The widget plane as data node
*/
mitk::DataNode::Pointer GetWidgetPlane(unsigned int number) const;
mitk::DataNode::Pointer GetWidgetPlane1() const;
mitk::DataNode::Pointer GetWidgetPlane2() const;
mitk::DataNode::Pointer GetWidgetPlane3() const;
/**
* @brief SetDecorationColor Set the color of the decoration of the 4 widgets.
*
* This is used to color the frame of the renderwindow and the corner annatation.
* For the first 3 widgets, this color is a property of the helper object nodes
* which contain the respective plane geometry. For widget 4, this is a member,
* since there is no data node for this widget.
*/
void SetDecorationColor(unsigned int widgetNumber, mitk::Color color);
/**
* @brief GetDecorationColorForWidget Get the color for annotation, crosshair and rectangle.
* @param widgetNumber Number of the renderwindow (0-3).
* @return Color in mitk format.
*/
mitk::Color GetDecorationColor(unsigned int widgetNumber);
public Q_SLOTS:
// mouse events
virtual void mousePressEvent(QMouseEvent*) override;
virtual void moveEvent(QMoveEvent* e) override;
virtual void wheelEvent(QWheelEvent* e) override;
void Fit();
void AddDisplayPlaneSubTree();
void EnsureDisplayContainsPoint(mitk::BaseRenderer *renderer, const mitk::Point3D &p);
void SetWidgetPlaneVisibility(const char *widgetName, bool visible, mitk::BaseRenderer *renderer = nullptr);
void SetWidgetPlanesVisibility(bool visible, mitk::BaseRenderer *renderer = nullptr);
Q_SIGNALS:
void NotifyCrosshairVisibilityChanged(bool visible);
void NotifyCrosshairRotationModeChanged(int mode);
void WheelMoved(QWheelEvent *);
void Moved();
private:
virtual void SetLayoutImpl() override;
virtual void SetInteractionSchemeImpl() override { }
void CreateRenderWindowWidgets();
- mitk::SliceNavigationController* m_TimeNavigationController;
-
/**
* @brief The 3 helper objects which contain the plane geometry.
*/
mitk::DataNode::Pointer m_PlaneNode1;
mitk::DataNode::Pointer m_PlaneNode2;
mitk::DataNode::Pointer m_PlaneNode3;
/**
* @brief m_ParentNodeForGeometryPlanes This helper object is added to the datastorage
* and contains the 3 planes for displaying the image geometry (crosshair and 3D planes).
*/
mitk::DataNode::Pointer m_ParentNodeForGeometryPlanes;
/**
* @brief m_DecorationColorWidget4 color for annotation and rectangle of widget 4.
*
* For other widgets1-3, the color is a property of the respective data node.
* There is no node for widget 4, hence, we need an extra member.
*/
mitk::Color m_DecorationColorWidget4;
};
#endif
diff --git a/Modules/QtWidgets/src/QmitkMultiWidgetLayoutManager.cpp b/Modules/QtWidgets/src/QmitkMultiWidgetLayoutManager.cpp
index 0c5a1111cc..04045da5b0 100644
--- a/Modules/QtWidgets/src/QmitkMultiWidgetLayoutManager.cpp
+++ b/Modules/QtWidgets/src/QmitkMultiWidgetLayoutManager.cpp
@@ -1,541 +1,541 @@
/*============================================================================
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 "QmitkMultiWidgetLayoutManager.h"
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <QmitkAbstractMultiWidget.h>
#include <QmitkRenderWindow.h>
#include <QmitkRenderWindowWidget.h>
// qt
#include <QHBoxLayout>
#include <qsplitter.h>
QmitkMultiWidgetLayoutManager::QmitkMultiWidgetLayoutManager(QmitkAbstractMultiWidget* multiwidget)
: QObject(multiwidget)
, m_MultiWidget(multiwidget)
, m_CurrentRenderWindowWidget(nullptr)
{
// nothing here
}
void QmitkMultiWidgetLayoutManager::SetLayoutDesign(LayoutDesign layoutDesign)
{
if (nullptr == m_MultiWidget)
{
return;
}
// retrieve the render window name from the sending render window
auto renderWindow = dynamic_cast<QmitkRenderWindow*>(QObject::sender());
m_CurrentRenderWindowWidget = m_MultiWidget->GetRenderWindowWidget(renderWindow).get();
switch (layoutDesign)
{
case LayoutDesign::DEFAULT:
{
SetDefaultLayout();
break;
}
case LayoutDesign::ALL_2D_TOP_3D_BOTTOM:
{
SetAll2DTop3DBottomLayout();
break;
}
case LayoutDesign::ALL_2D_LEFT_3D_RIGHT:
{
SetAll2DLeft3DRightLayout();
break;
}
case LayoutDesign::ONE_BIG:
{
SetOneBigLayout();
break;
}
case LayoutDesign::ONLY_2D_HORIZONTAL:
{
SetOnly2DHorizontalLayout();
break;
}
case LayoutDesign::ONLY_2D_VERTICAL:
{
SetOnly2DVerticalLayout();
break;
}
case LayoutDesign::ONE_TOP_3D_BOTTOM:
{
SetOneTop3DBottomLayout();
break;
}
case LayoutDesign::ONE_LEFT_3D_RIGHT:
{
SetOneLeft3DRightLayout();
break;
}
case LayoutDesign::ALL_HORIZONTAL:
{
SetAllHorizontalLayout();
break;
}
case LayoutDesign::ALL_VERTICAL:
{
SetAllVerticalLayout();
break;
}
case LayoutDesign::REMOVE_ONE:
{
RemoveOneLayout();
break;
}
case LayoutDesign::NONE:
{
break;
}
};
}
void QmitkMultiWidgetLayoutManager::SetCurrentRenderWindowWidget(QmitkRenderWindowWidget* renderWindowWidget)
{
m_CurrentRenderWindowWidget = renderWindowWidget;
}
void QmitkMultiWidgetLayoutManager::SetDefaultLayout()
{
MITK_INFO << "Set default layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(Qt::Vertical, m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
QList<int> splitterSizeRow;
for (int row = 0; row < m_MultiWidget->GetRowCount(); ++row)
{
splitterSizeRow.push_back(1000);
QList<int> splitterSizeColumn;
auto splitter = new QSplitter(mainSplit);
for (int column = 0; column < m_MultiWidget->GetColumnCount(); ++column)
{
splitterSizeColumn.push_back(1000);
auto renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(row, column);
splitter->addWidget(renderWindowWidget.get());
renderWindowWidget->show();
}
splitter->setSizes(splitterSizeColumn);
}
mainSplit->setSizes(splitterSizeRow);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::DEFAULT);
}
}
void QmitkMultiWidgetLayoutManager::SetAll2DTop3DBottomLayout()
{
MITK_INFO << "Set all 2D top and 3D bottom layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(Qt::Vertical, m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
auto subSplit2D = new QSplitter(mainSplit);
QList<int> splitterSize;
auto all2DRenderWindowWidgets = m_MultiWidget->Get2DRenderWindowWidgets();
for (const auto& renderWindowWidget : all2DRenderWindowWidgets)
{
subSplit2D->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
subSplit2D->setSizes(splitterSize);
auto subSplit3D = new QSplitter(mainSplit);
splitterSize.clear();
auto all3DRenderWindowWidgets = m_MultiWidget->Get3DRenderWindowWidgets();
for (const auto& renderWindowWidget : all3DRenderWindowWidgets)
{
subSplit3D->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
subSplit3D->setSizes(splitterSize);
// set size for main splitter
splitterSize.clear();
splitterSize.push_back(600);
splitterSize.push_back(1000);
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ALL_2D_TOP_3D_BOTTOM);
}
}
void QmitkMultiWidgetLayoutManager::SetAll2DLeft3DRightLayout()
{
MITK_INFO << "Set all 2D left and 3D right layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
auto subSplit2D = new QSplitter(Qt::Vertical, mainSplit);
QList<int> splitterSize;
auto all2DRenderWindowWidgets = m_MultiWidget->Get2DRenderWindowWidgets();
for (const auto& renderWindowWidget : all2DRenderWindowWidgets)
{
subSplit2D->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
subSplit2D->setSizes(splitterSize);
auto subSplit3D = new QSplitter(mainSplit);
splitterSize.clear();
auto all3DRenderWindowWidgets = m_MultiWidget->Get3DRenderWindowWidgets();
for (const auto& renderWindowWidget : all3DRenderWindowWidgets)
{
subSplit3D->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
subSplit3D->setSizes(splitterSize);
// set size for main splitter
splitterSize.clear();
splitterSize.push_back(600);
splitterSize.push_back(1000);
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ALL_2D_LEFT_3D_RIGHT);
}
}
void QmitkMultiWidgetLayoutManager::SetOneBigLayout()
{
MITK_INFO << "Set single 2D layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
mainSplit->addWidget(m_CurrentRenderWindowWidget);
m_CurrentRenderWindowWidget->show();
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ONE_BIG);
}
}
void QmitkMultiWidgetLayoutManager::SetOnly2DHorizontalLayout()
{
MITK_INFO << "Set only 2D layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
QList<int> splitterSize;
auto all2DRenderWindowWidgets = m_MultiWidget->Get2DRenderWindowWidgets();
for (const auto& renderWindowWidget : all2DRenderWindowWidgets)
{
mainSplit->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ONLY_2D_HORIZONTAL);
}
}
void QmitkMultiWidgetLayoutManager::SetOnly2DVerticalLayout()
{
MITK_INFO << "Set only 2D layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(Qt::Vertical, m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
QList<int> splitterSize;
auto all2DRenderWindowWidgets = m_MultiWidget->Get2DRenderWindowWidgets();
for (const auto& renderWindowWidget : all2DRenderWindowWidgets)
{
mainSplit->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ONLY_2D_VERTICAL);
}
}
void QmitkMultiWidgetLayoutManager::SetOneTop3DBottomLayout()
{
MITK_INFO << "Set one top and all 3D bottom layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(Qt::Vertical, m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
mainSplit->addWidget(m_CurrentRenderWindowWidget);
m_CurrentRenderWindowWidget->show();
auto subSplit3D = new QSplitter(mainSplit);
QList<int> splitterSize;
auto all3DRenderWindowWidgets = m_MultiWidget->Get3DRenderWindowWidgets();
for (const auto& renderWindowWidget : all3DRenderWindowWidgets)
{
subSplit3D->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
subSplit3D->setSizes(splitterSize);
// set size for main splitter
splitterSize.clear();
splitterSize.push_back(1000);
splitterSize.push_back(1000);
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ONE_TOP_3D_BOTTOM);
}
}
void QmitkMultiWidgetLayoutManager::SetOneLeft3DRightLayout()
{
MITK_INFO << "Set one left and all 3D right layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
mainSplit->addWidget(m_CurrentRenderWindowWidget);
m_CurrentRenderWindowWidget->show();
auto subSplit3D = new QSplitter(Qt::Vertical, mainSplit);
QList<int> splitterSize;
auto all3DRenderWindowWidgets = m_MultiWidget->Get3DRenderWindowWidgets();
for (const auto& renderWindowWidget : all3DRenderWindowWidgets)
{
subSplit3D->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
subSplit3D->setSizes(splitterSize);
// set size for main splitter
splitterSize.clear();
splitterSize.push_back(1000);
splitterSize.push_back(1000);
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ONE_LEFT_3D_RIGHT);
}
}
void QmitkMultiWidgetLayoutManager::SetAllHorizontalLayout()
{
MITK_INFO << "Set default layout" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
QList<int> splitterSize;
auto allRenderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets();
for (const auto& renderWindowWidget : allRenderWindowWidgets)
{
if (nullptr != renderWindowWidget.second)
{
mainSplit->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
}
// set size for main splitter
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ALL_HORIZONTAL);
}
}
void QmitkMultiWidgetLayoutManager::SetAllVerticalLayout()
{
MITK_INFO << "Set all vertical" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
delete m_MultiWidget->layout();
auto hBoxLayout = new QHBoxLayout(m_MultiWidget);
hBoxLayout->setContentsMargins(0, 0, 0, 0);
m_MultiWidget->setLayout(hBoxLayout);
hBoxLayout->setMargin(0);
auto mainSplit = new QSplitter(Qt::Vertical, m_MultiWidget);
hBoxLayout->addWidget(mainSplit);
QList<int> splitterSize;
auto allRenderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets();
for (const auto& renderWindowWidget : allRenderWindowWidgets)
{
mainSplit->addWidget(renderWindowWidget.second.get());
renderWindowWidget.second->show();
splitterSize.push_back(1000);
}
// set size for splitter
mainSplit->setSizes(splitterSize);
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::ALL_VERTICAL);
}
}
void QmitkMultiWidgetLayoutManager::RemoveOneLayout()
{
MITK_INFO << "Remove single render window" << std::endl;
m_MultiWidget->ActivateMenuWidget(false);
m_CurrentRenderWindowWidget->hide();
m_MultiWidget->ActivateMenuWidget(true);
auto allRenderWindows = m_MultiWidget->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
renderWindow->UpdateLayoutDesignList(LayoutDesign::NONE);
}
}
diff --git a/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp b/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp
index 0578c2e0d5..1f80c59170 100644
--- a/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp
+++ b/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp
@@ -1,134 +1,138 @@
/*============================================================================
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 "QmitkMultiWidgetLayoutSelectionWidget.h"
#include <QFileDialog>
#include <usGetModuleContext.h>
#include <usModuleContext.h>
#include <usModuleResource.h>
#include <usModuleResourceStream.h>
QmitkMultiWidgetLayoutSelectionWidget::QmitkMultiWidgetLayoutSelectionWidget(QWidget* parent/* = 0*/)
: QWidget(parent)
{
Init();
}
void QmitkMultiWidgetLayoutSelectionWidget::Init()
{
ui.setupUi(this);
auto stylesheet = "QTableWidget::item{background-color: white;}\nQTableWidget::item:selected{background-color: #1C97EA;}";
ui.tableWidget->setStyleSheet(stylesheet);
connect(ui.tableWidget, &QTableWidget::itemSelectionChanged, this, &QmitkMultiWidgetLayoutSelectionWidget::OnTableItemSelectionChanged);
connect(ui.setLayoutPushButton, &QPushButton::clicked, this, &QmitkMultiWidgetLayoutSelectionWidget::OnSetLayoutButtonClicked);
connect(ui.loadLayoutPushButton, &QPushButton::clicked, this, &QmitkMultiWidgetLayoutSelectionWidget::OnLoadLayoutButtonClicked);
connect(ui.saveLayoutPushButton, &QPushButton::clicked, this, &QmitkMultiWidgetLayoutSelectionWidget::OnSaveLayoutButtonClicked);
connect(ui.selectDefaultLayoutComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QmitkMultiWidgetLayoutSelectionWidget::OnLayoutPresetSelected);
ui.selectDefaultLayoutComboBox->addItem("Select a layout preset");
auto presetResources = us::GetModuleContext()->GetModule()->FindResources("/", "mxnLayout_*.json", false);
for (const auto& resource : presetResources)
{
us::ModuleResourceStream jsonStream(resource);
auto data = nlohmann::json::parse(jsonStream);
auto resourceName = data["name"].get<std::string>();
ui.selectDefaultLayoutComboBox->addItem(QString::fromStdString(resourceName));
m_PresetMap[ui.selectDefaultLayoutComboBox->count() - 1] = data;
}
}
void QmitkMultiWidgetLayoutSelectionWidget::OnTableItemSelectionChanged()
{
QItemSelectionModel* selectionModel = ui.tableWidget->selectionModel();
int row = 0;
int column = 0;
QModelIndexList indices = selectionModel->selectedIndexes();
if (indices.size() > 0)
{
row = indices[0].row();
column = indices[0].column();
QModelIndex topLeft = ui.tableWidget->model()->index(0, 0, QModelIndex());
QModelIndex bottomRight = ui.tableWidget->model()->index(row, column, QModelIndex());
QItemSelection cellSelection;
cellSelection.select(topLeft, bottomRight);
selectionModel->select(cellSelection, QItemSelectionModel::Select);
}
}
void QmitkMultiWidgetLayoutSelectionWidget::OnSetLayoutButtonClicked()
{
int row = 0;
int column = 0;
QModelIndexList indices = ui.tableWidget->selectionModel()->selectedIndexes();
if (indices.size() > 0)
{
// find largest row and column
for (const auto& modelIndex : qAsConst(indices))
{
if (modelIndex.row() > row)
{
row = modelIndex.row();
}
if (modelIndex.column() > column)
{
column = modelIndex.column();
}
}
close();
emit LayoutSet(row+1, column+1);
}
ui.selectDefaultLayoutComboBox->setCurrentIndex(0);
}
void QmitkMultiWidgetLayoutSelectionWidget::OnSaveLayoutButtonClicked()
{
QString filename = QFileDialog::getSaveFileName(nullptr, "Select where to save the current layout", "", "MITK Window Layout (*.json)");
if (filename.isEmpty())
return;
+ QString fileExt(".json");
+ if (!filename.endsWith(fileExt))
+ filename += fileExt;
+
auto outStream = std::ofstream(filename.toStdString());
emit SaveLayout(&outStream);
}
void QmitkMultiWidgetLayoutSelectionWidget::OnLoadLayoutButtonClicked()
{
QString filename = QFileDialog::getOpenFileName(nullptr, "Load a layout file", "", "MITK Window Layouts (*.json)");
if (filename.isEmpty())
return;
ui.selectDefaultLayoutComboBox->setCurrentIndex(0);
std::ifstream f(filename.toStdString());
auto jsonData = nlohmann::json::parse(f);
emit LoadLayout(&jsonData);
}
void QmitkMultiWidgetLayoutSelectionWidget::OnLayoutPresetSelected(int index)
{
if (index == 0)
{
// First entry is only for description
return;
}
auto jsonData = m_PresetMap[index];
close();
emit LoadLayout(&jsonData);
}
diff --git a/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp b/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp
index 40ac5e11a1..55c15a1c4e 100644
--- a/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp
+++ b/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp
@@ -1,633 +1,600 @@
/*============================================================================
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 "QmitkMxNMultiWidget.h"
// mitk core
#include <mitkDisplayActionEventFunctions.h>
#include <mitkDisplayActionEventHandlerDesynchronized.h>
#include <mitkDisplayActionEventHandlerSynchronized.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateProperty.h>
// mitk qt widget
#include <QmitkRenderWindowUtilityWidget.h>
#include <QmitkRenderWindowWidget.h>
// qt
#include <QGridLayout>
#include <QMessageBox>
#include <QSplitter>
#include <fstream>
QmitkMxNMultiWidget::QmitkMxNMultiWidget(QWidget* parent,
Qt::WindowFlags f/* = 0*/,
const QString& multiWidgetName/* = "mxn"*/)
: QmitkAbstractMultiWidget(parent, f, multiWidgetName)
- , m_TimeNavigationController(nullptr)
, m_SynchronizedWidgetConnector(std::make_unique<QmitkSynchronizedWidgetConnector>())
, m_CrosshairVisibility(false)
{
- m_TimeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
}
QmitkMxNMultiWidget::~QmitkMxNMultiWidget()
{
- auto allRenderWindows = this->GetRenderWindows();
- for (auto& renderWindow : allRenderWindows)
- {
- m_TimeNavigationController->Disconnect(renderWindow->GetSliceNavigationController());
- }
}
void QmitkMxNMultiWidget::InitializeMultiWidget()
{
SetLayout(1, 1);
SetDisplayActionEventHandler(std::make_unique<mitk::DisplayActionEventHandlerDesynchronized>());
auto displayActionEventHandler = GetDisplayActionEventHandler();
if (nullptr != displayActionEventHandler)
{
displayActionEventHandler->InitActions();
}
this->SetInitialSelection();
}
void QmitkMxNMultiWidget::Synchronize(bool synchronized)
{
if (synchronized)
{
SetDisplayActionEventHandler(std::make_unique<mitk::DisplayActionEventHandlerSynchronized>());
}
else
{
SetDisplayActionEventHandler(std::make_unique<mitk::DisplayActionEventHandlerDesynchronized>());
}
auto displayActionEventHandler = GetDisplayActionEventHandler();
if (nullptr != displayActionEventHandler)
{
displayActionEventHandler->InitActions();
}
}
QmitkRenderWindow* QmitkMxNMultiWidget::GetRenderWindow(const QString& widgetName) const
{
if ("axial" == widgetName || "sagittal" == widgetName || "coronal" == widgetName || "3d" == widgetName)
{
return GetActiveRenderWindowWidget()->GetRenderWindow();
}
return QmitkAbstractMultiWidget::GetRenderWindow(widgetName);
}
QmitkRenderWindow* QmitkMxNMultiWidget::GetRenderWindow(const mitk::AnatomicalPlane& /*orientation*/) const
{
// currently no mapping between plane orientation and render windows
// simply return the currently active render window
return GetActiveRenderWindowWidget()->GetRenderWindow();
}
void QmitkMxNMultiWidget::SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget)
{
auto currentActiveRenderWindowWidget = GetActiveRenderWindowWidget();
if (currentActiveRenderWindowWidget == activeRenderWindowWidget)
{
return;
}
// reset the decoration color of the previously active render window widget
if (nullptr != currentActiveRenderWindowWidget)
{
auto decorationColor = currentActiveRenderWindowWidget->GetDecorationColor();
QColor hexColor(decorationColor[0] * 255, decorationColor[1] * 255, decorationColor[2] * 255);
currentActiveRenderWindowWidget->setStyleSheet("QmitkRenderWindowWidget { border: 2px solid " +
hexColor.name(QColor::HexRgb) + "; }");
}
// set the new decoration color of the currently active render window widget
if (nullptr != activeRenderWindowWidget)
{
activeRenderWindowWidget->setStyleSheet("QmitkRenderWindowWidget { border: 2px solid #FF6464; }");
}
QmitkAbstractMultiWidget::SetActiveRenderWindowWidget(activeRenderWindowWidget);
}
void QmitkMxNMultiWidget::InitializeViews(const mitk::TimeGeometry* geometry, bool resetCamera)
{
auto* renderingManager = mitk::RenderingManager::GetInstance();
mitk::Point3D currentPosition = mitk::Point3D();
unsigned int imageTimeStep = 0;
if (!resetCamera)
{
// store the current position to set it again later, if the camera should not be reset
currentPosition = this->GetSelectedPosition("");
// store the current time step to set it again later, if the camera should not be reset
- const auto currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
+ const mitk::TimePointType currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
if (geometry->IsValidTimePoint(currentTimePoint))
{
imageTimeStep = geometry->TimePointToTimeStep(currentTimePoint);
}
}
// initialize active render window
renderingManager->InitializeView(
this->GetActiveRenderWindowWidget()->GetRenderWindow()->GetVtkRenderWindow(), geometry, resetCamera);
if (!resetCamera)
{
this->SetSelectedPosition(currentPosition, "");
- renderingManager->GetTimeNavigationController()->GetTime()->SetPos(imageTimeStep);
+ renderingManager->GetTimeNavigationController()->GetStepper()->SetPos(imageTimeStep);
}
}
void QmitkMxNMultiWidget::SetInteractionReferenceGeometry(const mitk::TimeGeometry* referenceGeometry)
{
// Set the interaction reference referenceGeometry for all render windows.
auto allRenderWindows = this->GetRenderWindows();
for (auto& renderWindow : allRenderWindows)
{
- auto* baseRenderer = mitk::BaseRenderer::GetInstance(renderWindow->GetRenderWindow());
+ auto* baseRenderer = mitk::BaseRenderer::GetInstance(renderWindow->GetVtkRenderWindow());
baseRenderer->SetInteractionReferenceGeometry(referenceGeometry);
}
}
bool QmitkMxNMultiWidget::HasCoupledRenderWindows() const
{
return false;
}
void QmitkMxNMultiWidget::SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName)
{
RenderWindowWidgetPointer renderWindowWidget;
if (widgetName.isNull() || widgetName.isEmpty())
{
renderWindowWidget = GetActiveRenderWindowWidget();
}
else
{
renderWindowWidget = GetRenderWindowWidget(widgetName);
}
if (nullptr != renderWindowWidget)
{
renderWindowWidget->GetSliceNavigationController()->SelectSliceByPoint(newPosition);
return;
}
MITK_ERROR << "Position can not be set for an unknown render window widget.";
}
const mitk::Point3D QmitkMxNMultiWidget::GetSelectedPosition(const QString& widgetName) const
{
RenderWindowWidgetPointer renderWindowWidget;
if (widgetName.isNull() || widgetName.isEmpty())
{
renderWindowWidget = GetActiveRenderWindowWidget();
}
else
{
renderWindowWidget = GetRenderWindowWidget(widgetName);
}
if (nullptr != renderWindowWidget)
{
return renderWindowWidget->GetCrosshairPosition();
}
MITK_ERROR << "Crosshair position can not be retrieved.";
return mitk::Point3D(0.0);
}
void QmitkMxNMultiWidget::SetCrosshairVisibility(bool visible)
{
// get the specific render window that sent the signal
QmitkRenderWindow* renderWindow = qobject_cast<QmitkRenderWindow*>(sender());
if (nullptr == renderWindow)
{
return;
}
auto renderWindowWidget = this->GetRenderWindowWidget(renderWindow);
renderWindowWidget->SetCrosshairVisibility(visible);
}
bool QmitkMxNMultiWidget::GetCrosshairVisibility() const
{
// get the specific render window that sent the signal
QmitkRenderWindow* renderWindow = qobject_cast<QmitkRenderWindow*>(sender());
if (nullptr == renderWindow)
{
return false;
}
auto renderWindowWidget = this->GetRenderWindowWidget(renderWindow);
return renderWindowWidget->GetCrosshairVisibility();
}
void QmitkMxNMultiWidget::SetCrosshairGap(unsigned int gapSize)
{
auto renderWindowWidgets = this->GetRenderWindowWidgets();
for (const auto& renderWindowWidget : renderWindowWidgets)
{
renderWindowWidget.second->SetCrosshairGap(gapSize);
}
}
void QmitkMxNMultiWidget::ResetCrosshair()
{
auto dataStorage = GetDataStorage();
if (nullptr == dataStorage)
{
return;
}
// get the specific render window that sent the signal
QmitkRenderWindow* renderWindow = qobject_cast<QmitkRenderWindow*>(sender());
if (nullptr == renderWindow)
{
return;
}
- mitk::RenderingManager::GetInstance()->InitializeViewByBoundingObjects(renderWindow->GetRenderWindow(), dataStorage);
+ mitk::RenderingManager::GetInstance()->InitializeViewByBoundingObjects(renderWindow->GetVtkRenderWindow(), dataStorage);
SetWidgetPlaneMode(mitk::InteractionSchemeSwitcher::MITKStandard);
}
void QmitkMxNMultiWidget::SetWidgetPlaneMode(int userMode)
{
MITK_DEBUG << "Changing crosshair mode to " << userMode;
switch (userMode)
{
case 0:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKStandard);
break;
case 1:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKRotationUncoupled);
break;
case 2:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKRotationCoupled);
break;
case 3:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKSwivel);
break;
}
}
-mitk::SliceNavigationController* QmitkMxNMultiWidget::GetTimeNavigationController()
-{
- return m_TimeNavigationController;
-}
-
void QmitkMxNMultiWidget::EnableCrosshair()
{
auto renderWindowWidgets = this->GetRenderWindowWidgets();
for (const auto& renderWindowWidget : renderWindowWidgets)
{
renderWindowWidget.second->EnableCrosshair();
}
}
void QmitkMxNMultiWidget::DisableCrosshair()
{
auto renderWindowWidgets = this->GetRenderWindowWidgets();
for (const auto& renderWindowWidget : renderWindowWidgets)
{
renderWindowWidget.second->DisableCrosshair();
}
}
//////////////////////////////////////////////////////////////////////////
// PUBLIC SLOTS
// MOUSE EVENTS
//////////////////////////////////////////////////////////////////////////
void QmitkMxNMultiWidget::wheelEvent(QWheelEvent* e)
{
emit WheelMoved(e);
}
void QmitkMxNMultiWidget::mousePressEvent(QMouseEvent*)
{
// nothing here, but necessary for mouse interactions (.xml-configuration files)
}
void QmitkMxNMultiWidget::moveEvent(QMoveEvent* e)
{
QWidget::moveEvent(e);
// it is necessary to readjust the position of the overlays as the MultiWidget has moved
// unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here
emit Moved();
}
-void QmitkMxNMultiWidget::RemoveRenderWindowWidget()
-{
- auto renderWindowWidgets = this->GetRenderWindowWidgets();
- auto iterator = renderWindowWidgets.find(this->GetNameFromIndex(this->GetNumberOfRenderWindowWidgets() - 1));
- if (iterator == renderWindowWidgets.end())
- {
- return;
- }
-
- // disconnect each signal of this render window widget
- RenderWindowWidgetPointer renderWindowWidgetToRemove = iterator->second;
- m_TimeNavigationController->Disconnect(renderWindowWidgetToRemove->GetSliceNavigationController());
-
- QmitkAbstractMultiWidget::RemoveRenderWindowWidget();
-}
-
//////////////////////////////////////////////////////////////////////////
// PRIVATE
//////////////////////////////////////////////////////////////////////////
void QmitkMxNMultiWidget::SetLayoutImpl()
{
int requiredRenderWindowWidgets = GetRowCount() * GetColumnCount();
int existingRenderWindowWidgets = GetRenderWindowWidgets().size();
int difference = requiredRenderWindowWidgets - existingRenderWindowWidgets;
while (0 < difference)
{
// more render window widgets needed
CreateRenderWindowWidget();
--difference;
}
while (0 > difference)
{
// less render window widgets needed
RemoveRenderWindowWidget();
++difference;
}
auto firstRenderWindowWidget = GetFirstRenderWindowWidget();
if (nullptr != firstRenderWindowWidget)
{
SetActiveRenderWindowWidget(firstRenderWindowWidget);
}
GetMultiWidgetLayoutManager()->SetLayoutDesign(QmitkMultiWidgetLayoutManager::LayoutDesign::DEFAULT);
}
QmitkAbstractMultiWidget::RenderWindowWidgetPointer QmitkMxNMultiWidget::CreateRenderWindowWidget()
{
// create the render window widget and connect signal / slot
QString renderWindowWidgetName = GetNameFromIndex(GetNumberOfRenderWindowWidgets());
RenderWindowWidgetPointer renderWindowWidget = std::make_shared<QmitkRenderWindowWidget>(this, renderWindowWidgetName, GetDataStorage());
renderWindowWidget->SetCornerAnnotationText(renderWindowWidgetName.toStdString());
AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget);
auto renderWindow = renderWindowWidget->GetRenderWindow();
QmitkRenderWindowUtilityWidget* utilityWidget = new QmitkRenderWindowUtilityWidget(this, renderWindow, GetDataStorage());
renderWindowWidget->AddUtilityWidget(utilityWidget);
connect(utilityWidget, &QmitkRenderWindowUtilityWidget::SynchronizationToggled,
this, &QmitkMxNMultiWidget::ToggleSynchronization);
connect(this, &QmitkMxNMultiWidget::UpdateUtilityWidgetViewPlanes,
utilityWidget, &QmitkRenderWindowUtilityWidget::UpdateViewPlaneSelection);
// needs to be done after 'QmitkRenderWindowUtilityWidget::ToggleSynchronization' has been connected
// initially synchronize the node selection widget
utilityWidget->ToggleSynchronization(true);
auto layoutManager = GetMultiWidgetLayoutManager();
connect(renderWindow, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign);
connect(renderWindow, &QmitkRenderWindow::ResetView, this, &QmitkMxNMultiWidget::ResetCrosshair);
connect(renderWindow, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkMxNMultiWidget::SetCrosshairVisibility);
connect(renderWindow, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkMxNMultiWidget::SetWidgetPlaneMode);
- // connect time navigation controller to react on referenceGeometry time events with the render window's slice naviation controller
- m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow->GetSliceNavigationController());
- // reverse connection between the render window's slice navigation controller and the time navigation controller
- renderWindow->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
-
return renderWindowWidget;
}
void QmitkMxNMultiWidget::LoadLayout(const nlohmann::json* jsonData)
{
if ((*jsonData).is_null())
{
QMessageBox::warning(this, "Load layout", "Could not read window layout");
return;
}
unsigned int windowCounter = 0;
try
{
auto version = jsonData->at("version").get<std::string>();
if (version != "1.0")
{
QMessageBox::warning(this, "Load layout", "Unknown layout version, could not load");
return;
}
delete this->layout();
auto content = BuildLayoutFromJSON(jsonData, &windowCounter);
auto hBoxLayout = new QHBoxLayout(this);
this->setLayout(hBoxLayout);
hBoxLayout->addWidget(content);
emit UpdateUtilityWidgetViewPlanes();
}
catch (nlohmann::json::out_of_range& e)
{
MITK_ERROR << "Error in loading window layout from JSON: " << e.what();
return;
}
while (GetNumberOfRenderWindowWidgets() > windowCounter)
{
RemoveRenderWindowWidget();
}
EnableCrosshair();
emit LayoutChanged();
}
void QmitkMxNMultiWidget::SaveLayout(std::ostream* outStream)
{
if (outStream == nullptr)
{
return;
}
auto layout = this->layout();
if (layout == nullptr)
return;
// There should only ever be one item: a splitter
auto widget = layout->itemAt(0)->widget();
auto splitter = dynamic_cast<QSplitter*>(widget);
if (!splitter)
{
MITK_ERROR << "Tried to save unexpected layout format. Make sure the layout of this instance contains a single QSplitter.";
return;
}
auto layoutJSON = BuildJSONFromLayout(splitter);
layoutJSON["version"] = "1.0";
layoutJSON["name"] = "Custom Layout";
*outStream << std::setw(4) << layoutJSON << std::endl;
}
nlohmann::json QmitkMxNMultiWidget::BuildJSONFromLayout(const QSplitter* splitter)
{
nlohmann::json resultJSON;
resultJSON["isWindow"] = false;
resultJSON["vertical"] = (splitter->orientation() == Qt::Vertical) ? true : false;
auto sizes = splitter->sizes();
auto content = nlohmann::json::array();
auto countSplitter = splitter->count();
for (int i = 0; i < countSplitter; ++i)
{
auto widget = splitter->widget(i);
nlohmann::json widgetJSON;
if (auto widgetSplitter = dynamic_cast<QSplitter*>(widget); widgetSplitter)
{
widgetJSON = BuildJSONFromLayout(widgetSplitter);
}
else if (auto widgetWindow = dynamic_cast<QmitkRenderWindowWidget*>(widget); widgetWindow)
{
widgetJSON["isWindow"] = true;
widgetJSON["viewDirection"] = widgetWindow->GetSliceNavigationController()->GetViewDirectionAsString();
}
widgetJSON["size"] = sizes[i];
content.push_back(widgetJSON);
}
resultJSON["content"] = content;
return resultJSON;
}
QSplitter* QmitkMxNMultiWidget::BuildLayoutFromJSON(const nlohmann::json* jsonData, unsigned int* windowCounter, QSplitter* parentSplitter)
{
bool vertical = jsonData->at("vertical").get<bool>();
auto orientation = vertical ? Qt::Vertical : Qt::Horizontal;
auto split = new QSplitter(orientation, parentSplitter);
QList<int> sizes;
for (auto object : jsonData->at("content"))
{
bool isWindow = object["isWindow"].get<bool>();
int size = object["size"].get<int>();
sizes.append(size);
if (isWindow)
{
auto viewDirection = object["viewDirection"].get<std::string>();
mitk::AnatomicalPlane viewPlane = mitk::AnatomicalPlane::Sagittal;
if (viewDirection == "Axial")
{
viewPlane = mitk::AnatomicalPlane::Axial;
}
else if (viewDirection == "Coronal")
{
viewPlane = mitk::AnatomicalPlane::Coronal;
}
else if (viewDirection == "Original")
{
viewPlane = mitk::AnatomicalPlane::Original;
}
else if (viewDirection == "Sagittal")
{
viewPlane = mitk::AnatomicalPlane::Sagittal;
}
QmitkAbstractMultiWidget::RenderWindowWidgetPointer window = nullptr;
QString renderWindowName;
QmitkAbstractMultiWidget::RenderWindowWidgetMap::iterator it;
// repurpose existing render windows as far as they already exist
if (*windowCounter < GetRenderWindowWidgets().size())
{
renderWindowName = this->GetNameFromIndex(*windowCounter);
auto renderWindowWidgets = GetRenderWindowWidgets();
it = renderWindowWidgets.find(renderWindowName);
if (it != renderWindowWidgets.end())
{
window = it->second;
}
else
{
MITK_ERROR << "Could not find render window " << renderWindowName.toStdString() << ", although it should be there.";
}
}
if (window == nullptr)
{
window = CreateRenderWindowWidget();
}
window->GetSliceNavigationController()->SetDefaultViewDirection(viewPlane);
window->GetSliceNavigationController()->Update();
split->addWidget(window.get());
window->show();
(*windowCounter)++;
}
else
{
auto subSplitter = BuildLayoutFromJSON(&object, windowCounter, split);
split->addWidget(subSplitter);
}
}
split->setSizes(sizes);
return split;
}
void QmitkMxNMultiWidget::SetInitialSelection()
{
auto dataStorage = this->GetDataStorage();
if (nullptr == dataStorage)
{
return;
}
mitk::NodePredicateAnd::Pointer noHelperObjects = mitk::NodePredicateAnd::New();
noHelperObjects->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
noHelperObjects->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
auto allNodes = dataStorage->GetSubset(noHelperObjects);
QmitkSynchronizedNodeSelectionWidget::NodeList currentSelection;
for (auto& node : *allNodes)
{
currentSelection.append(node);
}
m_SynchronizedWidgetConnector->ChangeSelection(currentSelection);
}
void QmitkMxNMultiWidget::ToggleSynchronization(QmitkSynchronizedNodeSelectionWidget* synchronizedWidget)
{
bool synchronized = synchronizedWidget->IsSynchronized();
if (synchronized)
{
m_SynchronizedWidgetConnector->ConnectWidget(synchronizedWidget);
m_SynchronizedWidgetConnector->SynchronizeWidget(synchronizedWidget);
}
else
{
m_SynchronizedWidgetConnector->DisconnectWidget(synchronizedWidget);
}
}
diff --git a/Modules/QtWidgets/src/QmitkRenderWindow.cpp b/Modules/QtWidgets/src/QmitkRenderWindow.cpp
index df1eb86c11..601981ce79 100644
--- a/Modules/QtWidgets/src/QmitkRenderWindow.cpp
+++ b/Modules/QtWidgets/src/QmitkRenderWindow.cpp
@@ -1,517 +1,515 @@
/*============================================================================
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 "QmitkRenderWindow.h"
#include "mitkInteractionKeyEvent.h"
#include "mitkInternalEvent.h"
#include "mitkMouseDoubleClickEvent.h"
#include "mitkMouseMoveEvent.h"
#include "mitkMousePressEvent.h"
#include "mitkMouseReleaseEvent.h"
#include "mitkMouseWheelEvent.h"
#include <mitkStatusBar.h>
#include <QCursor>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QResizeEvent>
#include <QSurfaceFormat>
#include <QTimer>
#include <QWheelEvent>
#include <QWindow>
-#include <QApplication>
-#include <QDesktopWidget>
#include <QmitkMimeTypes.h>
#include <QmitkRenderWindowMenu.h>
#include <QmitkStyleManager.h>
QmitkRenderWindow::QmitkRenderWindow(QWidget *parent, const QString &name, mitk::VtkPropRenderer *)
: QVTKOpenGLNativeWidget(parent)
, m_ResendQtEvents(true)
, m_MenuWidget(nullptr)
, m_MenuWidgetActivated(false)
, m_LayoutIndex(QmitkRenderWindowMenu::LayoutIndex::Axial)
, m_GeometryViolationWarningOverlay(nullptr)
{
m_InternalRenderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
m_InternalRenderWindow->SetMultiSamples(0);
m_InternalRenderWindow->SetAlphaBitPlanes(0);
setRenderWindow(m_InternalRenderWindow);
Initialize(name.toStdString().c_str());
setFocusPolicy(Qt::StrongFocus);
setMouseTracking(true);
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setSizePolicy(sizePolicy);
// setup overlay widget to show a warning message with a button
m_GeometryViolationWarningOverlay = new QmitkButtonOverlayWidget(this);
m_GeometryViolationWarningOverlay->setVisible(false);
m_GeometryViolationWarningOverlay->SetOverlayText(
QStringLiteral("<font color=\"red\"><p style=\"text-align:center\">Interaction is not possible because the "
"render window geometry<br>does not match the interaction reference geometry.</p></center></font>"));
m_GeometryViolationWarningOverlay->SetButtonText("Reset geometry");
m_GeometryViolationWarningOverlay->SetButtonIcon(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/reset.svg")));
connect(m_GeometryViolationWarningOverlay, &QmitkButtonOverlayWidget::Clicked,
this, &QmitkRenderWindow::ResetGeometry);
}
QmitkRenderWindow::~QmitkRenderWindow()
{
Destroy(); // Destroy mitkRenderWindowBase
}
void QmitkRenderWindow::SetResendQtEvents(bool resend)
{
m_ResendQtEvents = resend;
}
void QmitkRenderWindow::SetLayoutIndex(QmitkRenderWindowMenu::LayoutIndex layoutIndex)
{
m_LayoutIndex = layoutIndex;
if (nullptr != m_MenuWidget)
{
m_MenuWidget->SetLayoutIndex(layoutIndex);
}
}
QmitkRenderWindowMenu::LayoutIndex QmitkRenderWindow::GetLayoutIndex()
{
if (nullptr != m_MenuWidget)
{
return m_MenuWidget->GetLayoutIndex();
}
else
{
return QmitkRenderWindowMenu::LayoutIndex::Axial;
}
}
void QmitkRenderWindow::UpdateLayoutDesignList(QmitkRenderWindowMenu::LayoutDesign layoutDesign)
{
if (nullptr != m_MenuWidget)
{
m_MenuWidget->UpdateLayoutDesignList(layoutDesign);
}
}
void QmitkRenderWindow::UpdateCrosshairVisibility(bool visible)
{
m_MenuWidget->UpdateCrosshairVisibility(visible);
}
void QmitkRenderWindow::UpdateCrosshairRotationMode(int mode)
{
m_MenuWidget->UpdateCrosshairRotationMode(mode);
}
void QmitkRenderWindow::ActivateMenuWidget(bool state)
{
if (nullptr == m_MenuWidget)
{
m_MenuWidget = new QmitkRenderWindowMenu(this, nullptr, m_Renderer);
m_MenuWidget->SetLayoutIndex(m_LayoutIndex);
}
if (m_MenuWidgetActivated == state)
{
// no new state; nothing to do
return;
}
m_MenuWidgetActivated = state;
if (m_MenuWidgetActivated)
{
connect(m_MenuWidget, &QmitkRenderWindowMenu::LayoutDesignChanged, this, &QmitkRenderWindow::LayoutDesignChanged);
connect(m_MenuWidget, &QmitkRenderWindowMenu::ResetView, this, &QmitkRenderWindow::ResetView);
connect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairVisibilityChanged, this, &QmitkRenderWindow::CrosshairVisibilityChanged);
connect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairRotationModeChanged, this, &QmitkRenderWindow::CrosshairRotationModeChanged);
}
else
{
disconnect(m_MenuWidget, &QmitkRenderWindowMenu::LayoutDesignChanged, this, &QmitkRenderWindow::LayoutDesignChanged);
disconnect(m_MenuWidget, &QmitkRenderWindowMenu::ResetView, this, &QmitkRenderWindow::ResetView);
disconnect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairVisibilityChanged, this, &QmitkRenderWindow::CrosshairVisibilityChanged);
disconnect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairRotationModeChanged, this, &QmitkRenderWindow::CrosshairRotationModeChanged);
m_MenuWidget->hide();
}
}
void QmitkRenderWindow::ShowOverlayMessage(bool show)
{
m_GeometryViolationWarningOverlay->setVisible(show);
}
void QmitkRenderWindow::moveEvent(QMoveEvent *event)
{
QVTKOpenGLNativeWidget::moveEvent(event);
// after a move the overlays need to be positioned
emit moved();
}
void QmitkRenderWindow::showEvent(QShowEvent *event)
{
QVTKOpenGLNativeWidget::showEvent(event);
// this singleshot is necessary to have the overlays positioned correctly after initial show
// simple call of moved() is no use here!!
QTimer::singleShot(0, this, SIGNAL(moved()));
}
bool QmitkRenderWindow::event(QEvent* e)
{
mitk::InteractionEvent::Pointer mitkEvent = nullptr;
mitk::Point2D mousePosition;
bool updateStatusBar = false;
switch (e->type())
{
case QEvent::MouseMove:
{
auto me = static_cast<QMouseEvent *>(e);
mousePosition = this->GetMousePosition(me);
mitkEvent = mitk::MouseMoveEvent::New(m_Renderer, mousePosition, GetButtonState(me), GetModifiers(me));
updateStatusBar = true;
break;
}
case QEvent::MouseButtonPress:
{
auto me = static_cast<QMouseEvent *>(e);
mitkEvent = mitk::MousePressEvent::New( m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me));
break;
}
case QEvent::MouseButtonRelease:
{
auto me = static_cast<QMouseEvent *>(e);
mitkEvent = mitk::MouseReleaseEvent::New( m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me));
break;
}
case QEvent::MouseButtonDblClick:
{
auto me = static_cast<QMouseEvent *>(e);
mitkEvent = mitk::MouseDoubleClickEvent::New( m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me));
break;
}
case QEvent::Wheel:
{
auto we = static_cast<QWheelEvent *>(e);
mousePosition = this->GetMousePosition(we);
mitkEvent = mitk::MouseWheelEvent::New(m_Renderer, mousePosition, GetButtonState(we), GetModifiers(we), GetDelta(we));
updateStatusBar = true;
break;
}
case QEvent::KeyPress:
{
auto ke = static_cast<QKeyEvent*>(e);
mitkEvent = mitk::InteractionKeyEvent::New(m_Renderer, GetKeyLetter(ke), GetModifiers(ke));
break;
}
case QEvent::Resize:
{
if (nullptr != m_MenuWidget)
m_MenuWidget->MoveWidgetToCorrectPos();
}
default:
{
break;
}
}
if (mitkEvent != nullptr)
{
if (this->HandleEvent(mitkEvent.GetPointer())) {
return m_ResendQtEvents ? false : true;
}
}
if (updateStatusBar)
{
this->UpdateStatusBar(mousePosition);
}
return QVTKOpenGLNativeWidget::event(e);
}
void QmitkRenderWindow::enterEvent(QEvent *e)
{
- auto* baseRenderer = mitk::BaseRenderer::GetInstance(this->GetRenderWindow());
+ auto* baseRenderer = mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow());
this->ShowOverlayMessage(!baseRenderer->GetReferenceGeometryAligned());
if (nullptr != m_MenuWidget)
m_MenuWidget->ShowMenu();
QVTKOpenGLNativeWidget::enterEvent(e);
}
void QmitkRenderWindow::leaveEvent(QEvent *e)
{
auto statusBar = mitk::StatusBar::GetInstance();
statusBar->DisplayGreyValueText("");
this->ShowOverlayMessage(false);
if (nullptr != m_MenuWidget)
m_MenuWidget->HideMenu();
QVTKOpenGLNativeWidget::leaveEvent(e);
}
void QmitkRenderWindow::resizeGL(int w, int h)
{
QVTKOpenGLNativeWidget::resizeGL(w, h);
mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(renderWindow());
}
void QmitkRenderWindow::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("application/x-mitk-datanodes"))
{
event->accept();
}
}
void QmitkRenderWindow::dropEvent(QDropEvent *event)
{
QList<mitk::DataNode *> dataNodeList = QmitkMimeTypes::ToDataNodePtrList(event->mimeData());
if (!dataNodeList.empty())
{
emit NodesDropped(this, dataNodeList.toVector().toStdVector());
}
}
void QmitkRenderWindow::DeferredHideMenu()
{
MITK_DEBUG << "QmitkRenderWindow::DeferredHideMenu";
if (nullptr != m_MenuWidget)
{
m_MenuWidget->HideMenu();
}
}
mitk::Point2D QmitkRenderWindow::GetMousePosition(QMouseEvent *me) const
{
mitk::Point2D point;
- const auto scale = QApplication::desktop()->devicePixelRatio();
+ const auto scale = this->devicePixelRatioF();
point[0] = me->x()*scale;
// We need to convert the y component, as the display and vtk have other definitions for the y direction
point[1] = m_Renderer->GetSizeY() - me->y()*scale;
return point;
}
mitk::Point2D QmitkRenderWindow::GetMousePosition(QWheelEvent *we) const
{
mitk::Point2D point;
- const auto scale = QApplication::desktop()->devicePixelRatio();
+ const auto scale = this->devicePixelRatioF();
point[0] = we->x()*scale;
// We need to convert the y component, as the display and vtk have other definitions for the y direction
point[1] = m_Renderer->GetSizeY() - we->y()*scale;
return point;
}
mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetEventButton(QMouseEvent *me) const
{
mitk::InteractionEvent::MouseButtons eventButton;
switch (me->button())
{
case Qt::LeftButton:
eventButton = mitk::InteractionEvent::LeftMouseButton;
break;
case Qt::RightButton:
eventButton = mitk::InteractionEvent::RightMouseButton;
break;
case Qt::MidButton:
eventButton = mitk::InteractionEvent::MiddleMouseButton;
break;
default:
eventButton = mitk::InteractionEvent::NoButton;
break;
}
return eventButton;
}
mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetButtonState(QMouseEvent *me) const
{
mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton;
if (me->buttons() & Qt::LeftButton)
{
buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton;
}
if (me->buttons() & Qt::RightButton)
{
buttonState = buttonState | mitk::InteractionEvent::RightMouseButton;
}
if (me->buttons() & Qt::MidButton)
{
buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton;
}
return buttonState;
}
mitk::InteractionEvent::ModifierKeys QmitkRenderWindow::GetModifiers(QInputEvent *me) const
{
mitk::InteractionEvent::ModifierKeys modifiers = mitk::InteractionEvent::NoKey;
if (me->modifiers() & Qt::ALT)
{
modifiers = modifiers | mitk::InteractionEvent::AltKey;
}
if (me->modifiers() & Qt::CTRL)
{
modifiers = modifiers | mitk::InteractionEvent::ControlKey;
}
if (me->modifiers() & Qt::SHIFT)
{
modifiers = modifiers | mitk::InteractionEvent::ShiftKey;
}
return modifiers;
}
mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetButtonState(QWheelEvent *we) const
{
mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton;
if (we->buttons() & Qt::LeftButton)
{
buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton;
}
if (we->buttons() & Qt::RightButton)
{
buttonState = buttonState | mitk::InteractionEvent::RightMouseButton;
}
if (we->buttons() & Qt::MidButton)
{
buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton;
}
return buttonState;
}
std::string QmitkRenderWindow::GetKeyLetter(QKeyEvent *ke) const
{
// Converting Qt Key Event to string element.
std::string key = "";
int tkey = ke->key();
if (tkey < 128)
{ // standard ascii letter
key = (char)toupper(tkey);
}
else
{ // special keys
switch (tkey)
{
case Qt::Key_Return:
key = mitk::InteractionEvent::KeyReturn;
break;
case Qt::Key_Enter:
key = mitk::InteractionEvent::KeyEnter;
break;
case Qt::Key_Escape:
key = mitk::InteractionEvent::KeyEsc;
break;
case Qt::Key_Delete:
key = mitk::InteractionEvent::KeyDelete;
break;
case Qt::Key_Up:
key = mitk::InteractionEvent::KeyArrowUp;
break;
case Qt::Key_Down:
key = mitk::InteractionEvent::KeyArrowDown;
break;
case Qt::Key_Left:
key = mitk::InteractionEvent::KeyArrowLeft;
break;
case Qt::Key_Right:
key = mitk::InteractionEvent::KeyArrowRight;
break;
case Qt::Key_F1:
key = mitk::InteractionEvent::KeyF1;
break;
case Qt::Key_F2:
key = mitk::InteractionEvent::KeyF2;
break;
case Qt::Key_F3:
key = mitk::InteractionEvent::KeyF3;
break;
case Qt::Key_F4:
key = mitk::InteractionEvent::KeyF4;
break;
case Qt::Key_F5:
key = mitk::InteractionEvent::KeyF5;
break;
case Qt::Key_F6:
key = mitk::InteractionEvent::KeyF6;
break;
case Qt::Key_F7:
key = mitk::InteractionEvent::KeyF7;
break;
case Qt::Key_F8:
key = mitk::InteractionEvent::KeyF8;
break;
case Qt::Key_F9:
key = mitk::InteractionEvent::KeyF9;
break;
case Qt::Key_F10:
key = mitk::InteractionEvent::KeyF10;
break;
case Qt::Key_F11:
key = mitk::InteractionEvent::KeyF11;
break;
case Qt::Key_F12:
key = mitk::InteractionEvent::KeyF12;
break;
case Qt::Key_End:
key = mitk::InteractionEvent::KeyEnd;
break;
case Qt::Key_Home:
key = mitk::InteractionEvent::KeyPos1;
break;
case Qt::Key_Insert:
key = mitk::InteractionEvent::KeyInsert;
break;
case Qt::Key_PageDown:
key = mitk::InteractionEvent::KeyPageDown;
break;
case Qt::Key_PageUp:
key = mitk::InteractionEvent::KeyPageUp;
break;
case Qt::Key_Space:
key = mitk::InteractionEvent::KeySpace;
break;
}
}
return key;
}
int QmitkRenderWindow::GetDelta(QWheelEvent *we) const
{
return we->delta();
}
void QmitkRenderWindow::UpdateStatusBar(mitk::Point2D pointerPositionOnScreen)
{
mitk::Point3D worldPosition;
m_Renderer->ForceImmediateUpdate();
m_Renderer->DisplayToWorld(pointerPositionOnScreen, worldPosition);
auto statusBar = mitk::StatusBar::GetInstance();
statusBar->DisplayRendererInfo(worldPosition, m_Renderer->GetTime());
}
diff --git a/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp b/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp
index ece6a28e45..0ea68a3046 100644
--- a/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp
+++ b/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp
@@ -1,578 +1,578 @@
/*============================================================================
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 "QmitkRenderWindowMenu.h"
// mitk core
#include "mitkProperties.h"
#include "mitkResliceMethodProperty.h"
// qt
#include <QHBoxLayout>
#include <QPainter>
#include <QSize>
#include <QSpacerItem>
#include <QSlider>
#include <QGroupBox>
#include <QLine>
#include <QRadioButton>
#include <QWidgetAction>
//#include"iconClose.xpm"
#include "iconCrosshairMode.xpm"
#include "iconFullScreen.xpm"
//#include"iconHoriSplit.xpm"
#include "iconSettings.xpm"
//#include"iconVertiSplit.xpm"
#include "iconLeaveFullScreen.xpm"
// c++
#include <cmath>
unsigned int QmitkRenderWindowMenu::m_DefaultThickMode(1);
QmitkRenderWindowMenu::QmitkRenderWindowMenu(QWidget* parent,
Qt::WindowFlags flags,
mitk::BaseRenderer* baseRenderer)
: QWidget(parent, flags)
, m_LayoutActionsMenu(nullptr)
, m_CrosshairMenu(nullptr)
, m_FullScreenMode(false)
, m_Renderer(baseRenderer)
, m_Parent(parent)
, m_CrosshairRotationMode(0)
, m_CrosshairVisibility(true)
, m_Layout(LayoutIndex::Axial)
, m_LayoutDesign(LayoutDesign::DEFAULT)
, m_OldLayoutDesign(LayoutDesign::DEFAULT)
{
CreateMenuWidget();
setMinimumWidth(61); // DIRTY.. If you add or remove a button, you need to change the size.
setMaximumWidth(61);
setAutoFillBackground(true);
this->hide();
m_AutoRotationTimer = new QTimer(this);
m_AutoRotationTimer->setInterval(75);
connect(m_AutoRotationTimer, &QTimer::timeout, this, &QmitkRenderWindowMenu::AutoRotateNextStep);
connect(m_Parent, &QObject::destroyed, this, &QmitkRenderWindowMenu::deleteLater);
}
QmitkRenderWindowMenu::~QmitkRenderWindowMenu()
{
if (m_AutoRotationTimer->isActive())
{
m_AutoRotationTimer->stop();
}
}
void QmitkRenderWindowMenu::SetLayoutIndex(LayoutIndex layoutIndex)
{
m_Layout = layoutIndex;
}
void QmitkRenderWindowMenu::UpdateLayoutDesignList(LayoutDesign layoutDesign)
{
m_LayoutDesign = layoutDesign;
if (nullptr == m_LayoutActionsMenu)
{
CreateSettingsWidget();
}
m_DefaultLayoutAction->setEnabled(true);
m_All2DTop3DBottomLayoutAction->setEnabled(true);
m_All2DLeft3DRightLayoutAction->setEnabled(true);
m_OneBigLayoutAction->setEnabled(true);
m_Only2DHorizontalLayoutAction->setEnabled(true);
m_Only2DVerticalLayoutAction->setEnabled(true);
m_OneTop3DBottomLayoutAction->setEnabled(true);
m_OneLeft3DRightLayoutAction->setEnabled(true);
m_AllHorizontalLayoutAction->setEnabled(true);
m_AllVerticalLayoutAction->setEnabled(true);
m_RemoveOneLayoutAction->setEnabled(true);
switch (m_LayoutDesign)
{
case LayoutDesign::DEFAULT:
{
m_DefaultLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ALL_2D_TOP_3D_BOTTOM:
{
m_All2DTop3DBottomLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ALL_2D_LEFT_3D_RIGHT:
{
m_All2DLeft3DRightLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ONE_BIG:
{
m_OneBigLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ONLY_2D_HORIZONTAL:
{
m_Only2DHorizontalLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ONLY_2D_VERTICAL:
{
m_Only2DVerticalLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ONE_TOP_3D_BOTTOM:
{
m_OneTop3DBottomLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ONE_LEFT_3D_RIGHT:
{
m_OneLeft3DRightLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ALL_HORIZONTAL:
{
m_AllHorizontalLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::ALL_VERTICAL:
{
m_AllVerticalLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::REMOVE_ONE:
{
m_RemoveOneLayoutAction->setEnabled(false);
break;
}
case LayoutDesign::NONE:
{
break;
}
}
}
void QmitkRenderWindowMenu::UpdateCrosshairVisibility(bool visible)
{
m_CrosshairVisibility = visible;
}
void QmitkRenderWindowMenu::UpdateCrosshairRotationMode(int mode)
{
m_CrosshairRotationMode = mode;
}
void QmitkRenderWindowMenu::MoveWidgetToCorrectPos()
{
int moveX = floor(static_cast<double>(this->m_Parent->width()) - static_cast<double>(this->width()) - 4.0);
this->move(moveX, 3);
auto cursorPos = this->mapFromGlobal(QCursor::pos());
if (cursorPos.x() < 0 || cursorPos.x() >= this->width() ||
cursorPos.y() < 0 || cursorPos.y() >= this->height())
{
this->HideMenu();
}
else
{
this->ShowMenu();
}
}
void QmitkRenderWindowMenu::ShowMenu()
{
MITK_DEBUG << "menu showMenu";
this->show();
this->raise();
}
void QmitkRenderWindowMenu::HideMenu()
{
MITK_DEBUG << "menu hideEvent";
this->hide();
}
void QmitkRenderWindowMenu::paintEvent(QPaintEvent * /*e*/)
{
QPainter painter(this);
QColor semiTransparentColor = Qt::black;
semiTransparentColor.setAlpha(255);
painter.fillRect(rect(), semiTransparentColor);
}
void QmitkRenderWindowMenu::CreateMenuWidget()
{
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setAlignment(Qt::AlignRight);
layout->setContentsMargins(1, 1, 1, 1);
QSize size(13, 13);
m_CrosshairMenu = new QMenu(this);
connect(m_CrosshairMenu, &QMenu::aboutToShow, this, &QmitkRenderWindowMenu::OnCrosshairMenuAboutToShow);
m_CrosshairModeButton = new QToolButton(this);
m_CrosshairModeButton->setMaximumSize(15, 15);
m_CrosshairModeButton->setIconSize(size);
m_CrosshairModeButton->setMenu(m_CrosshairMenu);
m_CrosshairModeButton->setIcon(QIcon(QPixmap(iconCrosshairMode_xpm)));
m_CrosshairModeButton->setPopupMode(QToolButton::InstantPopup);
m_CrosshairModeButton->setStyleSheet("QToolButton::menu-indicator { image: none; }");
m_CrosshairModeButton->setAutoRaise(true);
layout->addWidget(m_CrosshairModeButton);
m_FullScreenButton = new QToolButton(this);
m_FullScreenButton->setMaximumSize(15, 15);
m_FullScreenButton->setIconSize(size);
m_FullScreenButton->setIcon(QIcon(QPixmap(iconFullScreen_xpm)));
m_FullScreenButton->setAutoRaise(true);
layout->addWidget(m_FullScreenButton);
m_LayoutDesignButton = new QToolButton(this);
m_LayoutDesignButton->setMaximumSize(15, 15);
m_LayoutDesignButton->setIconSize(size);
m_LayoutDesignButton->setIcon(QIcon(QPixmap(iconSettings_xpm)));
m_LayoutDesignButton->setAutoRaise(true);
layout->addWidget(m_LayoutDesignButton);
connect(m_FullScreenButton, &QToolButton::clicked, this, &QmitkRenderWindowMenu::OnFullScreenButton);
connect(m_LayoutDesignButton, &QToolButton::clicked, this, &QmitkRenderWindowMenu::OnLayoutDesignButton);
}
void QmitkRenderWindowMenu::CreateSettingsWidget()
{
m_LayoutActionsMenu = new QMenu(this);
m_DefaultLayoutAction = new QAction("Standard layout", m_LayoutActionsMenu);
m_DefaultLayoutAction->setDisabled(true);
m_All2DTop3DBottomLayoutAction = new QAction("All 2D top, 3D bottom", m_LayoutActionsMenu);
m_All2DTop3DBottomLayoutAction->setDisabled(false);
m_All2DLeft3DRightLayoutAction = new QAction("All 2D left, 3D right", m_LayoutActionsMenu);
m_All2DLeft3DRightLayoutAction->setDisabled(false);
m_OneBigLayoutAction = new QAction("This big", m_LayoutActionsMenu);
m_OneBigLayoutAction->setDisabled(false);
m_Only2DHorizontalLayoutAction = new QAction("Only 2D horizontal", m_LayoutActionsMenu);
m_Only2DHorizontalLayoutAction->setDisabled(false);
m_Only2DVerticalLayoutAction = new QAction("Only 2D vertical", m_LayoutActionsMenu);
m_Only2DVerticalLayoutAction->setDisabled(false);
m_OneTop3DBottomLayoutAction = new QAction("This top, 3D bottom", m_LayoutActionsMenu);
m_OneTop3DBottomLayoutAction->setDisabled(false);
m_OneLeft3DRightLayoutAction = new QAction("This left, 3D right", m_LayoutActionsMenu);
m_OneLeft3DRightLayoutAction->setDisabled(false);
m_AllHorizontalLayoutAction = new QAction("All horizontal", m_LayoutActionsMenu);
m_AllHorizontalLayoutAction->setDisabled(false);
m_AllVerticalLayoutAction = new QAction("All vertical", m_LayoutActionsMenu);
m_AllVerticalLayoutAction->setDisabled(false);
m_RemoveOneLayoutAction = new QAction("Remove this", m_LayoutActionsMenu);
m_RemoveOneLayoutAction->setDisabled(false);
m_LayoutActionsMenu->addAction(m_DefaultLayoutAction);
m_LayoutActionsMenu->addAction(m_All2DTop3DBottomLayoutAction);
m_LayoutActionsMenu->addAction(m_All2DLeft3DRightLayoutAction);
m_LayoutActionsMenu->addAction(m_OneBigLayoutAction);
m_LayoutActionsMenu->addAction(m_Only2DHorizontalLayoutAction);
m_LayoutActionsMenu->addAction(m_Only2DVerticalLayoutAction);
m_LayoutActionsMenu->addAction(m_OneTop3DBottomLayoutAction);
m_LayoutActionsMenu->addAction(m_OneLeft3DRightLayoutAction);
m_LayoutActionsMenu->addAction(m_AllHorizontalLayoutAction);
m_LayoutActionsMenu->addAction(m_AllVerticalLayoutAction);
m_LayoutActionsMenu->addAction(m_RemoveOneLayoutAction);
m_LayoutActionsMenu->setVisible(false);
connect(m_DefaultLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::DEFAULT); });
connect(m_All2DTop3DBottomLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ALL_2D_TOP_3D_BOTTOM); });
connect(m_All2DLeft3DRightLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ALL_2D_LEFT_3D_RIGHT); });
connect(m_OneBigLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ONE_BIG); });
connect(m_Only2DHorizontalLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ONLY_2D_HORIZONTAL); });
connect(m_Only2DVerticalLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ONLY_2D_VERTICAL); });
connect(m_OneTop3DBottomLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ONE_TOP_3D_BOTTOM); });
connect(m_OneLeft3DRightLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ONE_LEFT_3D_RIGHT); });
connect(m_AllHorizontalLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ALL_HORIZONTAL); });
connect(m_AllVerticalLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::ALL_VERTICAL); });
connect(m_RemoveOneLayoutAction, &QAction::triggered, [this]() { this->OnSetLayout(LayoutDesign::REMOVE_ONE); });
}
void QmitkRenderWindowMenu::ChangeFullScreenIcon()
{
m_FullScreenButton->setIcon(m_FullScreenMode ? QPixmap(iconLeaveFullScreen_xpm) : QPixmap(iconFullScreen_xpm));
}
void QmitkRenderWindowMenu::AutoRotateNextStep()
{
if (m_Renderer->GetCameraRotationController())
{
- m_Renderer->GetCameraRotationController()->GetSlice()->Next();
+ m_Renderer->GetCameraRotationController()->GetStepper()->Next();
}
}
void QmitkRenderWindowMenu::OnAutoRotationActionTriggered()
{
if (m_AutoRotationTimer->isActive())
{
m_AutoRotationTimer->stop();
- m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOff();
+ m_Renderer->GetCameraRotationController()->GetStepper()->PingPongOff();
}
else
{
- m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOn();
+ m_Renderer->GetCameraRotationController()->GetStepper()->PingPongOn();
m_AutoRotationTimer->start();
}
}
void QmitkRenderWindowMenu::OnTSNumChanged(int num)
{
MITK_DEBUG << "Thickslices num: " << num << " on renderer " << m_Renderer.GetPointer();
if (m_Renderer.IsNotNull())
{
unsigned int thickSlicesMode = 0;
// determine the state of the thick-slice mode
mitk::ResliceMethodProperty *resliceMethodEnumProperty = nullptr;
if(m_Renderer->GetCurrentWorldPlaneGeometryNode()->GetProperty(resliceMethodEnumProperty, "reslice.thickslices") && resliceMethodEnumProperty)
{
thickSlicesMode = resliceMethodEnumProperty->GetValueAsId();
if(thickSlicesMode!=0)
m_DefaultThickMode = thickSlicesMode;
}
if(thickSlicesMode==0 && num>0) //default mode only for single slices
{
thickSlicesMode = m_DefaultThickMode; //mip default
m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.showarea",
mitk::BoolProperty::New(true));
}
if(num<1)
{
thickSlicesMode = 0;
m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.showarea",
mitk::BoolProperty::New(false));
}
m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices",
mitk::ResliceMethodProperty::New(thickSlicesMode));
m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.num",
mitk::IntProperty::New(num));
m_TSLabel->setText(QString::number(num * 2 + 1));
m_Renderer->SendUpdateSlice();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkRenderWindowMenu::OnCrosshairMenuAboutToShow()
{
QMenu *crosshairModesMenu = m_CrosshairMenu;
crosshairModesMenu->clear();
QAction *resetViewAction = new QAction(crosshairModesMenu);
resetViewAction->setText("Reset view");
crosshairModesMenu->addAction(resetViewAction);
connect(resetViewAction, &QAction::triggered, this, &QmitkRenderWindowMenu::ResetView);
// Show hide crosshairs
{
QAction *showHideCrosshairVisibilityAction = new QAction(crosshairModesMenu);
showHideCrosshairVisibilityAction->setText("Show crosshair");
showHideCrosshairVisibilityAction->setCheckable(true);
showHideCrosshairVisibilityAction->setChecked(m_CrosshairVisibility);
crosshairModesMenu->addAction(showHideCrosshairVisibilityAction);
connect(showHideCrosshairVisibilityAction, &QAction::toggled, this, &QmitkRenderWindowMenu::OnCrosshairVisibilityChanged);
}
// Rotation mode
{
QAction *rotationGroupSeparator = new QAction(crosshairModesMenu);
rotationGroupSeparator->setSeparator(true);
rotationGroupSeparator->setText("Rotation mode");
crosshairModesMenu->addAction(rotationGroupSeparator);
QActionGroup *rotationModeActionGroup = new QActionGroup(crosshairModesMenu);
rotationModeActionGroup->setExclusive(true);
QAction *noCrosshairRotation = new QAction(crosshairModesMenu);
noCrosshairRotation->setActionGroup(rotationModeActionGroup);
noCrosshairRotation->setText("No crosshair rotation");
noCrosshairRotation->setCheckable(true);
noCrosshairRotation->setChecked(m_CrosshairRotationMode == 0);
noCrosshairRotation->setData(0);
crosshairModesMenu->addAction(noCrosshairRotation);
QAction *singleCrosshairRotation = new QAction(crosshairModesMenu);
singleCrosshairRotation->setActionGroup(rotationModeActionGroup);
singleCrosshairRotation->setText("Crosshair rotation");
singleCrosshairRotation->setCheckable(true);
singleCrosshairRotation->setChecked(m_CrosshairRotationMode == 1);
singleCrosshairRotation->setData(1);
crosshairModesMenu->addAction(singleCrosshairRotation);
QAction *coupledCrosshairRotation = new QAction(crosshairModesMenu);
coupledCrosshairRotation->setActionGroup(rotationModeActionGroup);
coupledCrosshairRotation->setText("Coupled crosshair rotation");
coupledCrosshairRotation->setCheckable(true);
coupledCrosshairRotation->setChecked(m_CrosshairRotationMode == 2);
coupledCrosshairRotation->setData(2);
crosshairModesMenu->addAction(coupledCrosshairRotation);
QAction *swivelMode = new QAction(crosshairModesMenu);
swivelMode->setActionGroup(rotationModeActionGroup);
swivelMode->setText("Swivel mode");
swivelMode->setCheckable(true);
swivelMode->setChecked(m_CrosshairRotationMode == 3);
swivelMode->setData(3);
crosshairModesMenu->addAction(swivelMode);
connect(rotationModeActionGroup, &QActionGroup::triggered, this, &QmitkRenderWindowMenu::OnCrosshairRotationModeSelected);
}
// auto rotation support
if (m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard3D)
{
QAction *autoRotationGroupSeparator = new QAction(crosshairModesMenu);
autoRotationGroupSeparator->setSeparator(true);
crosshairModesMenu->addAction(autoRotationGroupSeparator);
QAction *autoRotationAction = crosshairModesMenu->addAction("Auto Rotation");
autoRotationAction->setCheckable(true);
autoRotationAction->setChecked(m_AutoRotationTimer->isActive());
connect(autoRotationAction, &QAction::triggered, this, &QmitkRenderWindowMenu::OnAutoRotationActionTriggered);
}
// Thickslices support
if (m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard2D)
{
QAction *thickSlicesGroupSeparator = new QAction(crosshairModesMenu);
thickSlicesGroupSeparator->setSeparator(true);
thickSlicesGroupSeparator->setText("ThickSlices mode");
crosshairModesMenu->addAction(thickSlicesGroupSeparator);
QActionGroup *thickSlicesActionGroup = new QActionGroup(crosshairModesMenu);
thickSlicesActionGroup->setExclusive(true);
int currentMode = 0;
{
mitk::ResliceMethodProperty::Pointer m = dynamic_cast<mitk::ResliceMethodProperty *>(
m_Renderer->GetCurrentWorldPlaneGeometryNode()->GetProperty("reslice.thickslices"));
if (m.IsNotNull())
currentMode = m->GetValueAsId();
}
int currentNum = 1;
{
mitk::IntProperty::Pointer m = dynamic_cast<mitk::IntProperty *>(
m_Renderer->GetCurrentWorldPlaneGeometryNode()->GetProperty("reslice.thickslices.num"));
if (m.IsNotNull())
{
currentNum = m->GetValue();
}
}
if (currentMode == 0)
currentNum = 0;
QSlider *m_TSSlider = new QSlider(crosshairModesMenu);
m_TSSlider->setMinimum(0);
m_TSSlider->setMaximum(50);
m_TSSlider->setValue(currentNum);
m_TSSlider->setOrientation(Qt::Horizontal);
connect(m_TSSlider, &QSlider::valueChanged, this, &QmitkRenderWindowMenu::OnTSNumChanged);
QHBoxLayout *tsLayout = new QHBoxLayout;
tsLayout->setContentsMargins(4, 4, 4, 4);
tsLayout->addWidget(new QLabel("TS: "));
tsLayout->addWidget(m_TSSlider);
tsLayout->addWidget(m_TSLabel = new QLabel(QString::number(currentNum * 2 + 1), this));
QWidget *tsWidget = new QWidget;
tsWidget->setLayout(tsLayout);
QWidgetAction *m_TSSliderAction = new QWidgetAction(crosshairModesMenu);
m_TSSliderAction->setDefaultWidget(tsWidget);
crosshairModesMenu->addAction(m_TSSliderAction);
}
}
void QmitkRenderWindowMenu::OnCrosshairVisibilityChanged(bool visible)
{
UpdateCrosshairVisibility(visible);
emit CrosshairVisibilityChanged(m_CrosshairVisibility);
}
void QmitkRenderWindowMenu::OnCrosshairRotationModeSelected(QAction *action)
{
UpdateCrosshairRotationMode(action->data().toInt());
emit CrosshairRotationModeChanged(m_CrosshairRotationMode);
}
void QmitkRenderWindowMenu::OnFullScreenButton(bool /*checked*/)
{
if (!m_FullScreenMode)
{
m_FullScreenMode = true;
m_OldLayoutDesign = m_LayoutDesign;
emit LayoutDesignChanged(LayoutDesign::ONE_BIG);
}
else
{
m_FullScreenMode = false;
emit LayoutDesignChanged(m_OldLayoutDesign);
}
MoveWidgetToCorrectPos();
ChangeFullScreenIcon();
ShowMenu();
}
void QmitkRenderWindowMenu::OnLayoutDesignButton(bool /*checked*/)
{
if (nullptr == m_LayoutActionsMenu)
{
CreateSettingsWidget();
}
QPoint point = mapToGlobal(m_LayoutDesignButton->geometry().topLeft());
m_LayoutActionsMenu->setVisible(true);
m_LayoutActionsMenu->exec(point);
}
void QmitkRenderWindowMenu::OnSetLayout(LayoutDesign layoutDesign)
{
m_FullScreenMode = false;
ChangeFullScreenIcon();
m_LayoutDesign = layoutDesign;
emit LayoutDesignChanged(m_LayoutDesign);
ShowMenu();
}
diff --git a/Modules/QtWidgets/src/QmitkRenderWindowUtilityWidget.cpp b/Modules/QtWidgets/src/QmitkRenderWindowUtilityWidget.cpp
index 9e08a160f7..ce0614d60b 100644
--- a/Modules/QtWidgets/src/QmitkRenderWindowUtilityWidget.cpp
+++ b/Modules/QtWidgets/src/QmitkRenderWindowUtilityWidget.cpp
@@ -1,181 +1,181 @@
/*============================================================================
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 "QmitkRenderWindowUtilityWidget.h"
#include <QWidgetAction>
// mitk core
#include <mitkDataStorage.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateProperty.h>
// mitk qt widgets
#include <QmitkRenderWindow.h>
#include <QmitkStyleManager.h>
// itk
#include <itkSpatialOrientationAdapter.h>
QmitkRenderWindowUtilityWidget::QmitkRenderWindowUtilityWidget(
QWidget* parent/* = nullptr */,
QmitkRenderWindow* renderWindow/* = nullptr */,
mitk::DataStorage* dataStorage/* = nullptr */)
: m_NodeSelectionWidget(nullptr)
, m_SliceNavigationWidget(nullptr)
, m_StepperAdapter(nullptr)
, m_ViewDirectionSelector(nullptr)
{
this->setParent(parent);
auto layout = new QHBoxLayout(this);
layout->setMargin(0);
mitk::NodePredicateAnd::Pointer noHelperObjects = mitk::NodePredicateAnd::New();
noHelperObjects->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
noHelperObjects->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
m_BaseRenderer = mitk::BaseRenderer::GetInstance(renderWindow->GetVtkRenderWindow());
m_NodeSelectionWidget = new QmitkSynchronizedNodeSelectionWidget(parent);
m_NodeSelectionWidget->SetBaseRenderer(m_BaseRenderer);
m_NodeSelectionWidget->SetDataStorage(dataStorage);
m_NodeSelectionWidget->SetNodePredicate(noHelperObjects);
auto menuBar = new QMenuBar(this);
menuBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
auto dataMenu = menuBar->addMenu("Data");
QWidgetAction* dataAction = new QWidgetAction(dataMenu);
dataAction->setDefaultWidget(m_NodeSelectionWidget);
dataMenu->addAction(dataAction);
layout->addWidget(menuBar);
auto* synchPushButton = new QPushButton(this);
auto* synchIcon = new QIcon();
auto synchronizeSvg = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/lock.svg"));
auto desynchronizeSvg = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/unlock.svg"));
synchIcon->addPixmap(synchronizeSvg.pixmap(64), QIcon::Normal, QIcon::On);
synchIcon->addPixmap(desynchronizeSvg.pixmap(64), QIcon::Normal, QIcon::Off);
synchPushButton->setIcon(*synchIcon);
synchPushButton->setToolTip("Synchronize / desynchronize data management");
synchPushButton->setCheckable(true);
synchPushButton->setChecked(true);
connect(synchPushButton, &QPushButton::clicked,
this, &QmitkRenderWindowUtilityWidget::ToggleSynchronization);
layout->addWidget(synchPushButton);
auto* sliceNavigationController = m_BaseRenderer->GetSliceNavigationController();
m_SliceNavigationWidget = new QmitkSliceNavigationWidget(this);
m_StepperAdapter =
- new QmitkStepperAdapter(m_SliceNavigationWidget, sliceNavigationController->GetSlice());
+ new QmitkStepperAdapter(m_SliceNavigationWidget, sliceNavigationController->GetStepper());
layout->addWidget(m_SliceNavigationWidget);
mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer{ m_BaseRenderer };
m_RenderWindowViewDirectionController = std::make_unique<mitk::RenderWindowViewDirectionController>();
m_RenderWindowViewDirectionController->SetControlledRenderer(controlledRenderer);
m_RenderWindowViewDirectionController->SetDataStorage(dataStorage);
m_ViewDirectionSelector = new QComboBox(this);
QStringList viewDirections{ "axial", "coronal", "sagittal"};
m_ViewDirectionSelector->insertItems(0, viewDirections);
connect(m_ViewDirectionSelector, &QComboBox::currentTextChanged, this, &QmitkRenderWindowUtilityWidget::ChangeViewDirection);
UpdateViewPlaneSelection();
layout->addWidget(m_ViewDirectionSelector);
// finally add observer, after all relevant objects have been created / initialized
sliceNavigationController->ConnectGeometrySendEvent(this);
}
QmitkRenderWindowUtilityWidget::~QmitkRenderWindowUtilityWidget()
{
}
void QmitkRenderWindowUtilityWidget::ToggleSynchronization(bool synchronized)
{
m_NodeSelectionWidget->SetSynchronized(synchronized);
emit SynchronizationToggled(m_NodeSelectionWidget);
}
void QmitkRenderWindowUtilityWidget::SetGeometry(const itk::EventObject& event)
{
if (!mitk::SliceNavigationController::GeometrySendEvent(nullptr, 0).CheckEvent(&event))
{
return;
}
const auto* sliceNavigationController = m_BaseRenderer->GetSliceNavigationController();
auto viewDirection = sliceNavigationController->GetViewDirection();
unsigned int axis = 0;
switch (viewDirection)
{
case mitk::AnatomicalPlane::Original:
return;
case mitk::AnatomicalPlane::Axial:
{
axis = 2;
break;
}
case mitk::AnatomicalPlane::Coronal:
{
axis = 1;
break;
}
case mitk::AnatomicalPlane::Sagittal:
{
axis = 0;
break;
}
}
const auto* inputTimeGeometry = sliceNavigationController->GetInputWorldTimeGeometry();
const mitk::BaseGeometry* rendererGeometry = m_BaseRenderer->GetCurrentWorldGeometry();
- mitk::TimeStepType timeStep = sliceNavigationController->GetTime()->GetPos();
+ mitk::TimeStepType timeStep = sliceNavigationController->GetStepper()->GetPos();
mitk::BaseGeometry::ConstPointer geometry = inputTimeGeometry->GetGeometryForTimeStep(timeStep);
mitk::AffineTransform3D::MatrixType matrix = geometry->GetIndexToWorldTransform()->GetMatrix();
matrix.GetVnlMatrix().normalize_columns();
mitk::AffineTransform3D::MatrixType::InternalMatrixType inverseMatrix = matrix.GetInverse();
int dominantAxis = itk::Function::Max3(inverseMatrix[0][axis], inverseMatrix[1][axis], inverseMatrix[2][axis]);
bool referenceGeometryAxisInverted = inverseMatrix[dominantAxis][axis] < 0;
bool rendererZAxisInverted = rendererGeometry->GetAxisVector(2)[axis] < 0;
m_SliceNavigationWidget->SetInverseDirection(referenceGeometryAxisInverted != rendererZAxisInverted);
}
void QmitkRenderWindowUtilityWidget::ChangeViewDirection(const QString& viewDirection)
{
m_RenderWindowViewDirectionController->SetViewDirectionOfRenderer(viewDirection.toStdString());
}
void QmitkRenderWindowUtilityWidget::UpdateViewPlaneSelection()
{
const auto sliceNavigationController = m_BaseRenderer->GetSliceNavigationController();
const auto viewDirection = sliceNavigationController->GetDefaultViewDirection();
switch (viewDirection)
{
case mitk::AnatomicalPlane::Axial:
m_ViewDirectionSelector->setCurrentIndex(0);
break;
case mitk::AnatomicalPlane::Coronal:
m_ViewDirectionSelector->setCurrentIndex(1);
break;
case mitk::AnatomicalPlane::Sagittal:
m_ViewDirectionSelector->setCurrentIndex(2);
break;
default:
break;
}
}
diff --git a/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp b/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp
index 4b05156f91..29325720d7 100644
--- a/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp
+++ b/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp
@@ -1,322 +1,322 @@
/*============================================================================
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 "QmitkRenderWindowWidget.h"
// vtk
#include <vtkCornerAnnotation.h>
#include <vtkTextProperty.h>
QmitkRenderWindowWidget::QmitkRenderWindowWidget(QWidget* parent/* = nullptr*/,
const QString& widgetName/* = ""*/,
mitk::DataStorage* dataStorage/* = nullptr*/)
: QFrame(parent)
, m_WidgetName(widgetName)
, m_DataStorage(dataStorage)
, m_RenderWindow(nullptr)
, m_CrosshairManager(nullptr)
{
this->InitializeGUI();
}
QmitkRenderWindowWidget::~QmitkRenderWindowWidget()
{
auto sliceNavigationController = this->GetSliceNavigationController();
if (nullptr != sliceNavigationController)
{
sliceNavigationController->SetCrosshairEvent.RemoveListener(
mitk::MessageDelegate1<QmitkRenderWindowWidget, const mitk::Point3D &>(
this, &QmitkRenderWindowWidget::SetCrosshairPosition));
}
this->DisableCrosshair();
}
void QmitkRenderWindowWidget::SetDataStorage(mitk::DataStorage* dataStorage)
{
if (dataStorage == m_DataStorage)
{
return;
}
m_DataStorage = dataStorage;
if (nullptr != m_RenderWindow)
{
mitk::BaseRenderer::GetInstance(m_RenderWindow->renderWindow())->SetDataStorage(dataStorage);
}
}
mitk::SliceNavigationController* QmitkRenderWindowWidget::GetSliceNavigationController() const
{
return m_RenderWindow->GetSliceNavigationController();
}
void QmitkRenderWindowWidget::RequestUpdate()
{
mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow->renderWindow());
}
void QmitkRenderWindowWidget::ForceImmediateUpdate()
{
mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(m_RenderWindow->renderWindow());
}
void QmitkRenderWindowWidget::AddUtilityWidget(QWidget* utilityWidget)
{
m_Layout->insertWidget(0, utilityWidget);
}
void QmitkRenderWindowWidget::SetGradientBackgroundColors(const mitk::Color& upper, const mitk::Color& lower)
{
vtkRenderer* vtkRenderer = m_RenderWindow->GetRenderer()->GetVtkRenderer();
if (nullptr == vtkRenderer)
{
return;
}
m_GradientBackgroundColors.first = upper;
m_GradientBackgroundColors.second = lower;
vtkRenderer->SetBackground(lower[0], lower[1], lower[2]);
vtkRenderer->SetBackground2(upper[0], upper[1], upper[2]);
ShowGradientBackground(true);
}
void QmitkRenderWindowWidget::ShowGradientBackground(bool show)
{
m_RenderWindow->GetRenderer()->GetVtkRenderer()->SetGradientBackground(show);
}
bool QmitkRenderWindowWidget::IsGradientBackgroundOn() const
{
return m_RenderWindow->GetRenderer()->GetVtkRenderer()->GetGradientBackground();
}
void QmitkRenderWindowWidget::SetDecorationColor(const mitk::Color& color)
{
m_DecorationColor = color;
m_CornerAnnotation->GetTextProperty()->SetColor(m_DecorationColor[0], m_DecorationColor[1], m_DecorationColor[2]);
QColor hexColor(m_DecorationColor[0] * 255, m_DecorationColor[1] * 255, m_DecorationColor[2] * 255);
setStyleSheet("QmitkRenderWindowWidget { border: 2px solid " + hexColor.name(QColor::HexRgb) + "; }");
}
void QmitkRenderWindowWidget::ShowColoredRectangle(bool show)
{
if (show)
{
setFrameStyle(QFrame::Box | QFrame::Plain);
}
else
{
setFrameStyle(NoFrame);
}
}
bool QmitkRenderWindowWidget::IsColoredRectangleVisible() const
{
return frameStyle() > 0;
}
void QmitkRenderWindowWidget::ShowCornerAnnotation(bool show)
{
m_CornerAnnotation->SetVisibility(show);
}
bool QmitkRenderWindowWidget::IsCornerAnnotationVisible() const
{
return m_CornerAnnotation->GetVisibility() > 0;
}
void QmitkRenderWindowWidget::SetCornerAnnotationText(const std::string& cornerAnnotation)
{
m_CornerAnnotation->SetText(0, cornerAnnotation.c_str());
}
std::string QmitkRenderWindowWidget::GetCornerAnnotationText() const
{
return std::string(m_CornerAnnotation->GetText(0));
}
bool QmitkRenderWindowWidget::IsRenderWindowMenuActivated() const
{
return m_RenderWindow->GetActivateMenuWidgetFlag();
}
void QmitkRenderWindowWidget::SetCrosshairVisibility(bool visible)
{
m_CrosshairManager->SetCrosshairVisibility(visible, m_RenderWindow->GetRenderer());
this->RequestUpdate();
}
bool QmitkRenderWindowWidget::GetCrosshairVisibility()
{
return m_CrosshairManager->GetCrosshairVisibility(m_RenderWindow->GetRenderer());
}
void QmitkRenderWindowWidget::SetCrosshairGap(unsigned int gapSize)
{
m_CrosshairManager->SetCrosshairGap(gapSize);
}
void QmitkRenderWindowWidget::EnableCrosshair()
{
m_CrosshairManager->AddCrosshairNodeToDataStorage(m_DataStorage);
}
void QmitkRenderWindowWidget::DisableCrosshair()
{
m_CrosshairManager->RemoveCrosshairNodeFromDataStorage(m_DataStorage);
}
void QmitkRenderWindowWidget::InitializeGUI()
{
m_Layout = new QVBoxLayout(this);
m_Layout->setMargin(0);
setLayout(m_Layout);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setContentsMargins(0, 0, 0, 0);
if (nullptr == m_DataStorage)
{
return;
}
mitk::RenderingManager::GetInstance()->SetDataStorage(m_DataStorage);
// create render window for this render window widget
m_RenderWindow = new QmitkRenderWindow(this, m_WidgetName, nullptr);
m_RenderWindow->SetLayoutIndex(mitk::AnatomicalPlane::Sagittal);
connect(m_RenderWindow, &QmitkRenderWindow::ResetGeometry,
this, &QmitkRenderWindowWidget::OnResetGeometry);
auto* sliceNavigationController = this->GetSliceNavigationController();
sliceNavigationController->SetDefaultViewDirection(mitk::AnatomicalPlane::Sagittal);
m_Layout->addWidget(m_RenderWindow);
// set colors and corner annotation
InitializeDecorations();
// use crosshair manager
m_CrosshairManager = mitk::CrosshairManager::New(m_RenderWindow->GetRenderer());
sliceNavigationController->SetCrosshairEvent.AddListener(
mitk::MessageDelegate1<QmitkRenderWindowWidget, const mitk::Point3D &>(
this, &QmitkRenderWindowWidget::SetCrosshairPosition));
// finally add observer, after all relevant objects have been created / initialized
sliceNavigationController->ConnectGeometrySendEvent(this);
sliceNavigationController->ConnectGeometrySliceEvent(this);
mitk::TimeGeometry::ConstPointer timeGeometry = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeView(m_RenderWindow->GetVtkRenderWindow(), timeGeometry);
}
void QmitkRenderWindowWidget::InitializeDecorations()
{
vtkRenderer* vtkRenderer = m_RenderWindow->GetRenderer()->GetVtkRenderer();
if (nullptr == vtkRenderer)
{
return;
}
// initialize background color gradients
float black[3] = { 0.0f, 0.0f, 0.0f };
SetGradientBackgroundColors(black, black);
// initialize annotation text and decoration color
setFrameStyle(QFrame::Box | QFrame::Plain);
m_CornerAnnotation = vtkSmartPointer<vtkCornerAnnotation>::New();
m_CornerAnnotation->SetText(0, "Sagittal");
m_CornerAnnotation->SetMaximumFontSize(12);
if (0 == vtkRenderer->HasViewProp(m_CornerAnnotation))
{
vtkRenderer->AddViewProp(m_CornerAnnotation);
}
float white[3] = { 1.0f, 1.0f, 1.0f };
SetDecorationColor(mitk::Color(white));
}
void QmitkRenderWindowWidget::SetCrosshairPosition(const mitk::Point3D& newPosition)
{
m_CrosshairManager->SetCrosshairPosition(newPosition);
this->RequestUpdate();
}
mitk::Point3D QmitkRenderWindowWidget::GetCrosshairPosition() const
{
return m_CrosshairManager->GetCrosshairPosition();
}
void QmitkRenderWindowWidget::SetGeometry(const itk::EventObject& event)
{
if (!mitk::SliceNavigationController::GeometrySendEvent(nullptr, 0).CheckEvent(&event))
{
return;
}
const auto* planeGeometry = this->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (nullptr == planeGeometry)
{
mitkThrow() << "No valid plane geometry set. Render window is in an invalid state.";
}
return SetCrosshairPosition(planeGeometry->GetCenter());
}
void QmitkRenderWindowWidget::SetGeometrySlice(const itk::EventObject& event)
{
if (!mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0).CheckEvent(&event))
{
return;
}
const auto* sliceNavigationController = this->GetSliceNavigationController();
m_CrosshairManager->UpdateCrosshairPosition(sliceNavigationController);
}
void QmitkRenderWindowWidget::OnResetGeometry()
{
- const auto* baseRenderer = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetRenderWindow());
+ const auto* baseRenderer = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow());
const auto* interactionReferenceGeometry = baseRenderer->GetInteractionReferenceGeometry();
this->ResetGeometry(interactionReferenceGeometry);
m_RenderWindow->ShowOverlayMessage(false);
}
void QmitkRenderWindowWidget::ResetGeometry(const mitk::TimeGeometry* referenceGeometry)
{
if (nullptr == referenceGeometry)
{
return;
}
mitk::TimeStepType imageTimeStep = 0;
// store the current position to set it again later, if the camera should not be reset
mitk::Point3D currentPosition = this->GetCrosshairPosition();
// store the current time step to set it again later, if the camera should not be reset
auto* renderingManager = mitk::RenderingManager::GetInstance();
- const auto currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
+ const mitk::TimePointType currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
if (referenceGeometry->IsValidTimePoint(currentTimePoint))
{
imageTimeStep = referenceGeometry->TimePointToTimeStep(currentTimePoint);
}
const auto* baseRenderer = mitk::BaseRenderer::GetInstance(m_RenderWindow->renderWindow());
renderingManager->InitializeView(baseRenderer->GetRenderWindow(), referenceGeometry, false);
// reset position and time step
this->GetSliceNavigationController()->SelectSliceByPoint(currentPosition);
- renderingManager->GetTimeNavigationController()->GetTime()->SetPos(imageTimeStep);
+ renderingManager->GetTimeNavigationController()->GetStepper()->SetPos(imageTimeStep);
}
diff --git a/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp b/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp
index 3ad055e200..05efea7479 100644
--- a/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp
+++ b/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp
@@ -1,742 +1,716 @@
/*============================================================================
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 SMW_INFO MITK_INFO("widget.stdmulti")
#include "QmitkStdMultiWidget.h"
#include "QmitkRenderWindowWidget.h"
// mitk core
#include <mitkCameraController.h>
#include <mitkImage.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkInteractionConst.h>
#include <mitkLine.h>
#include <mitkNodePredicateBase.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkPixelTypeMultiplex.h>
#include <mitkPlaneGeometryDataMapper2D.h>
#include <mitkPointSet.h>
#include <mitkProperties.h>
#include <mitkStatusBar.h>
#include <mitkDisplayActionEventHandlerStd.h>
#include <mitkVtkLayerController.h>
// qt
#include <QList>
#include <QMouseEvent>
#include <QTimer>
// vtk
#include <vtkSmartPointer.h>
// c++
#include <iomanip>
QmitkStdMultiWidget::QmitkStdMultiWidget(QWidget *parent,
Qt::WindowFlags f/* = 0*/,
const QString &name/* = "stdmulti"*/)
: QmitkAbstractMultiWidget(parent, f, name)
- , m_TimeNavigationController(nullptr)
{
- m_TimeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
}
QmitkStdMultiWidget::~QmitkStdMultiWidget()
{
- auto allRenderWindows = this->GetRenderWindows();
- for (auto& renderWindow : allRenderWindows)
- {
- m_TimeNavigationController->Disconnect(renderWindow->GetSliceNavigationController());
- }
}
void QmitkStdMultiWidget::InitializeMultiWidget()
{
// yellow is default color for widget4
m_DecorationColorWidget4[0] = 1.0f;
m_DecorationColorWidget4[1] = 1.0f;
m_DecorationColorWidget4[2] = 0.0f;
SetLayout(2, 2);
// transfer colors in WorldGeometry-Nodes of the associated Renderer
// of widget 1
m_PlaneNode1 =
mitk::BaseRenderer::GetInstance(GetRenderWindow1()->renderWindow())->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode1->SetColor(GetDecorationColor(0));
// of widget 2
m_PlaneNode2 =
mitk::BaseRenderer::GetInstance(GetRenderWindow2()->renderWindow())->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode2->SetColor(GetDecorationColor(1));
// of widget 3
m_PlaneNode3 =
mitk::BaseRenderer::GetInstance(GetRenderWindow3()->renderWindow())->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode3->SetColor(GetDecorationColor(2));
// the parent node
m_ParentNodeForGeometryPlanes =
mitk::BaseRenderer::GetInstance(GetRenderWindow4()->renderWindow())->GetCurrentWorldPlaneGeometryNode();
AddDisplayPlaneSubTree();
SetDisplayActionEventHandler(std::make_unique<mitk::DisplayActionEventHandlerStd>());
auto displayActionEventHandler = GetDisplayActionEventHandler();
if (nullptr != displayActionEventHandler)
{
displayActionEventHandler->InitActions();
}
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow(const QString& widgetName) const
{
if ("axial" == widgetName || "Axial" == widgetName)
{
return GetRenderWindow1();
}
if ("sagittal" == widgetName || "Sagittal" == widgetName)
{
return GetRenderWindow2();
}
if ("coronal" == widgetName || "Coronal" == widgetName)
{
return GetRenderWindow3();
}
if ("3d" == widgetName || "3D" == widgetName)
{
return GetRenderWindow4();
}
return QmitkAbstractMultiWidget::GetRenderWindow(widgetName);
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow(const mitk::AnatomicalPlane& orientation) const
{
return GetRenderWindow(static_cast<unsigned int>(orientation));
}
void QmitkStdMultiWidget::InitializeViews(const mitk::TimeGeometry* geometry, bool resetCamera)
{
auto* renderingManager = mitk::RenderingManager::GetInstance();
mitk::Point3D currentPosition = mitk::Point3D();
unsigned int imageTimeStep = 0;
if (!resetCamera)
{
// store the current position to set it again later, if the camera should not be reset
currentPosition = this->GetSelectedPosition("");
// store the current time step to set it again later, if the camera should not be reset
- const auto currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
+ const mitk::TimePointType currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
if (geometry->IsValidTimePoint(currentTimePoint))
{
imageTimeStep = geometry->TimePointToTimeStep(currentTimePoint);
}
}
// initialize render windows
renderingManager->InitializeViews(geometry, mitk::RenderingManager::REQUEST_UPDATE_ALL, resetCamera);
if (!resetCamera)
{
this->SetSelectedPosition(currentPosition, "");
- renderingManager->GetTimeNavigationController()->GetTime()->SetPos(imageTimeStep);
+ renderingManager->GetTimeNavigationController()->GetStepper()->SetPos(imageTimeStep);
}
}
void QmitkStdMultiWidget::SetInteractionReferenceGeometry(const mitk::TimeGeometry* /*referenceGeometry*/)
{
// not implemented on purpose
}
bool QmitkStdMultiWidget::HasCoupledRenderWindows() const
{
return true;
}
void QmitkStdMultiWidget::SetSelectedPosition(const mitk::Point3D& newPosition, const QString& /*widgetName*/)
{
GetRenderWindow1()->GetSliceNavigationController()->SelectSliceByPoint(newPosition);
GetRenderWindow2()->GetSliceNavigationController()->SelectSliceByPoint(newPosition);
GetRenderWindow3()->GetSliceNavigationController()->SelectSliceByPoint(newPosition);
RequestUpdateAll();
}
const mitk::Point3D QmitkStdMultiWidget::GetSelectedPosition(const QString& /*widgetName*/) const
{
const mitk::PlaneGeometry* plane1 = GetRenderWindow1()->GetSliceNavigationController()->GetCurrentPlaneGeometry();
const mitk::PlaneGeometry* plane2 = GetRenderWindow2()->GetSliceNavigationController()->GetCurrentPlaneGeometry();
const mitk::PlaneGeometry* plane3 = GetRenderWindow3()->GetSliceNavigationController()->GetCurrentPlaneGeometry();
mitk::Line3D line;
if ((plane1 != nullptr) && (plane2 != nullptr)
&& (plane1->IntersectionLine(plane2, line)))
{
mitk::Point3D point;
if ((plane3 != nullptr) && (plane3->IntersectionPoint(line, point)))
{
return point;
}
}
return mitk::Point3D();
}
void QmitkStdMultiWidget::SetCrosshairVisibility(bool visible)
{
if (m_PlaneNode1.IsNotNull())
{
m_PlaneNode1->SetVisibility(visible);
}
if (m_PlaneNode2.IsNotNull())
{
m_PlaneNode2->SetVisibility(visible);
}
if (m_PlaneNode3.IsNotNull())
{
m_PlaneNode3->SetVisibility(visible);
}
emit NotifyCrosshairVisibilityChanged(visible);
RequestUpdateAll();
}
bool QmitkStdMultiWidget::GetCrosshairVisibility() const
{
bool crosshairVisibility = true;
if (m_PlaneNode1.IsNotNull())
{
bool visibilityProperty = false;
m_PlaneNode1->GetVisibility(visibilityProperty, nullptr);
crosshairVisibility &= visibilityProperty;
}
if (m_PlaneNode2.IsNotNull())
{
bool visibilityProperty = false;
crosshairVisibility &= m_PlaneNode2->GetVisibility(visibilityProperty, nullptr);
crosshairVisibility &= visibilityProperty;
}
if (m_PlaneNode3.IsNotNull())
{
bool visibilityProperty = false;
crosshairVisibility &= m_PlaneNode3->GetVisibility(visibilityProperty, nullptr);
crosshairVisibility &= visibilityProperty;
}
return crosshairVisibility;
}
void QmitkStdMultiWidget::SetCrosshairGap(unsigned int gapSize)
{
m_PlaneNode1->SetIntProperty("Crosshair.Gap Size", gapSize);
m_PlaneNode2->SetIntProperty("Crosshair.Gap Size", gapSize);
m_PlaneNode3->SetIntProperty("Crosshair.Gap Size", gapSize);
}
void QmitkStdMultiWidget::ResetCrosshair()
{
auto dataStorage = GetDataStorage();
if (nullptr == dataStorage)
{
return;
}
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage);
SetWidgetPlaneMode(mitk::InteractionSchemeSwitcher::MITKStandard);
}
void QmitkStdMultiWidget::SetWidgetPlaneMode(int userMode)
{
MITK_DEBUG << "Changing crosshair mode to " << userMode;
switch (userMode)
{
case 0:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKStandard);
break;
case 1:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKRotationUncoupled);
break;
case 2:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKRotationCoupled);
break;
case 3:
SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKSwivel);
break;
}
emit NotifyCrosshairRotationModeChanged(userMode);
}
-mitk::SliceNavigationController* QmitkStdMultiWidget::GetTimeNavigationController()
-{
- return m_TimeNavigationController;
-}
-
void QmitkStdMultiWidget::AddPlanesToDataStorage()
{
auto dataStorage = GetDataStorage();
if (nullptr == dataStorage)
{
return;
}
if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull()
&& m_PlaneNode3.IsNotNull() && m_ParentNodeForGeometryPlanes.IsNotNull())
{
dataStorage->Add(m_ParentNodeForGeometryPlanes);
dataStorage->Add(m_PlaneNode1, m_ParentNodeForGeometryPlanes);
dataStorage->Add(m_PlaneNode2, m_ParentNodeForGeometryPlanes);
dataStorage->Add(m_PlaneNode3, m_ParentNodeForGeometryPlanes);
}
}
void QmitkStdMultiWidget::RemovePlanesFromDataStorage()
{
auto dataStorage = GetDataStorage();
if (nullptr == dataStorage)
{
return;
}
if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull()
&& m_PlaneNode3.IsNotNull() && m_ParentNodeForGeometryPlanes.IsNotNull())
{
dataStorage->Remove(m_PlaneNode1);
dataStorage->Remove(m_PlaneNode2);
dataStorage->Remove(m_PlaneNode3);
dataStorage->Remove(m_ParentNodeForGeometryPlanes);
}
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow(unsigned int number) const
{
switch (number)
{
case 0:
return GetRenderWindow1();
case 1:
return GetRenderWindow2();
case 2:
return GetRenderWindow3();
case 3:
return GetRenderWindow4();
default:
MITK_ERROR << "Requested unknown render window";
break;
}
return nullptr;
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow1() const
{
return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(0, 0));
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow2() const
{
return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(0, 1));
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow3() const
{
return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(1, 0));
}
QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow4() const
{
return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(1, 1));
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane1() const
{
return m_PlaneNode1;
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane2() const
{
return m_PlaneNode2;
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane3() const
{
return m_PlaneNode3;
}
mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane(unsigned number) const
{
switch (number)
{
case 1:
return m_PlaneNode1;
case 2:
return m_PlaneNode2;
case 3:
return m_PlaneNode3;
default:
MITK_ERROR << "Requested unknown render window";
break;
}
return nullptr;
}
void QmitkStdMultiWidget::SetDecorationColor(unsigned int widgetNumber, mitk::Color color)
{
switch (widgetNumber)
{
case 0:
if (m_PlaneNode1.IsNotNull())
{
m_PlaneNode1->SetColor(color);
}
break;
case 1:
if (m_PlaneNode2.IsNotNull())
{
m_PlaneNode2->SetColor(color);
}
break;
case 2:
if (m_PlaneNode3.IsNotNull())
{
m_PlaneNode3->SetColor(color);
}
break;
case 3:
m_DecorationColorWidget4 = color;
break;
default:
MITK_ERROR << "Decoration color for unknown widget!";
break;
}
}
mitk::Color QmitkStdMultiWidget::GetDecorationColor(unsigned int widgetNumber)
{
// The implementation looks a bit messy here, but it avoids
// synchronization of the color of the geometry nodes and an
// internal member here.
// Default colors were chosen for decent visibility.
// Feel free to change your preferences in the workbench.
float tmp[3] = { 0.0f, 0.0f, 0.0f };
switch (widgetNumber)
{
case 0:
{
if (m_PlaneNode1.IsNotNull())
{
if (m_PlaneNode1->GetColor(tmp))
{
return dynamic_cast<mitk::ColorProperty *>(m_PlaneNode1->GetProperty("color"))->GetColor();
}
}
float red[3] = { 0.753f, 0.0f, 0.0f }; // This is #C00000 in hex
return mitk::Color(red);
}
case 1:
{
if (m_PlaneNode2.IsNotNull())
{
if (m_PlaneNode2->GetColor(tmp))
{
return dynamic_cast<mitk::ColorProperty *>(m_PlaneNode2->GetProperty("color"))->GetColor();
}
}
float green[3] = { 0.0f, 0.69f, 0.0f }; // This is #00B000 in hex
return mitk::Color(green);
}
case 2:
{
if (m_PlaneNode3.IsNotNull())
{
if (m_PlaneNode3->GetColor(tmp))
{
return dynamic_cast<mitk::ColorProperty *>(m_PlaneNode3->GetProperty("color"))->GetColor();
}
}
float blue[3] = { 0.0, 0.502f, 1.0f }; // This is #0080FF in hex
return mitk::Color(blue);
}
case 3:
{
return m_DecorationColorWidget4;
}
default:
MITK_ERROR << "Decoration color for unknown widget!";
float black[3] = { 0.0f, 0.0f, 0.0f };
return mitk::Color(black);
}
}
void QmitkStdMultiWidget::mousePressEvent(QMouseEvent*)
{
// nothing here, but necessary for mouse interactions (.xml-configuration files)
}
void QmitkStdMultiWidget::moveEvent(QMoveEvent* e)
{
QWidget::moveEvent(e);
// it is necessary to readjust the position of the Annotation as the StdMultiWidget has moved
// unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here
emit Moved();
}
void QmitkStdMultiWidget::wheelEvent(QWheelEvent* e)
{
emit WheelMoved(e);
}
void QmitkStdMultiWidget::Fit()
{
vtkSmartPointer<vtkRenderer> vtkrenderer;
vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow1()->renderWindow())->GetVtkRenderer();
if (nullptr != vtkrenderer)
{
vtkrenderer->ResetCamera();
}
vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow2()->renderWindow())->GetVtkRenderer();
if (nullptr != vtkrenderer)
{
vtkrenderer->ResetCamera();
}
vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow3()->renderWindow())->GetVtkRenderer();
if (nullptr != vtkrenderer)
{
vtkrenderer->ResetCamera();
}
vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow4()->renderWindow())->GetVtkRenderer();
if (nullptr != vtkrenderer)
{
vtkrenderer->ResetCamera();
}
mitk::BaseRenderer::GetInstance(GetRenderWindow1()->renderWindow())->GetCameraController()->Fit();
mitk::BaseRenderer::GetInstance(GetRenderWindow2()->renderWindow())->GetCameraController()->Fit();
mitk::BaseRenderer::GetInstance(GetRenderWindow3()->renderWindow())->GetCameraController()->Fit();
mitk::BaseRenderer::GetInstance(GetRenderWindow4()->renderWindow())->GetCameraController()->Fit();
int w = vtkObject::GetGlobalWarningDisplay();
vtkObject::GlobalWarningDisplayOff();
vtkObject::SetGlobalWarningDisplay(w);
}
void QmitkStdMultiWidget::AddDisplayPlaneSubTree()
{
// add the displayed planes of the multiwidget to a node to which the subtree
// @a planesSubTree points ...
mitk::PlaneGeometryDataMapper2D::Pointer mapper;
// ... of widget 1
mitk::BaseRenderer* renderer1 = mitk::BaseRenderer::GetInstance(GetRenderWindow1()->renderWindow());
m_PlaneNode1 = renderer1->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode1->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode1->SetProperty("name", mitk::StringProperty::New(std::string(renderer1->GetName()) + ".plane"));
m_PlaneNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode1->SetProperty("helper object", mitk::BoolProperty::New(true));
mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
// ... of widget 2
mitk::BaseRenderer* renderer2 = mitk::BaseRenderer::GetInstance(GetRenderWindow2()->renderWindow());
m_PlaneNode2 = renderer2->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode2->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode2->SetProperty("name", mitk::StringProperty::New(std::string(renderer2->GetName()) + ".plane"));
m_PlaneNode2->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode2->SetProperty("helper object", mitk::BoolProperty::New(true));
mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode2->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
// ... of widget 3
mitk::BaseRenderer *renderer3 = mitk::BaseRenderer::GetInstance(GetRenderWindow3()->renderWindow());
m_PlaneNode3 = renderer3->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode3->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode3->SetProperty("name", mitk::StringProperty::New(std::string(renderer3->GetName()) + ".plane"));
m_PlaneNode3->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_PlaneNode3->SetProperty("helper object", mitk::BoolProperty::New(true));
mapper = mitk::PlaneGeometryDataMapper2D::New();
m_PlaneNode3->SetMapper(mitk::BaseRenderer::Standard2D, mapper);
m_ParentNodeForGeometryPlanes = mitk::DataNode::New();
m_ParentNodeForGeometryPlanes->SetProperty("name", mitk::StringProperty::New("Widgets"));
m_ParentNodeForGeometryPlanes->SetProperty("helper object", mitk::BoolProperty::New(true));
}
void QmitkStdMultiWidget::EnsureDisplayContainsPoint(mitk::BaseRenderer *renderer, const mitk::Point3D &p)
{
mitk::Point2D pointOnDisplay;
renderer->WorldToDisplay(p, pointOnDisplay);
if (pointOnDisplay[0] < renderer->GetVtkRenderer()->GetOrigin()[0] ||
pointOnDisplay[1] < renderer->GetVtkRenderer()->GetOrigin()[1] ||
pointOnDisplay[0] > renderer->GetVtkRenderer()->GetOrigin()[0] + renderer->GetViewportSize()[0] ||
pointOnDisplay[1] > renderer->GetVtkRenderer()->GetOrigin()[1] + renderer->GetViewportSize()[1])
{
mitk::Point2D pointOnPlane;
renderer->GetCurrentWorldPlaneGeometry()->Map(p, pointOnPlane);
renderer->GetCameraController()->MoveCameraToPoint(pointOnPlane);
}
}
void QmitkStdMultiWidget::SetWidgetPlaneVisibility(const char *widgetName, bool visible, mitk::BaseRenderer *renderer)
{
auto dataStorage = GetDataStorage();
if (nullptr != dataStorage)
{
mitk::DataNode* dataNode = dataStorage->GetNamedNode(widgetName);
if (dataNode != nullptr)
{
dataNode->SetVisibility(visible, renderer);
}
}
}
void QmitkStdMultiWidget::SetWidgetPlanesVisibility(bool visible, mitk::BaseRenderer *renderer)
{
if (m_PlaneNode1.IsNotNull())
{
m_PlaneNode1->SetVisibility(visible, renderer);
}
if (m_PlaneNode2.IsNotNull())
{
m_PlaneNode2->SetVisibility(visible, renderer);
}
if (m_PlaneNode3.IsNotNull())
{
m_PlaneNode3->SetVisibility(visible, renderer);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
//////////////////////////////////////////////////////////////////////////
// PRIVATE
//////////////////////////////////////////////////////////////////////////
void QmitkStdMultiWidget::SetLayoutImpl()
{
CreateRenderWindowWidgets();
GetMultiWidgetLayoutManager()->SetLayoutDesign(QmitkMultiWidgetLayoutManager::LayoutDesign::DEFAULT);
// Initialize views as axial, sagittal, coronal to all data objects in DataStorage
auto geo = GetDataStorage()->ComputeBoundingGeometry3D(GetDataStorage()->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(geo);
}
void QmitkStdMultiWidget::CreateRenderWindowWidgets()
{
// create axial render window (widget)
QString renderWindowWidgetName = GetNameFromIndex(0, 0);
RenderWindowWidgetPointer renderWindowWidget1 = std::make_shared<QmitkRenderWindowWidget>(this, renderWindowWidgetName, GetDataStorage());
auto renderWindow1 = renderWindowWidget1->GetRenderWindow();
renderWindow1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Axial);
renderWindowWidget1->SetDecorationColor(GetDecorationColor(0));
renderWindowWidget1->SetCornerAnnotationText("Axial");
renderWindowWidget1->GetRenderWindow()->SetLayoutIndex(mitk::AnatomicalPlane::Axial);
AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget1);
// create sagittal render window (widget)
renderWindowWidgetName = GetNameFromIndex(0, 1);
RenderWindowWidgetPointer renderWindowWidget2 = std::make_shared<QmitkRenderWindowWidget>(this, renderWindowWidgetName, GetDataStorage());
auto renderWindow2 = renderWindowWidget2->GetRenderWindow();
renderWindow2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Sagittal);
renderWindowWidget2->SetDecorationColor(GetDecorationColor(1));
renderWindowWidget2->setStyleSheet("border: 0px");
renderWindowWidget2->SetCornerAnnotationText("Sagittal");
renderWindowWidget2->GetRenderWindow()->SetLayoutIndex(mitk::AnatomicalPlane::Sagittal);
AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget2);
// create coronal render window (widget)
renderWindowWidgetName = GetNameFromIndex(1, 0);
RenderWindowWidgetPointer renderWindowWidget3 = std::make_shared<QmitkRenderWindowWidget>(this, renderWindowWidgetName, GetDataStorage());
auto renderWindow3 = renderWindowWidget3->GetRenderWindow();
renderWindow3->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Coronal);
renderWindowWidget3->SetDecorationColor(GetDecorationColor(2));
renderWindowWidget3->SetCornerAnnotationText("Coronal");
renderWindowWidget3->GetRenderWindow()->SetLayoutIndex(mitk::AnatomicalPlane::Coronal);
AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget3);
// create 3D render window (widget)
renderWindowWidgetName = GetNameFromIndex(1, 1);
RenderWindowWidgetPointer renderWindowWidget4 = std::make_shared<QmitkRenderWindowWidget>(this, renderWindowWidgetName, GetDataStorage());
auto renderWindow4 = renderWindowWidget4->GetRenderWindow();
renderWindow4->GetSliceNavigationController()->SetDefaultViewDirection(mitk::AnatomicalPlane::Original);
renderWindowWidget4->SetDecorationColor(GetDecorationColor(3));
renderWindowWidget4->SetCornerAnnotationText("3D");
renderWindowWidget4->GetRenderWindow()->SetLayoutIndex(mitk::AnatomicalPlane::Original);
mitk::BaseRenderer::GetInstance(renderWindowWidget4->GetRenderWindow()->renderWindow())->SetMapperID(mitk::BaseRenderer::Standard3D);
AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget4);
SetActiveRenderWindowWidget(renderWindowWidget1);
- // connect to the "time navigation controller": send time via sliceNavigationControllers
- m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow1->GetSliceNavigationController());
- m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow2->GetSliceNavigationController());
- m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow3->GetSliceNavigationController());
- m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow4->GetSliceNavigationController());
- renderWindow1->GetSliceNavigationController()->ConnectGeometrySendEvent(
- mitk::BaseRenderer::GetInstance(renderWindow4->renderWindow()));
-
- // reverse connection between sliceNavigationControllers and timeNavigationController
- renderWindow1->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
- renderWindow2->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
- renderWindow3->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
- //renderWindow4->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController);
-
auto layoutManager = GetMultiWidgetLayoutManager();
connect(renderWindow1, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair);
connect(renderWindow1, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility);
connect(renderWindow1, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode);
connect(renderWindow1, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairVisibilityChanged, renderWindow1, &QmitkRenderWindow::UpdateCrosshairVisibility);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairRotationModeChanged, renderWindow1, &QmitkRenderWindow::UpdateCrosshairRotationMode);
connect(renderWindow2, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair);
connect(renderWindow2, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility);
connect(renderWindow2, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode);
connect(renderWindow2, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairVisibilityChanged, renderWindow2, &QmitkRenderWindow::UpdateCrosshairVisibility);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairRotationModeChanged, renderWindow2, &QmitkRenderWindow::UpdateCrosshairRotationMode);
connect(renderWindow3, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair);
connect(renderWindow3, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility);
connect(renderWindow3, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode);
connect(renderWindow3, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairVisibilityChanged, renderWindow3, &QmitkRenderWindow::UpdateCrosshairVisibility);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairRotationModeChanged, renderWindow3, &QmitkRenderWindow::UpdateCrosshairRotationMode);
connect(renderWindow4, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair);
connect(renderWindow4, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility);
connect(renderWindow4, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode);
connect(renderWindow4, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairVisibilityChanged, renderWindow4, &QmitkRenderWindow::UpdateCrosshairVisibility);
connect(this, &QmitkStdMultiWidget::NotifyCrosshairRotationModeChanged, renderWindow4, &QmitkRenderWindow::UpdateCrosshairRotationMode);
}
diff --git a/Modules/QtWidgets/src/QmitkStyleManager.cpp b/Modules/QtWidgets/src/QmitkStyleManager.cpp
index cdb10e0262..9e9e854b12 100644
--- a/Modules/QtWidgets/src/QmitkStyleManager.cpp
+++ b/Modules/QtWidgets/src/QmitkStyleManager.cpp
@@ -1,86 +1,86 @@
/*============================================================================
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 <QmitkStyleManager.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <QApplication>
#include <QFile>
#include <QImage>
#include <QPixmap>
#include <QRegularExpression>
namespace
{
QString ParseColor(const QString &subject, const QString &colorName, const QString &fallback)
{
const QString pattern = QString("%1\\s*[=:]\\s*(#[0-9a-f]{6})").arg(colorName);
QRegularExpression re(pattern, QRegularExpression::CaseInsensitiveOption);
auto match = re.match(subject);
return match.hasMatch()
? match.captured(1)
: fallback;
}
}
QIcon QmitkStyleManager::ThemeIcon(const QByteArray &originalSVG)
{
auto styleSheet = qApp->styleSheet();
if (styleSheet.isEmpty())
return QPixmap::fromImage(QImage::fromData(originalSVG));
auto iconColor = GetIconColor();
auto iconAccentColor = GetIconAccentColor();
auto themedSVG = QString(originalSVG).replace(QStringLiteral("#00ff00"), iconColor, Qt::CaseInsensitive);
themedSVG = themedSVG.replace(QStringLiteral("#ff00ff"), iconAccentColor, Qt::CaseInsensitive);
return QPixmap::fromImage(QImage::fromData(themedSVG.toLatin1()));
}
QIcon QmitkStyleManager::ThemeIcon(const QString &resourcePath)
{
QFile resourceFile(resourcePath);
if (resourceFile.open(QIODevice::ReadOnly))
{
auto originalSVG = resourceFile.readAll();
return ThemeIcon(originalSVG);
}
MITK_WARN << "Could not read " << resourcePath.toStdString();
return QIcon();
}
QString QmitkStyleManager::GetIconColor()
{
const auto styleSheet = qApp->styleSheet();
const auto fallback = QStringLiteral("#000000");
return !styleSheet.isEmpty()
? ParseColor(styleSheet, QStringLiteral("iconColor"), fallback)
: fallback;
}
QString QmitkStyleManager::GetIconAccentColor()
{
const auto styleSheet = qApp->styleSheet();
const auto fallback = QStringLiteral("#ffffff");
return !styleSheet.isEmpty()
? ParseColor(styleSheet, QStringLiteral("iconAccentColor"), fallback)
: fallback;
}
diff --git a/Modules/QtWidgets/src/mitkDataStorageInspectorGenerator.cpp b/Modules/QtWidgets/src/mitkDataStorageInspectorGenerator.cpp
index 9f1ab8d13c..0c0a5aeed8 100644
--- a/Modules/QtWidgets/src/mitkDataStorageInspectorGenerator.cpp
+++ b/Modules/QtWidgets/src/mitkDataStorageInspectorGenerator.cpp
@@ -1,57 +1,57 @@
/*============================================================================
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 "usModuleContext.h"
#include "usGetModuleContext.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include "mitkDataStorageInspectorGenerator.h"
mitk::IDataStorageInspectorProvider* mitk::DataStorageInspectorGenerator::GetProvider(const IDType& id)
{
mitk::IDataStorageInspectorProvider* result = nullptr;
std::string filter = "(" + mitk::IDataStorageInspectorProvider::PROP_INSPECTOR_ID() + "=" + id + ")";
std::vector<us::ServiceReference<mitk::IDataStorageInspectorProvider> > providerRegisters = us::GetModuleContext()->GetServiceReferences<mitk::IDataStorageInspectorProvider>(filter);
if (!providerRegisters.empty())
{
if (providerRegisters.size() > 1)
{
MITK_WARN << "Multiple provider for class id'" << id << "' found. Using just one.";
}
result = us::GetModuleContext()->GetService<mitk::IDataStorageInspectorProvider>(providerRegisters.front());
}
return result;
};
mitk::DataStorageInspectorGenerator::ProviderMapType mitk::DataStorageInspectorGenerator::GetProviders()
{
std::vector<us::ServiceReference<mitk::IDataStorageInspectorProvider> > providerRegisters = us::GetModuleContext()->GetServiceReferences<mitk::IDataStorageInspectorProvider>();
ProviderMapType result;
for (const auto &regs : providerRegisters)
{
auto provider = us::GetModuleContext()->GetService<mitk::IDataStorageInspectorProvider>(regs);
result.insert(std::make_pair(provider->GetInspectorID(), provider));
}
return result;
};
mitk::DataStorageInspectorGenerator::DataStorageInspectorGenerator()
= default;
mitk::DataStorageInspectorGenerator::~DataStorageInspectorGenerator()
= default;
diff --git a/Modules/QtWidgets/test/QmitkThreadedLogTest.cpp b/Modules/QtWidgets/test/QmitkThreadedLogTest.cpp
index 8f1b8d43b5..87430b2647 100644
--- a/Modules/QtWidgets/test/QmitkThreadedLogTest.cpp
+++ b/Modules/QtWidgets/test/QmitkThreadedLogTest.cpp
@@ -1,108 +1,108 @@
/*============================================================================
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 "mitkCommon.h"
#include "mitkTestingMacros.h"
#include <itksys/SystemTools.hxx>
-#include <mitkLog.h>
+#include <mitkLogBackend.h>
#include <mitkStandardFileLocations.h>
#include <string>
#include <QtConcurrentRun>
void LogMessages(unsigned int threadID, unsigned int numberOfTimes)
{
unsigned int times = 0;
while (times < numberOfTimes)
{
MITK_INFO << "Test info stream in thread" << threadID << "\n even with newlines";
MITK_WARN << "Test warning stream in thread " << threadID << ". "
<< "Even with a very long text, even without meaning or implied meaning or content, just a long sentence "
"to see whether something has problems with long sentences or output in files or into windows or "
"commandlines or whatever.";
MITK_DEBUG << "Test debugging stream in thread " << threadID;
MITK_ERROR << "Test error stream in thread " << threadID;
MITK_FATAL << "Test fatal stream in thread " << threadID;
times += 5;
}
}
/**
\brief Test logging from Qt threads
*/
static void TestThreadSaveLog(bool toFile)
{
bool testSucceded = true;
try
{
if (toFile)
{
std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + "/qtestthreadlog.log";
itksys::SystemTools::RemoveFile(filename.c_str()); // remove old file, we do not want to append to large files
- mitk::LoggingBackend::SetLogFile(filename.c_str());
+ mitk::LogBackend::SetLogFile(filename);
}
unsigned int numberOfThreads = 10;
unsigned int threadRuntimeInMilliseconds = 4000;
QVector<QFuture<void>> threads;
// Spawn some threads
for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
{
threads.push_back(QtConcurrent::run(LogMessages, threadIdx, 100));
std::cout << "Created " << threadIdx << ". thread." << std::endl;
}
// wait for some time (milliseconds)
itksys::SystemTools::Delay(threadRuntimeInMilliseconds);
// Wait for all to finish
for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
{
threads[threadIdx].waitForFinished();
std::cout << threadIdx << ". thread has finished" << std::endl;
}
}
catch (std::exception e)
{
MITK_ERROR << "exception during 'TestThreadSaveLog': " << e.what();
testSucceded = false;
}
catch (...)
{
MITK_ERROR << "unknown exception during 'TestThreadSaveLog'";
testSucceded = false;
}
// if no error occured until now, everything is ok
MITK_TEST_CONDITION_REQUIRED(testSucceded, "Test logging in different threads.");
}
int QmitkThreadedLogTest(int /* argc */, char * /*argv*/ [])
{
// always start with this!
MITK_TEST_BEGIN("QmitkThreadedLogTest")
MITK_TEST_OUTPUT(<< "TESTING ALL LOGGING OUTPUTS, ERROR MESSAGES ARE ALSO TESTED AND NOT MEANING AN ERROR OCCURED!")
TestThreadSaveLog(false); // false = to console
TestThreadSaveLog(true); // true = to file
MITK_TEST_OUTPUT(<< "Number of threads in QThreadPool: " << QThreadPool::globalInstance()->maxThreadCount())
// always end with this!
MITK_TEST_END()
}
diff --git a/Modules/QtWidgetsExt/src/QmitkSliceWidget.cpp b/Modules/QtWidgetsExt/src/QmitkSliceWidget.cpp
index 3a8462c70b..7cfbb790eb 100644
--- a/Modules/QtWidgetsExt/src/QmitkSliceWidget.cpp
+++ b/Modules/QtWidgetsExt/src/QmitkSliceWidget.cpp
@@ -1,266 +1,266 @@
/*============================================================================
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 "QmitkSliceWidget.h"
#include "QmitkStepperAdapter.h"
#include "mitkCameraController.h"
#include "mitkImage.h"
#include "mitkNodePredicateDataType.h"
#include <QMenu>
#include <QMouseEvent>
#include <mitkCameraController.h>
#include <mitkProportionalTimeGeometry.h>
QmitkSliceWidget::QmitkSliceWidget(QWidget *parent, const char *name, Qt::WindowFlags f) : QWidget(parent, f)
{
this->setupUi(this);
if (name != nullptr)
this->setObjectName(name);
popUp = new QMenu(this);
popUp->addAction("Axial");
popUp->addAction("Coronal");
popUp->addAction("Sagittal");
QObject::connect(popUp, SIGNAL(triggered(QAction *)), this, SLOT(ChangeView(QAction *)));
setPopUpEnabled(false);
m_SlicedGeometry = nullptr;
m_View = mitk::AnatomicalPlane::Axial;
QHBoxLayout *hlayout = new QHBoxLayout(container);
hlayout->setMargin(0);
// create widget
QString composedName("QmitkSliceWidget::");
if (!this->objectName().isEmpty())
composedName += this->objectName();
else
composedName += "QmitkGLWidget";
m_RenderWindow = new QmitkRenderWindow(container, composedName);
m_Renderer = m_RenderWindow->GetRenderer();
hlayout->addWidget(m_RenderWindow);
- new QmitkStepperAdapter(sliceNavigationWidget, m_RenderWindow->GetSliceNavigationController()->GetSlice());
+ new QmitkStepperAdapter(sliceNavigationWidget, m_RenderWindow->GetSliceNavigationController()->GetStepper());
SetLevelWindowEnabled(true);
}
mitk::VtkPropRenderer *QmitkSliceWidget::GetRenderer()
{
return m_Renderer;
}
QFrame *QmitkSliceWidget::GetSelectionFrame()
{
return SelectionFrame;
}
void QmitkSliceWidget::SetDataStorage(mitk::StandaloneDataStorage::Pointer storage)
{
m_DataStorage = storage;
m_Renderer->SetDataStorage(m_DataStorage);
}
mitk::StandaloneDataStorage *QmitkSliceWidget::GetDataStorage()
{
return m_DataStorage;
}
void QmitkSliceWidget::SetData(mitk::DataStorage::SetOfObjects::ConstIterator it)
{
SetData(it->Value(), m_View);
}
void QmitkSliceWidget::SetData(mitk::DataStorage::SetOfObjects::ConstIterator it,
mitk::AnatomicalPlane view)
{
SetData(it->Value(), view);
}
void QmitkSliceWidget::SetData(mitk::DataNode::Pointer node)
{
try
{
if (m_DataStorage.IsNotNull())
{
m_DataStorage->Add(node);
}
}
catch (...)
{
}
SetData(node, m_View);
}
void QmitkSliceWidget::SetData(mitk::DataNode::Pointer node, mitk::AnatomicalPlane view)
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(node->GetData());
if (image.IsNull())
{
MITK_WARN << "QmitkSliceWidget data is not an image!";
return;
}
m_SlicedGeometry = image->GetSlicedGeometry();
this->InitWidget(view);
}
void QmitkSliceWidget::InitWidget(mitk::AnatomicalPlane view)
{
m_View = view;
mitk::SliceNavigationController *controller = m_RenderWindow->GetSliceNavigationController();
if (view == mitk::AnatomicalPlane::Axial)
{
controller->SetViewDirection(mitk::AnatomicalPlane::Axial);
}
else if (view == mitk::AnatomicalPlane::Coronal)
{
controller->SetViewDirection(mitk::AnatomicalPlane::Coronal);
}
// init sagittal view for all other cases ('original' is covered here as well)
else
{
controller->SetViewDirection(mitk::AnatomicalPlane::Sagittal);
}
if (m_SlicedGeometry.IsNull())
{
return;
}
mitk::BaseGeometry::Pointer geometry = static_cast<mitk::BaseGeometry *>(m_SlicedGeometry->Clone().GetPointer());
const mitk::BoundingBox::Pointer boundingbox = m_DataStorage->ComputeVisibleBoundingBox(GetRenderer(), nullptr);
if (boundingbox->GetPoints()->Size() > 0)
{
// let's see if we have data with a limited live-span ...
mitk::TimeBounds timebounds = m_DataStorage->ComputeTimeBounds(GetRenderer(), nullptr);
mitk::ProportionalTimeGeometry::Pointer timeGeometry = mitk::ProportionalTimeGeometry::New();
timeGeometry->Initialize(geometry, 1);
{
timeGeometry->SetFirstTimePoint(timebounds[0]);
timeGeometry->SetStepDuration(1.0);
}
if (timeGeometry->GetBoundingBoxInWorld()->GetDiagonalLength2() >= mitk::eps)
{
controller->SetInputWorldTimeGeometry(timeGeometry);
controller->Update();
}
}
GetRenderer()->GetCameraController()->Fit();
mitk::RenderingManager::GetInstance()->RequestUpdate(GetRenderer()->GetRenderWindow());
}
void QmitkSliceWidget::UpdateGL()
{
GetRenderer()->GetCameraController()->Fit();
mitk::RenderingManager::GetInstance()->RequestUpdate(GetRenderer()->GetRenderWindow());
}
void QmitkSliceWidget::mousePressEvent(QMouseEvent *e)
{
if (e->button() == Qt::RightButton && popUpEnabled)
{
popUp->popup(QCursor::pos());
}
}
void QmitkSliceWidget::wheelEvent(QWheelEvent *e)
{
int val = sliceNavigationWidget->GetPos();
if (e->orientation() * e->delta() > 0)
{
sliceNavigationWidget->SetPos(val + 1);
}
else
{
if (val > 0)
sliceNavigationWidget->SetPos(val - 1);
}
}
void QmitkSliceWidget::ChangeView(QAction *val)
{
if (val->text() == "Axial")
{
InitWidget(mitk::AnatomicalPlane::Axial);
}
else if (val->text() == "Coronal")
{
InitWidget(mitk::AnatomicalPlane::Coronal);
}
else if (val->text() == "Sagittal")
{
InitWidget(mitk::AnatomicalPlane::Sagittal);
}
}
void QmitkSliceWidget::setPopUpEnabled(bool b)
{
popUpEnabled = b;
}
QmitkSliceNavigationWidget* QmitkSliceWidget::GetSliceNavigationWidget()
{
return sliceNavigationWidget;
}
void QmitkSliceWidget::SetLevelWindowEnabled(bool enable)
{
levelWindow->setEnabled(enable);
if (!enable)
{
levelWindow->setMinimumWidth(0);
levelWindow->setMaximumWidth(0);
}
else
{
levelWindow->setMinimumWidth(28);
levelWindow->setMaximumWidth(28);
}
}
bool QmitkSliceWidget::IsLevelWindowEnabled()
{
return levelWindow->isEnabled();
}
QmitkRenderWindow *QmitkSliceWidget::GetRenderWindow()
{
return m_RenderWindow;
}
mitk::SliceNavigationController *QmitkSliceWidget::GetSliceNavigationController() const
{
return m_RenderWindow->GetSliceNavigationController();
}
mitk::CameraRotationController *QmitkSliceWidget::GetCameraRotationController() const
{
return m_RenderWindow->GetCameraRotationController();
}
mitk::BaseController *QmitkSliceWidget::GetController() const
{
return m_RenderWindow->GetController();
}
diff --git a/Modules/RESTService/src/mitkRESTManager.cpp b/Modules/RESTService/src/mitkRESTManager.cpp
index 0e1962835e..1f59480cd6 100644
--- a/Modules/RESTService/src/mitkRESTManager.cpp
+++ b/Modules/RESTService/src/mitkRESTManager.cpp
@@ -1,258 +1,258 @@
/*============================================================================
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 <mitkIRESTObserver.h>
#include <mitkRESTClient.h>
#include <mitkRESTManager.h>
#include <mitkRESTServer.h>
#include <mitkExceptionMacro.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
mitk::RESTManager::RESTManager() {}
mitk::RESTManager::~RESTManager() {}
pplx::task<web::json::value> mitk::RESTManager::SendRequest(
const web::uri &uri, const RequestType &type, const std::map<utility::string_t, utility::string_t> headers)
{
pplx::task<web::json::value> answer;
auto client = new RESTClient;
switch (type)
{
case RequestType::Get:
answer = client->Get(uri, headers);
break;
default:
mitkThrow() << "Request Type not supported";
}
return answer;
}
pplx::task<web::json::value> mitk::RESTManager::SendBinaryRequest(
const web::uri &uri,
const RequestType &type,
const std::vector<unsigned char> *content,
const std::map<utility::string_t, utility::string_t> headers)
{
pplx::task<web::json::value> answer;
auto client = new RESTClient;
switch (type)
{
case RequestType::Post:
if (nullptr == content)
MITK_WARN << "Content for post is empty, this will create an empty resource";
answer = client->Post(uri, content, headers);
break;
default:
mitkThrow() << "Request Type not supported for binary data";
}
return answer;
}
pplx::task<web::json::value> mitk::RESTManager::SendJSONRequest(
const web::uri &uri,
const RequestType &type,
const web::json::value *content,
const std::map<utility::string_t, utility::string_t> headers,
const utility::string_t &filePath)
{
pplx::task<web::json::value> answer;
auto client = new RESTClient;
switch (type)
{
case RequestType::Get:
answer = !filePath.empty() ? client->Get(uri, filePath, headers) : client->Get(uri, headers);
break;
case RequestType::Post:
if (nullptr == content)
MITK_WARN << "Content for post is empty, this will create an empty resource";
answer = client->Post(uri, content, headers);
break;
case RequestType::Put:
if (nullptr == content)
MITK_WARN << "Content for put is empty, this will empty the ressource";
answer = client->Put(uri, content);
break;
default:
mitkThrow() << "Request Type not supported";
}
return answer;
}
void mitk::RESTManager::ReceiveRequest(const web::uri &uri, mitk::IRESTObserver *observer)
{
// New instance of RESTServer in m_ServerMap, key is port of the request
auto port = uri.port();
// Checking if port is free to add a new Server
if (0 == m_ServerMap.count(port))
{
this->AddObserver(uri, observer);
// creating server instance
auto server = new RESTServer(uri.authority());
// add reference to server instance to map
m_ServerMap[port] = server;
// start Server
server->OpenListener();
}
// If there is already a server under this port
else
{
this->RequestForATakenPort(uri, observer);
}
}
web::http::http_response mitk::RESTManager::Handle(const web::uri &uri,
const web::json::value &body,
const web::http::method &method,
const mitk::RESTUtil::ParamMap &headers)
{
// Checking if there is an observer for the port and path
auto key = std::make_pair(uri.port(), uri.path());
if (0 != m_Observers.count(key))
{
return m_Observers[key]->Notify(uri, body, method, headers);
}
// No observer under this port, return null which results in status code 404 (s. RESTServer)
else
{
MITK_WARN << "No Observer can handle the data";
web::http::http_response response(web::http::status_codes::BadGateway);
response.set_body(U("No one can handle the request under the given port."));
return response;
}
}
void mitk::RESTManager::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri)
{
for (auto it = m_Observers.begin(); it != m_Observers.end();)
{
mitk::IRESTObserver *obsMap = it->second;
// Check wether observer is at this place in map
if (observer == obsMap)
{
// Check wether it is the right uri to be deleted
if (uri.is_empty() || uri.path() == it->first.second)
{
int port = it->first.first;
bool noObserverForPort = this->DeleteObserver(it);
if (noObserverForPort)
{
// there isn't an observer at this port, delete m_ServerMap entry for this port
// close listener
m_ServerMap[port]->CloseListener();
delete m_ServerMap[port];
// delete server from map
m_ServerMap.erase(port);
}
}
else
{
++it;
}
}
else
{
++it;
}
}
}
const std::map<int, mitk::RESTServer *> &mitk::RESTManager::GetServerMap()
{
return m_ServerMap;
}
std::map<std::pair<int, utility::string_t>, mitk::IRESTObserver *> &mitk::RESTManager::GetObservers()
{
return m_Observers;
}
void mitk::RESTManager::AddObserver(const web::uri &uri, IRESTObserver *observer)
{
// new observer has to be added
std::pair<int, utility::string_t> key(uri.port(), uri.path());
m_Observers[key] = observer;
}
void mitk::RESTManager::RequestForATakenPort(const web::uri &uri, IRESTObserver *observer)
{
// Same host, means new observer but not a new server instance
if (uri.authority() == m_ServerMap[uri.port()]->GetUri())
{
// new observer has to be added
std::pair<int, utility::string_t> key(uri.port(), uri.path());
// only add a new observer if there isn't already an observer for this uri
if (0 == m_Observers.count(key))
{
this->AddObserver(uri, observer);
}
else
{
MITK_ERROR << "Threre is already a observer handeling this data";
}
}
// Error, since another server can't be added under this port
else
{
MITK_ERROR << "There is already another server listening under this port";
}
}
bool mitk::RESTManager::DeleteObserver(std::map<std::pair<int, utility::string_t>, IRESTObserver *>::iterator &it)
{
int port = it->first.first;
it = m_Observers.erase(it);
for (auto observer : m_Observers)
{
if (port == observer.first.first)
{
// there still exists an observer for this port
return false;
}
}
return true;
}
void mitk::RESTManager::SetServerMap(const int port, RESTServer *server)
{
m_ServerMap[port] = server;
}
void mitk::RESTManager::DeleteFromServerMap(const int port)
{
m_ServerMap.erase(port);
}
void mitk::RESTManager::SetObservers(const std::pair<int, utility::string_t> key, IRESTObserver *observer)
{
m_Observers[key] = observer;
}
diff --git a/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.cpp b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.cpp
index 6cfcd9af94..73cc2dd8a8 100644
--- a/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.cpp
+++ b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.cpp
@@ -1,271 +1,305 @@
/*============================================================================
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 "mitkContourModelSetToImageFilter.h"
#include <mitkContourModelSet.h>
#include <mitkContourModelUtils.h>
#include <mitkExtractSliceFilter.h>
#include <mitkImageWriteAccessor.h>
#include <mitkProgressBar.h>
#include <mitkTimeHelper.h>
-
+#include <mitkLabel.h>
#include <mitkVtkImageOverwrite.h>
mitk::ContourModelSetToImageFilter::ContourModelSetToImageFilter()
- : m_MakeOutputBinary(true), m_TimeStep(0), m_ReferenceImage(nullptr)
+ : m_MakeOutputBinary(true),
+ m_MakeOutputLabelPixelType(false),
+ m_PaintingPixelValue(1),
+ m_TimeStep(0),
+ m_ReferenceImage(nullptr)
{
// Create the output.
itk::DataObject::Pointer output = this->MakeOutput(0);
Superclass::SetNumberOfRequiredInputs(1);
Superclass::SetNumberOfRequiredOutputs(1);
Superclass::SetNthOutput(0, output);
}
mitk::ContourModelSetToImageFilter::~ContourModelSetToImageFilter()
{
}
+void mitk::ContourModelSetToImageFilter::SetMakeOutputBinary(bool makeOutputBinary)
+{
+ if (m_MakeOutputBinary != makeOutputBinary)
+ {
+ m_MakeOutputBinary = makeOutputBinary;
+
+ if (m_MakeOutputBinary)
+ m_MakeOutputLabelPixelType = false;
+
+ this->Modified();
+ }
+}
+
+void mitk::ContourModelSetToImageFilter::SetMakeOutputLabelPixelType(bool makeOutputLabelPixelType)
+{
+ if (m_MakeOutputLabelPixelType != makeOutputLabelPixelType)
+ {
+ m_MakeOutputLabelPixelType = makeOutputLabelPixelType;
+
+ if (m_MakeOutputLabelPixelType)
+ m_MakeOutputBinary = false;
+
+ this->Modified();
+ }
+}
+
void mitk::ContourModelSetToImageFilter::GenerateInputRequestedRegion()
{
mitk::Image *output = this->GetOutput();
if ((output->IsInitialized() == false))
return;
GenerateTimeInInputRegion(output, const_cast<mitk::Image *>(m_ReferenceImage));
}
void mitk::ContourModelSetToImageFilter::GenerateOutputInformation()
{
mitk::Image::Pointer output = this->GetOutput();
itkDebugMacro(<< "GenerateOutputInformation()");
if ((m_ReferenceImage == nullptr) || (m_ReferenceImage->IsInitialized() == false) ||
(m_ReferenceImage->GetTimeGeometry() == nullptr))
return;
- if (m_MakeOutputBinary)
+ if (m_MakeOutputLabelPixelType)
+ {
+ output->Initialize(mitk::MakeScalarPixelType<mitk::Label::PixelType>(), *m_ReferenceImage->GetTimeGeometry(), 1);
+ }
+ else if (m_MakeOutputBinary)
{
output->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *m_ReferenceImage->GetTimeGeometry(), 1);
}
else
{
output->Initialize(m_ReferenceImage->GetPixelType(), *m_ReferenceImage->GetTimeGeometry());
}
output->SetPropertyList(m_ReferenceImage->GetPropertyList()->Clone());
}
itk::DataObject::Pointer mitk::ContourModelSetToImageFilter::MakeOutput(DataObjectPointerArraySizeType /*idx*/)
{
return OutputType::New().GetPointer();
}
itk::DataObject::Pointer mitk::ContourModelSetToImageFilter::MakeOutput(const DataObjectIdentifierType &name)
{
itkDebugMacro("MakeOutput(" << name << ")");
if (this->IsIndexedOutputName(name))
{
return this->MakeOutput(this->MakeIndexFromOutputName(name));
}
return OutputType::New().GetPointer();
}
const mitk::ContourModelSet *mitk::ContourModelSetToImageFilter::GetInput(void)
{
if (this->GetNumberOfInputs() < 1)
{
return nullptr;
}
return static_cast<const mitk::ContourModelSet *>(this->ProcessObject::GetInput(0));
}
void mitk::ContourModelSetToImageFilter::SetInput(const ContourModelSet *input)
{
// Process object is not const-correct so the const_cast is required here
this->ProcessObject::SetNthInput(0, const_cast<mitk::ContourModelSet *>(input));
}
void mitk::ContourModelSetToImageFilter::SetImage(const mitk::Image *refImage)
{
m_ReferenceImage = refImage;
}
const mitk::Image *mitk::ContourModelSetToImageFilter::GetImage(void)
{
return m_ReferenceImage;
}
void mitk::ContourModelSetToImageFilter::GenerateData()
{
auto *contourSet = const_cast<mitk::ContourModelSet *>(this->GetInput());
// Initializing progressbar
unsigned int num_contours = contourSet->GetContourModelList()->size();
mitk::ProgressBar::GetInstance()->AddStepsToDo(num_contours);
// Assure that the volume data of the output is set (fill volume with zeros)
this->InitializeOutputEmpty();
mitk::Image::Pointer outputImage = const_cast<mitk::Image *>(this->GetOutput());
if (outputImage.IsNull() || outputImage->IsInitialized() == false || !outputImage->IsVolumeSet(m_TimeStep))
{
mitkThrow() << "Error creating output for specified image!";
}
if (!contourSet || contourSet->GetContourModelList()->size() == 0)
{
mitkThrow() << "No contours specified!";
}
mitk::BaseGeometry *outputImageGeo = outputImage->GetGeometry(m_TimeStep);
// Create mitkVtkImageOverwrite which is needed to write the slice back into the volume
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
// Create ExtractSliceFilter for extracting the corresponding slices from the volume
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput(outputImage);
extractor->SetTimeStep(m_TimeStep);
extractor->SetResliceTransformByGeometry(outputImageGeo);
// Fill each contour of the contourmodelset into the image
auto it = contourSet->Begin();
auto end = contourSet->End();
while (it != end)
{
mitk::ContourModel *contour = it->GetPointer();
// 1. Create slice geometry using the contour points
mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New();
mitk::Point3D point3D, tempPoint;
mitk::Vector3D normal;
mitk::Image::Pointer slice;
int sliceIndex;
bool isFrontside = true;
bool isRotated = false;
// Determine plane orientation
point3D = contour->GetVertexAt(0)->Coordinates;
tempPoint = contour->GetVertexAt(contour->GetNumberOfVertices() * 0.25)->Coordinates;
mitk::Vector3D vec = point3D - tempPoint;
vec.Normalize();
outputImageGeo->WorldToIndex(point3D, point3D);
mitk::AnatomicalPlane orientation;
if (mitk::Equal(vec[0], 0))
{
orientation = mitk::AnatomicalPlane::Sagittal;
sliceIndex = point3D[0];
}
else if (mitk::Equal(vec[1], 0))
{
orientation = mitk::AnatomicalPlane::Coronal;
sliceIndex = point3D[1];
}
else if (mitk::Equal(vec[2], 0))
{
orientation = mitk::AnatomicalPlane::Axial;
sliceIndex = point3D[2];
}
else
{
// TODO Maybe rotate geometry to extract slice?
MITK_ERROR
<< "Cannot detect correct slice number! Only axial, sagittal and coronal oriented contours are supported!";
return;
}
// Initialize plane using the detected orientation
plane->InitializeStandardPlane(outputImageGeo, orientation, sliceIndex, isFrontside, isRotated);
point3D = plane->GetOrigin();
normal = plane->GetNormal();
normal.Normalize();
point3D += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
plane->SetOrigin(point3D);
// 2. Extract slice at the given position
extractor->SetWorldGeometry(plane);
extractor->SetVtkOutputRequest(false);
reslice->SetOverwriteMode(false);
extractor->Modified();
extractor->Update();
slice = extractor->GetOutput();
slice->DisconnectPipeline();
// 3. Fill contour into slice
mitk::ContourModel::Pointer projectedContour =
mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contour);
- mitk::ContourModelUtils::FillContourInSlice(projectedContour, slice, outputImage);
+ mitk::ContourModelUtils::FillContourInSlice(projectedContour, slice, outputImage, m_PaintingPixelValue);
// 4. Write slice back into image volume
reslice->SetInputSlice(slice->GetVtkImageData());
// set overwrite mode to true to write back to the image volume
reslice->SetOverwriteMode(true);
reslice->Modified();
extractor->Modified();
extractor->Update();
reslice->SetInputSlice(nullptr);
// Progress
mitk::ProgressBar::GetInstance()->Progress();
++it;
}
outputImage->Modified();
outputImage->GetVtkImageData()->Modified();
}
void mitk::ContourModelSetToImageFilter::InitializeOutputEmpty()
{
// Initialize the output's volume with zeros
mitk::Image *output = this->GetOutput();
unsigned int byteSize = output->GetPixelType().GetSize();
if (output->GetDimension() < 4)
{
for (unsigned int dim = 0; dim < output->GetDimension(); ++dim)
{
byteSize *= output->GetDimension(dim);
}
mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(0));
memset(writeAccess.GetData(), 0, byteSize);
}
else
{
// if we have a time-resolved image we need to set memory to 0 for each time step
for (unsigned int dim = 0; dim < 3; ++dim)
{
byteSize *= output->GetDimension(dim);
}
for (unsigned int volumeNumber = 0; volumeNumber < output->GetDimension(3); volumeNumber++)
{
mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(volumeNumber));
memset(writeAccess.GetData(), 0, byteSize);
}
}
}
diff --git a/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.h b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.h
index 1d03c356e6..a19f46b578 100644
--- a/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.h
+++ b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.h
@@ -1,91 +1,100 @@
/*============================================================================
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 mitkContourModelSetToImageFilter_h
#define mitkContourModelSetToImageFilter_h
#include <MitkSegmentationExports.h>
#include <mitkImageSource.h>
namespace mitk
{
class ContourModelSet;
/**
* @brief Fills a given mitk::ContourModelSet into a given mitk::Image
* @ingroup Process
*/
class MITKSEGMENTATION_EXPORT ContourModelSetToImageFilter : public ImageSource
{
public:
mitkClassMacro(ContourModelSetToImageFilter, ImageSource);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
- itkSetMacro(MakeOutputBinary, bool);
- itkGetMacro(MakeOutputBinary, bool);
- itkBooleanMacro(MakeOutputBinary);
+ virtual void SetMakeOutputBinary(bool makeOutputBinary);
+ virtual void SetMakeOutputLabelPixelType(bool makeOutputLabelPixelType);
+ itkSetMacro(PaintingPixelValue, int);
itkSetMacro(TimeStep, unsigned int);
+ itkGetMacro(MakeOutputBinary, bool);
+ itkGetMacro(MakeOutputLabelPixelType, bool);
+ itkGetMacro(PaintingPixelValue, int);
+
+ itkBooleanMacro(MakeOutputBinary);
+ itkBooleanMacro(MakeOutputLabelPixelType);
+
/**
* Allocates a new output object and returns it. Currently the
* index idx is not evaluated.
* @param idx the index of the output for which an object should be created
* @returns the new object
*/
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override;
/**
* This is a default implementation to make sure we have something.
* Once all the subclasses of ProcessObject provide an appopriate
* MakeOutput(), then ProcessObject::MakeOutput() can be made pure
* virtual.
*/
itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name) override;
void GenerateInputRequestedRegion() override;
void GenerateOutputInformation() override;
void GenerateData() override;
const mitk::ContourModelSet *GetInput(void);
using itk::ProcessObject::SetInput;
virtual void SetInput(const mitk::ContourModelSet *input);
/**
* @brief Set the image which will be used to initialize the output of this filter.
* @param refImage the image used to initialize the output image
*/
void SetImage(const mitk::Image *refImage);
const mitk::Image *GetImage(void);
protected:
ContourModelSetToImageFilter();
~ContourModelSetToImageFilter() override;
/**
* @brief Initializes the volume of the output image with zeros
*/
void InitializeOutputEmpty();
bool m_MakeOutputBinary;
+ bool m_MakeOutputLabelPixelType;
+ int m_PaintingPixelValue;
unsigned int m_TimeStep;
const mitk::Image *m_ReferenceImage;
};
}
#endif
diff --git a/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp b/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp
index 6c666c1b36..fc8ce4fbdf 100644
--- a/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp
+++ b/Modules/Segmentation/Algorithms/mitkDiffSliceOperationApplier.cpp
@@ -1,89 +1,89 @@
/*============================================================================
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 "mitkDiffSliceOperationApplier.h"
#include "mitkDiffSliceOperation.h"
#include "mitkRenderingManager.h"
#include "mitkSegTool2D.h"
#include <mitkExtractSliceFilter.h>
#include <mitkVtkImageOverwrite.h>
// VTK
#include <vtkSmartPointer.h>
mitk::DiffSliceOperationApplier::DiffSliceOperationApplier()
{
}
mitk::DiffSliceOperationApplier::~DiffSliceOperationApplier()
{
}
void mitk::DiffSliceOperationApplier::ExecuteOperation(Operation *operation)
{
auto *imageOperation = dynamic_cast<DiffSliceOperation *>(operation);
// as we only support DiffSliceOperation return if operation is not type of DiffSliceOperation
if (!imageOperation)
return;
- // chak if the operation is valid
+ // check if the operation is valid
if (imageOperation->IsValid())
{
// the actual overwrite filter (vtk)
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
mitk::Image::Pointer slice = imageOperation->GetSlice();
// Set the slice as 'input'
reslice->SetInputSlice(slice->GetVtkImageData());
// set overwrite mode to true to write back to the image volume
reslice->SetOverwriteMode(true);
reslice->Modified();
// a wrapper for vtkImageOverwrite
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput(imageOperation->GetImage());
extractor->SetTimeStep(imageOperation->GetTimeStep());
extractor->SetWorldGeometry(dynamic_cast<const PlaneGeometry *>(imageOperation->GetWorldGeometry()));
extractor->SetVtkOutputRequest(true);
extractor->SetResliceTransformByGeometry(imageOperation->GetImage()->GetGeometry(imageOperation->GetTimeStep()));
extractor->Modified();
extractor->Update();
// make sure the modification is rendered
RenderingManager::GetInstance()->RequestUpdateAll();
imageOperation->GetImage()->Modified();
mitk::ExtractSliceFilter::Pointer extractor2 = mitk::ExtractSliceFilter::New();
extractor2->SetInput(imageOperation->GetImage());
extractor2->SetTimeStep(imageOperation->GetTimeStep());
extractor2->SetWorldGeometry(dynamic_cast<const PlaneGeometry *>(imageOperation->GetWorldGeometry()));
extractor2->SetResliceTransformByGeometry(imageOperation->GetImage()->GetGeometry(imageOperation->GetTimeStep()));
extractor2->Modified();
extractor2->Update();
// TODO Move this code to SurfaceInterpolationController!
mitk::Image::Pointer slice2 = extractor2->GetOutput();
mitk::PlaneGeometry::ConstPointer plane = dynamic_cast<const PlaneGeometry *>(imageOperation->GetWorldGeometry());
slice2->DisconnectPipeline();
mitk::SegTool2D::UpdateSurfaceInterpolation(slice2, imageOperation->GetImage(), plane, true);
}
}
mitk::DiffSliceOperationApplier *mitk::DiffSliceOperationApplier::GetInstance()
{
static auto *s_Instance = new DiffSliceOperationApplier();
return s_Instance;
}
diff --git a/Modules/Segmentation/Algorithms/mitkSegmentationHelper.cpp b/Modules/Segmentation/Algorithms/mitkSegmentationHelper.cpp
index c65ac2c200..8dac9a7fff 100644
--- a/Modules/Segmentation/Algorithms/mitkSegmentationHelper.cpp
+++ b/Modules/Segmentation/Algorithms/mitkSegmentationHelper.cpp
@@ -1,45 +1,45 @@
/*============================================================================
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 "mitkSegmentationHelper.h"
#include <mitkImageTimeSelector.h>
#include <mitkRenderingManager.h>
-#include <mitkSliceNavigationController.h>
+#include <mitkTimeNavigationController.h>
mitk::Image::Pointer mitk::SegmentationHelper::GetStaticSegmentationTemplate(const Image* referenceImage)
{
if (referenceImage == nullptr)
return nullptr;
const auto* referenceGeometry = referenceImage->GetTimeGeometry();
const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
const auto timeStep = referenceGeometry->IsValidTimePoint(timePoint)
? referenceGeometry->TimePointToTimeStep(timePoint)
: 0;
auto geometry = ProportionalTimeGeometry::New();
geometry->SetFirstTimePoint(referenceGeometry->GetMinimumTimePoint());
geometry->SetStepDuration(referenceGeometry->GetMaximumTimePoint() - referenceGeometry->GetMinimumTimePoint());
geometry->SetTimeStepGeometry(referenceImage->GetGeometry(timeStep), 0);
auto selector = mitk::ImageTimeSelector::New();
selector->SetInput(referenceImage);
selector->SetTimeNr(timeStep);
selector->Update();
Image::Pointer templateImage = selector->GetOutput();
templateImage->SetTimeGeometry(geometry);
return templateImage;
}
diff --git a/Modules/Segmentation/Algorithms/mitkVtkImageOverwrite.h b/Modules/Segmentation/Algorithms/mitkVtkImageOverwrite.h
index a48eeb9d9c..56f821ad56 100644
--- a/Modules/Segmentation/Algorithms/mitkVtkImageOverwrite.h
+++ b/Modules/Segmentation/Algorithms/mitkVtkImageOverwrite.h
@@ -1,84 +1,84 @@
/*============================================================================
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 mitkVtkImageOverwrite_h
#define mitkVtkImageOverwrite_h
#include <MitkSegmentationExports.h>
#include <vtkImageReslice.h>
/** \brief A vtk Filter based on vtkImageReslice with the aditional feature to write a slice into the given input
volume.
All optimizations for e.g. the plane directions or interpolation are stripped away, the algorithm only interpolates
nearest
neighbor and uses the non optimized execute function of vtkImageReslice. Note that any interpolation doesn't make
sense
-for round trip use extract->edit->overwrite, because it is nearly impossible to invert the interolation.
+for round trip use extract->edit->overwrite, because it is nearly impossible to invert the interpolation.
There are two use cases for the Filter which are specified by the overwritemode property:
1)Extract slices from a 3D volume.
Overwritemode = false
In this mode the class can be used like vtkImageReslice. The usual way to do this is:
- Set an image volume as input
- Set the ResliceAxes via SetResliceAxesDirectionCosines and SetResliceAxesOrigin
- Set the the OutputSpacing, OutputOrigin and OutputExtent
- Call Update
2)Overwrite a 3D volume at a given slice.
Overwritemode = true
The handling in this mode is quite similar to the description above with the addition that the
InputSlice needs to be specified via SetInputSlice(vtkImageData*).
- Set the properties mentioned above (Note that SetInput specifies the volume to write to)
- Set the slice to that has to be overwritten in the volume ( SetInputSlice(vtkImageData*)
After calling Update() there is no need to retrieve the output as the input volume is modified.
\sa vtkImageReslice
(Note that the execute and interpolation functions are no members and thus can not be overriden)
*/
class MITKSEGMENTATION_EXPORT mitkVtkImageOverwrite : public vtkImageReslice
{
public:
static mitkVtkImageOverwrite *New();
vtkTypeMacro(mitkVtkImageOverwrite, vtkImageReslice);
/** \brief Set the mode either to reslice (false) or to overwrite (true).
Default: false
*/
void SetOverwriteMode(bool b);
bool IsOverwriteMode() { return m_Overwrite_Mode; }
/** \brief Set the slice for overwrite mode.
Note:
It is recommend not to use this in reslice mode because otherwise the slice will be modified!
*/
void SetInputSlice(vtkImageData *slice);
protected:
mitkVtkImageOverwrite();
~mitkVtkImageOverwrite() override;
bool m_Overwrite_Mode;
/** Overridden from vtkImageReslice. \sa vtkImageReslice::ThreadedRequestData */
void ThreadedRequestData(vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *vtkNotUsed(outputVector),
vtkImageData ***inData,
vtkImageData **outData,
int outExt[6],
int id) override;
};
#endif
diff --git a/Modules/Segmentation/CMakeLists.txt b/Modules/Segmentation/CMakeLists.txt
index 83b9c461ac..709e882c01 100644
--- a/Modules/Segmentation/CMakeLists.txt
+++ b/Modules/Segmentation/CMakeLists.txt
@@ -1,10 +1,11 @@
mitk_create_module(
INCLUDE_DIRS Algorithms Controllers DataManagement Interactions Rendering SegmentationUtilities/BooleanOperations SegmentationUtilities/MorphologicalOperations
DEPENDS MitkAlgorithmsExt MitkSurfaceInterpolation MitkGraphAlgorithms MitkContourModel MitkMultilabel
PACKAGE_DEPENDS
PUBLIC ITK|QuadEdgeMesh+RegionGrowing
PRIVATE ITK|LabelMap+MathematicalMorphology VTK|ImagingGeneral
TARGET_DEPENDS PRIVATE GrowCut
)
+add_subdirectory(cmdapps)
add_subdirectory(Testing)
diff --git a/Modules/Segmentation/Controllers/mitkToolManager.cpp b/Modules/Segmentation/Controllers/mitkToolManager.cpp
index bf4b30c3bf..d1fab073f6 100644
--- a/Modules/Segmentation/Controllers/mitkToolManager.cpp
+++ b/Modules/Segmentation/Controllers/mitkToolManager.cpp
@@ -1,596 +1,592 @@
/*============================================================================
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 "mitkToolManager.h"
#include "mitkToolManagerProvider.h"
#include "mitkCoreObjectFactory.h"
#include <itkCommand.h>
#include <itkObjectFactoryBase.h>
#include <list>
#include "mitkInteractionEventObserver.h"
#include "mitkSegTool2D.h"
#include "mitkRenderingManager.h"
-#include "mitkSliceNavigationController.h"
+#include "mitkTimeNavigationController.h"
#include "usGetModuleContext.h"
#include "usModuleContext.h"
mitk::ToolManager::ToolManager(DataStorage *storage)
: m_ActiveTool(nullptr), m_ActiveToolID(-1), m_RegisteredClients(0), m_DataStorage(storage)
{
CoreObjectFactory::GetInstance(); // to make sure a CoreObjectFactory was instantiated (and in turn, possible tools
// are registered) - bug 1029
this->InitializeTools();
}
void mitk::ToolManager::EnsureTimeObservation()
{
- if (nullptr != mitk::RenderingManager::GetInstance() && nullptr != mitk::RenderingManager::GetInstance()->GetTimeNavigationController())
- {
- auto timeController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
-
- m_LastTimePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+ auto* timeController = RenderingManager::GetInstance()->GetTimeNavigationController();
+ m_LastTimePoint = timeController->GetSelectedTimePoint();
- auto currentTimeController = m_CurrentTimeNavigationController.Lock();
+ auto currentTimeController = m_CurrentTimeNavigationController.Lock();
- if (timeController != currentTimeController)
+ if (timeController != currentTimeController)
+ {
+ if (currentTimeController.IsNotNull())
{
- if (currentTimeController.IsNotNull())
- {
- currentTimeController->RemoveObserver(m_TimePointObserverTag);
- }
-
- itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
- command->SetCallbackFunction(this, &ToolManager::OnTimeChanged);
- command->SetCallbackFunction(this, &ToolManager::OnTimeChangedConst);
- m_CurrentTimeNavigationController = timeController;
- m_TimePointObserverTag = timeController->AddObserver(SliceNavigationController::GeometryTimeEvent(nullptr,0), command);
+ currentTimeController->RemoveObserver(m_TimePointObserverTag);
}
+
+ itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
+ command->SetCallbackFunction(this, &ToolManager::OnTimeChanged);
+ command->SetCallbackFunction(this, &ToolManager::OnTimeChangedConst);
+ m_CurrentTimeNavigationController = timeController;
+ m_TimePointObserverTag = timeController->AddObserver(TimeNavigationController::TimeEvent(0), command);
}
}
void mitk::ToolManager::StopTimeObservation()
{
auto currentTimeController = m_CurrentTimeNavigationController.Lock();
if (currentTimeController.IsNotNull())
{
currentTimeController->RemoveObserver(m_TimePointObserverTag);
m_CurrentTimeNavigationController = nullptr;
m_TimePointObserverTag = 0;
}
}
mitk::ToolManager::~ToolManager()
{
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
(*dataIter)->RemoveObserver(m_WorkingDataObserverTags[(*dataIter)]);
if (this->GetDataStorage() != nullptr)
this->GetDataStorage()->RemoveNodeEvent.RemoveListener(
mitk::MessageDelegate1<ToolManager, const mitk::DataNode *>(this, &ToolManager::OnNodeRemoved));
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
m_ActiveToolRegistration.Unregister();
m_ActiveTool = nullptr;
m_ActiveToolID = -1; // no tool active
ActiveToolChanged.Send();
}
for (auto observerTagMapIter = m_ReferenceDataObserverTags.begin();
observerTagMapIter != m_ReferenceDataObserverTags.end();
++observerTagMapIter)
{
observerTagMapIter->first->RemoveObserver(observerTagMapIter->second);
}
this->StopTimeObservation();
}
void mitk::ToolManager::InitializeTools()
{
// clear all previous tool pointers (tools may be still activated from another recently used plugin)
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
m_ActiveToolRegistration.Unregister();
m_ActiveTool = nullptr;
m_ActiveToolID = -1; // no tool active
ActiveToolChanged.Send();
}
m_Tools.clear();
// get a list of all known mitk::Tools
std::list<itk::LightObject::Pointer> thingsThatClaimToBeATool = itk::ObjectFactoryBase::CreateAllInstance("mitkTool");
// remember these tools
for (auto iter = thingsThatClaimToBeATool.begin();
iter != thingsThatClaimToBeATool.end();
++iter)
{
if (auto *tool = dynamic_cast<Tool *>(iter->GetPointer()))
{
tool->InitializeStateMachine();
tool->SetToolManager(this); // important to call right after instantiation
tool->ErrorMessage += MessageDelegate1<mitk::ToolManager, std::string>(this, &ToolManager::OnToolErrorMessage);
tool->GeneralMessage +=
MessageDelegate1<mitk::ToolManager, std::string>(this, &ToolManager::OnGeneralToolMessage);
m_Tools.push_back(tool);
}
}
}
void mitk::ToolManager::OnToolErrorMessage(std::string s)
{
this->ToolErrorMessage(s);
}
void mitk::ToolManager::OnGeneralToolMessage(std::string s)
{
this->GeneralToolMessage(s);
}
const mitk::ToolManager::ToolVectorTypeConst mitk::ToolManager::GetTools()
{
ToolVectorTypeConst resultList;
for (auto iter = m_Tools.begin(); iter != m_Tools.end(); ++iter)
{
resultList.push_back(iter->GetPointer());
}
return resultList;
}
mitk::Tool *mitk::ToolManager::GetToolById(int id)
{
try
{
return m_Tools.at(id);
}
catch (const std::exception &)
{
return nullptr;
}
}
bool mitk::ToolManager::ActivateTool(int id)
{
const auto workingDataNode = this->GetWorkingData(0);
const mitk::BaseData* workingData = nullptr;
if (nullptr != workingDataNode)
{
workingData = workingDataNode->GetData();
}
const auto referenceDataNode = this->GetReferenceData(0);
const mitk::BaseData* referenceData = nullptr;
if (nullptr != referenceDataNode)
{
referenceData = referenceDataNode->GetData();
}
if (id != -1 && !this->GetToolById(id)->CanHandle(referenceData, workingData))
return false;
if (this->GetDataStorage())
{
this->GetDataStorage()->RemoveNodeEvent.AddListener(
mitk::MessageDelegate1<ToolManager, const mitk::DataNode *>(this, &ToolManager::OnNodeRemoved));
}
if (GetToolById(id) == m_ActiveTool)
return true; // no change needed
static int nextTool = -1;
nextTool = id;
static bool inActivateTool = false;
if (inActivateTool)
{
return true;
}
inActivateTool = true;
while (nextTool != m_ActiveToolID)
{
// Deactivate all other active tools to ensure a globally single active tool
for (const auto& toolManager : ToolManagerProvider::GetInstance()->GetToolManagers())
{
if (nullptr != toolManager.second->m_ActiveTool)
{
toolManager.second->m_ActiveTool->Deactivated();
toolManager.second->m_ActiveToolRegistration.Unregister();
// The active tool of *this* ToolManager is handled below this loop
if (this != toolManager.second)
{
toolManager.second->m_ActiveTool = nullptr;
toolManager.second->m_ActiveToolID = -1;
toolManager.second->ActiveToolChanged.Send();
}
}
}
m_ActiveTool = GetToolById(nextTool);
m_ActiveToolID = m_ActiveTool ? nextTool : -1; // current ID if tool is valid, otherwise -1
ActiveToolChanged.Send();
if (m_ActiveTool)
{
this->EnsureTimeObservation();
if (m_RegisteredClients > 0)
{
m_ActiveTool->Activated();
m_ActiveToolRegistration =
us::GetModuleContext()->RegisterService<InteractionEventObserver>(m_ActiveTool, us::ServiceProperties());
}
}
}
inActivateTool = false;
return (m_ActiveTool != nullptr);
}
void mitk::ToolManager::SetReferenceData(DataVectorType data)
{
if (data != m_ReferenceData)
{
// remove observers from old nodes
for (auto dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter)
{
auto searchIter = m_ReferenceDataObserverTags.find(*dataIter);
if (searchIter != m_ReferenceDataObserverTags.end())
{
(*dataIter)->RemoveObserver(searchIter->second);
}
}
m_ReferenceData = data;
// TODO tell active tool?
// attach new observers
m_ReferenceDataObserverTags.clear();
for (auto dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter)
{
itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheReferenceDataDeleted);
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheReferenceDataDeletedConst);
m_ReferenceDataObserverTags.insert(
std::pair<DataNode *, unsigned long>((*dataIter), (*dataIter)->AddObserver(itk::DeleteEvent(), command)));
}
ReferenceDataChanged.Send();
}
}
void mitk::ToolManager::OnOneOfTheReferenceDataDeletedConst(const itk::Object *caller, const itk::EventObject &e)
{
OnOneOfTheReferenceDataDeleted(const_cast<itk::Object *>(caller), e);
}
void mitk::ToolManager::OnOneOfTheReferenceDataDeleted(itk::Object *caller, const itk::EventObject &itkNotUsed(e))
{
DataVectorType v;
for (auto dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter)
{
if ((void *)(*dataIter) != (void *)caller)
{
v.push_back(*dataIter);
}
else
{
m_ReferenceDataObserverTags.erase(*dataIter); // no tag to remove anymore
}
}
this->SetReferenceData(v);
}
void mitk::ToolManager::SetReferenceData(DataNode *data)
{
DataVectorType v;
if (data)
{
v.push_back(data);
}
SetReferenceData(v);
}
void mitk::ToolManager::SetWorkingData(DataVectorType data)
{
if (data != m_WorkingData)
{
// remove observers from old nodes
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
{
auto searchIter = m_WorkingDataObserverTags.find(*dataIter);
if (searchIter != m_WorkingDataObserverTags.end())
{
(*dataIter)->RemoveObserver(searchIter->second);
}
}
m_WorkingData = data;
// TODO tell active tool?
// Quick workaround for bug #16598
if (m_WorkingData.empty())
this->ActivateTool(-1);
// workaround end
// attach new observers
m_WorkingDataObserverTags.clear();
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
{
itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheWorkingDataDeleted);
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheWorkingDataDeletedConst);
m_WorkingDataObserverTags.insert(
std::pair<DataNode *, unsigned long>((*dataIter), (*dataIter)->AddObserver(itk::DeleteEvent(), command)));
}
WorkingDataChanged.Send();
}
}
void mitk::ToolManager::OnOneOfTheWorkingDataDeletedConst(const itk::Object *caller, const itk::EventObject &e)
{
OnOneOfTheWorkingDataDeleted(const_cast<itk::Object *>(caller), e);
}
void mitk::ToolManager::OnOneOfTheWorkingDataDeleted(itk::Object *caller, const itk::EventObject &itkNotUsed(e))
{
DataVectorType v;
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
{
if ((void *)(*dataIter) != (void *)caller)
{
v.push_back(*dataIter);
}
else
{
m_WorkingDataObserverTags.erase(*dataIter); // no tag to remove anymore
}
}
this->SetWorkingData(v);
}
void mitk::ToolManager::SetWorkingData(DataNode *data)
{
DataVectorType v;
if (data) // don't allow for nullptr nodes
{
v.push_back(data);
}
SetWorkingData(v);
}
void mitk::ToolManager::SetRoiData(DataVectorType data)
{
if (data != m_RoiData)
{
// remove observers from old nodes
for (auto dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter)
{
auto searchIter = m_RoiDataObserverTags.find(*dataIter);
if (searchIter != m_RoiDataObserverTags.end())
{
(*dataIter)->RemoveObserver(searchIter->second);
}
}
m_RoiData = data;
// TODO tell active tool?
// attach new observers
m_RoiDataObserverTags.clear();
for (auto dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter)
{
itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheRoiDataDeleted);
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheRoiDataDeletedConst);
m_RoiDataObserverTags.insert(
std::pair<DataNode *, unsigned long>((*dataIter), (*dataIter)->AddObserver(itk::DeleteEvent(), command)));
}
RoiDataChanged.Send();
}
}
void mitk::ToolManager::SetRoiData(DataNode *data)
{
DataVectorType v;
if (data)
{
v.push_back(data);
}
this->SetRoiData(v);
}
void mitk::ToolManager::OnOneOfTheRoiDataDeletedConst(const itk::Object *caller, const itk::EventObject &e)
{
OnOneOfTheRoiDataDeleted(const_cast<itk::Object *>(caller), e);
}
void mitk::ToolManager::OnOneOfTheRoiDataDeleted(itk::Object *caller, const itk::EventObject &itkNotUsed(e))
{
DataVectorType v;
for (auto dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter)
{
if ((void *)(*dataIter) != (void *)caller)
{
v.push_back(*dataIter);
}
else
{
m_RoiDataObserverTags.erase(*dataIter); // no tag to remove anymore
}
}
this->SetRoiData(v);
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetReferenceData()
{
return m_ReferenceData;
}
mitk::DataNode *mitk::ToolManager::GetReferenceData(int idx)
{
try
{
return m_ReferenceData.at(idx);
}
catch (const std::exception &)
{
return nullptr;
}
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetWorkingData()
{
return m_WorkingData;
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetRoiData()
{
return m_RoiData;
}
mitk::DataNode *mitk::ToolManager::GetRoiData(int idx)
{
try
{
return m_RoiData.at(idx);
}
catch (const std::exception &)
{
return nullptr;
}
}
mitk::DataStorage::Pointer mitk::ToolManager::GetDataStorage() const
{
return m_DataStorage.Lock();
}
void mitk::ToolManager::SetDataStorage(DataStorage &storage)
{
m_DataStorage = &storage;
}
mitk::DataNode *mitk::ToolManager::GetWorkingData(unsigned int idx)
{
if (m_WorkingData.empty())
return nullptr;
if (m_WorkingData.size() > idx)
return m_WorkingData[idx];
return nullptr;
}
int mitk::ToolManager::GetActiveToolID()
{
return m_ActiveToolID;
}
mitk::Tool *mitk::ToolManager::GetActiveTool()
{
return m_ActiveTool;
}
void mitk::ToolManager::RegisterClient()
{
if (m_RegisteredClients < 1)
{
if (m_ActiveTool)
{
m_ActiveTool->Activated();
m_ActiveToolRegistration =
us::GetModuleContext()->RegisterService<InteractionEventObserver>(m_ActiveTool, us::ServiceProperties());
}
}
++m_RegisteredClients;
}
void mitk::ToolManager::UnregisterClient()
{
if (m_RegisteredClients < 1)
return;
--m_RegisteredClients;
if (m_RegisteredClients < 1)
{
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
m_ActiveToolRegistration.Unregister();
}
}
}
int mitk::ToolManager::GetToolID(const Tool *tool)
{
int id(0);
for (auto iter = m_Tools.begin(); iter != m_Tools.end(); ++iter, ++id)
{
if (tool == iter->GetPointer())
{
return id;
}
}
return -1;
}
void mitk::ToolManager::OnNodeRemoved(const mitk::DataNode *node)
{
// check all storage vectors
OnOneOfTheReferenceDataDeleted(const_cast<mitk::DataNode *>(node), itk::DeleteEvent());
OnOneOfTheRoiDataDeleted(const_cast<mitk::DataNode *>(node), itk::DeleteEvent());
OnOneOfTheWorkingDataDeleted(const_cast<mitk::DataNode *>(node), itk::DeleteEvent());
}
void mitk::ToolManager::OnTimeChanged(itk::Object* caller, const itk::EventObject& e)
{
this->OnTimeChangedConst(caller, e);
}
void mitk::ToolManager::OnTimeChangedConst(const itk::Object* caller, const itk::EventObject& /*e*/)
{
- auto currentController = m_CurrentTimeNavigationController.Lock();
+ const auto currentController = m_CurrentTimeNavigationController.Lock();
if (caller == currentController)
{
- const auto currentTimePoint = currentController->GetSelectedTimePoint();
+ const TimePointType currentTimePoint = currentController->GetSelectedTimePoint();
if (currentTimePoint != m_LastTimePoint)
{
m_LastTimePoint = currentTimePoint;
SelectedTimePointChanged.Send();
}
}
}
mitk::TimePointType mitk::ToolManager::GetCurrentTimePoint() const
{
return m_LastTimePoint;
}
diff --git a/Modules/Segmentation/Controllers/mitkToolManager.h b/Modules/Segmentation/Controllers/mitkToolManager.h
index ebade99775..f6bbc61208 100644
--- a/Modules/Segmentation/Controllers/mitkToolManager.h
+++ b/Modules/Segmentation/Controllers/mitkToolManager.h
@@ -1,302 +1,302 @@
/*============================================================================
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 mitkToolManager_h
#define mitkToolManager_h
#include "mitkDataNode.h"
#include "mitkDataStorage.h"
#include "mitkTool.h"
#include "mitkWeakPointer.h"
#include <MitkSegmentationExports.h>
#pragma GCC visibility push(default)
#include <itkEventObject.h>
#pragma GCC visibility pop
#include <vector>
namespace mitk
{
class Image;
class PlaneGeometry;
/**
\brief Manages and coordinates instances of mitk::Tool.
\sa QmitkToolSelectionBox
\sa Tool
\sa QmitkSegmentationView
\ingroup Interaction
\ingroup ToolManagerEtAl
There is a separate page describing the general design of QmitkSegmentationView: \ref QmitkSegmentationTechnicalPage
This class creates and manages several instances of mitk::Tool.
\li ToolManager creates instances of mitk::Tool by asking the itk::ObjectFactory to list all known implementations
of mitk::Tool.
As a result, one has to implement both a subclass of mitk::Tool and a matching subclass of
itk::ObjectFactoryBase that is registered
to the top-level itk::ObjectFactory. For an example, see mitkContourToolFactory.h. (this limitiation of
one-class-one-factory is due
to the implementation of itk::ObjectFactory).
In MITK, the right place to register the factories to itk::ObjectFactory is the mitk::QMCoreObjectFactory or
mitk::SBCoreObjectFactory.
\li ToolManager knows a set of "reference" DataNodes and a set of "working" DataNodes. The first application are
segmentation tools, where the
reference is the original image and the working data the (kind of) binary segmentation. However, ToolManager is
implemented more generally, so that
there could be other tools that work, e.g., with surfaces.
\li There is a set of events that are sent by ToolManager. At the moment these are TODO update documentation:
- mitk::ToolReferenceDataChangedEvent whenever somebody calls SetReferenceData. Most of the time this actually
means that the data has changed, but
there might be cases where the same data is passed to SetReferenceData a second time, so don't rely on the
assumption that something actually changed.
- mitk::ToolSelectedEvent is sent when a (truly) different tool was activated. In reaction to this event you can
ask for the active Tool using
GetActiveTool or GetActiveToolID (where nullptr or -1 indicate that NO tool is active at the moment).
Design descisions:
\li Not a singleton, because there could be two functionalities using tools, each one with different
reference/working data.
$Author$
*/
class MITKSEGMENTATION_EXPORT ToolManager : public itk::Object
{
public:
typedef std::vector<Tool::Pointer> ToolVectorType;
typedef std::vector<Tool::ConstPointer> ToolVectorTypeConst;
typedef std::vector<DataNode *> DataVectorType; // has to be observed for delete events!
typedef std::map<DataNode *, unsigned long> NodeTagMapType;
Message<> NodePropertiesChanged;
Message<> NewNodesGenerated;
Message1<DataVectorType *> NewNodeObjectsGenerated;
Message<> ActiveToolChanged;
Message<> ReferenceDataChanged;
Message<> WorkingDataChanged;
Message<> RoiDataChanged;
Message<> SelectedTimePointChanged;
Message1<std::string> ToolErrorMessage;
Message1<std::string> GeneralToolMessage;
mitkClassMacroItkParent(ToolManager, itk::Object);
mitkNewMacro1Param(ToolManager, DataStorage *);
/**
\brief Gives you a list of all tools.
This is const on purpose.
*/
const ToolVectorTypeConst GetTools();
int GetToolID(const Tool *tool);
/**
\param id The tool of interest.
Counting starts with 0.
*/
Tool *GetToolById(int id);
/**
\param id The tool to activate. Provide -1 for disabling any tools.
Counting starts with 0.
Registeres a listner for NodeRemoved event at DataStorage (see mitk::ToolManager::OnNodeRemoved).
*/
bool ActivateTool(int id);
template <class T>
int GetToolIdByToolType()
{
int id = 0;
for (auto iter = m_Tools.begin(); iter != m_Tools.end(); ++iter, ++id)
{
if (dynamic_cast<T *>(iter->GetPointer()))
{
return id;
}
}
return -1;
}
/**
\return -1 for "No tool is active"
*/
int GetActiveToolID();
/**
\return nullptr for "No tool is active"
*/
Tool *GetActiveTool();
/**
\brief Set a list of data/images as reference objects.
*/
void SetReferenceData(DataVectorType);
/**
\brief Set single data item/image as reference object.
*/
void SetReferenceData(DataNode *);
/**
\brief Set a list of data/images as working objects.
*/
void SetWorkingData(DataVectorType);
/**
\brief Set single data item/image as working object.
*/
void SetWorkingData(DataNode *);
/**
\brief Set a list of data/images as roi objects.
*/
void SetRoiData(DataVectorType);
/**
\brief Set a single data item/image as roi object.
*/
void SetRoiData(DataNode *);
/**
\brief Get the list of reference data.
*/
DataVectorType GetReferenceData();
/**
\brief Get the current reference data.
\warning If there is a list of items, this method will only return the first list item.
*/
DataNode *GetReferenceData(int);
/**
\brief Get the list of working data.
*/
DataVectorType GetWorkingData();
/**
\brief Get the current working data.
\warning If there is a list of items, this method will only return the first list item.
*/
DataNode *GetWorkingData(unsigned int);
/**
\brief Get the current roi data
*/
DataVectorType GetRoiData();
/**
\brief Get the roi data at position idx
*/
DataNode *GetRoiData(int idx);
DataStorage::Pointer GetDataStorage() const;
void SetDataStorage(DataStorage &storage);
/** Get the current selected time point of the RenderManager
*/
TimePointType GetCurrentTimePoint() const;
/**
\brief Tell that someone is using tools.
GUI elements should call this when they become active. This method increases an internal "client count".
*/
void RegisterClient();
/**
\brief Tell that someone is NOT using tools.
GUI elements should call this when they become active. This method increases an internal "client count".
*/
void UnregisterClient();
/** \brief Initialize all classes derived from mitk::Tool by itkObjectFactoy */
void InitializeTools();
void OnOneOfTheReferenceDataDeletedConst(const itk::Object *caller, const itk::EventObject &e);
void OnOneOfTheReferenceDataDeleted(itk::Object *caller, const itk::EventObject &e);
void OnOneOfTheWorkingDataDeletedConst(const itk::Object *caller, const itk::EventObject &e);
void OnOneOfTheWorkingDataDeleted(itk::Object *caller, const itk::EventObject &e);
void OnOneOfTheRoiDataDeletedConst(const itk::Object *caller, const itk::EventObject &e);
void OnOneOfTheRoiDataDeleted(itk::Object *caller, const itk::EventObject &e);
/**
\brief Connected to tool's messages
This method just resends error messages coming from any of the tools. This way clients (GUIs) only have to observe
one message.
*/
void OnToolErrorMessage(std::string s);
void OnGeneralToolMessage(std::string s);
protected:
/**
You may specify a list of tool "groups" that should be available for this ToolManager. Every Tool can report its
group
as a string. This constructor will try to find the tool's group inside the supplied string. If there is a match,
the tool is accepted. Effectively, you can provide a human readable list like "default, lymphnodevolumetry,
oldERISstuff".
*/
ToolManager(DataStorage *storage); // purposely hidden
~ToolManager() override;
ToolVectorType m_Tools;
Tool *m_ActiveTool;
int m_ActiveToolID;
us::ServiceRegistration<InteractionEventObserver> m_ActiveToolRegistration;
DataVectorType m_ReferenceData;
NodeTagMapType m_ReferenceDataObserverTags;
DataVectorType m_WorkingData;
NodeTagMapType m_WorkingDataObserverTags;
DataVectorType m_RoiData;
NodeTagMapType m_RoiDataObserverTags;
int m_RegisteredClients;
WeakPointer<DataStorage> m_DataStorage;
/// \brief Callback for NodeRemove events
void OnNodeRemoved(const mitk::DataNode *node);
/** Callback for time changed events*/
void OnTimeChangedConst(const itk::Object* caller, const itk::EventObject& e);
void OnTimeChanged(itk::Object* caller, const itk::EventObject& e);
void EnsureTimeObservation();
void StopTimeObservation();
private:
/** Time point of last detected change*/
TimePointType m_LastTimePoint = 0;
/** Tag of the observer that listens to time changes*/
unsigned long m_TimePointObserverTag = 0;
/** Pointer to the observed time stepper*/
- WeakPointer<SliceNavigationController> m_CurrentTimeNavigationController;
+ WeakPointer<TimeNavigationController> m_CurrentTimeNavigationController;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp
index baad32e9c2..665c7a1714 100644
--- a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp
@@ -1,122 +1,125 @@
/*============================================================================
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 "mitkBinaryThresholdBaseTool.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageCast.h"
#include "mitkImageStatisticsHolder.h"
#include "mitkLabelSetImage.h"
#include <itkBinaryThresholdImageFilter.h>
#include <itkImageRegionIterator.h>
mitk::BinaryThresholdBaseTool::BinaryThresholdBaseTool()
: m_SensibleMinimumThreshold(-100),
m_SensibleMaximumThreshold(+100),
m_LowerThreshold(1),
m_UpperThreshold(1)
{
}
mitk::BinaryThresholdBaseTool::~BinaryThresholdBaseTool()
{
}
void mitk::BinaryThresholdBaseTool::SetThresholdValues(double lower, double upper)
{
/* If value is not in the min/max range, do nothing. In that case, this
method will be called again with a proper value right after. The only
known case where this happens is with an [0.0, 1.0[ image, where value
could be an epsilon greater than the max. */
if (lower < m_SensibleMinimumThreshold
|| lower > m_SensibleMaximumThreshold
|| upper < m_SensibleMinimumThreshold
|| upper > m_SensibleMaximumThreshold)
{
return;
}
m_LowerThreshold = lower;
m_UpperThreshold = upper;
if (nullptr != this->GetPreviewSegmentation())
{
UpdatePreview();
}
}
void mitk::BinaryThresholdBaseTool::InitiateToolByInput()
{
const auto referenceImage = this->GetReferenceData();
if (nullptr != referenceImage)
{
m_SensibleMinimumThreshold = std::numeric_limits<ScalarType>::max();
m_SensibleMaximumThreshold = std::numeric_limits<ScalarType>::lowest();
Image::StatisticsHolderPointer statistics = referenceImage->GetStatistics();
for (unsigned int ts = 0; ts < referenceImage->GetTimeSteps(); ++ts)
{
m_SensibleMinimumThreshold = std::min(m_SensibleMinimumThreshold, static_cast<double>(statistics->GetScalarValueMin()));
m_SensibleMaximumThreshold = std::max(m_SensibleMaximumThreshold, static_cast<double>(statistics->GetScalarValueMax()));
}
if (m_LockedUpperThreshold)
{
m_LowerThreshold = (m_SensibleMaximumThreshold + m_SensibleMinimumThreshold) / 2.0;
m_UpperThreshold = m_SensibleMaximumThreshold;
}
else
{
double range = m_SensibleMaximumThreshold - m_SensibleMinimumThreshold;
m_LowerThreshold = m_SensibleMinimumThreshold + range / 3.0;
m_UpperThreshold = m_SensibleMinimumThreshold + 2 * range / 3.0;
}
bool isFloatImage = false;
if ((referenceImage->GetPixelType().GetPixelType() == itk::IOPixelEnum::SCALAR) &&
(referenceImage->GetPixelType().GetComponentType() == itk::IOComponentEnum::FLOAT ||
referenceImage->GetPixelType().GetComponentType() == itk::IOComponentEnum::DOUBLE))
{
isFloatImage = true;
}
IntervalBordersChanged.Send(m_SensibleMinimumThreshold, m_SensibleMaximumThreshold, isFloatImage);
ThresholdingValuesChanged.Send(m_LowerThreshold, m_UpperThreshold);
}
}
void mitk::BinaryThresholdBaseTool::DoUpdatePreview(const Image* inputAtTimeStep, const Image* /*oldSegAtTimeStep*/, LabelSetImage* previewImage, TimeStepType timeStep)
{
if (nullptr != inputAtTimeStep && nullptr != previewImage)
{
AccessByItk_n(inputAtTimeStep, ITKThresholding, (previewImage, timeStep));
}
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::BinaryThresholdBaseTool::ITKThresholding(const itk::Image<TPixel, VImageDimension>* inputImage,
- Image* segmentation,
+ LabelSetImage *segmentation,
unsigned int timeStep)
{
typedef itk::Image<TPixel, VImageDimension> ImageType;
typedef itk::Image<Tool::DefaultSegmentationDataType, VImageDimension> SegmentationType;
typedef itk::BinaryThresholdImageFilter<ImageType, SegmentationType> ThresholdFilterType;
+ const auto activeValue = this->GetActiveLabelValueOfPreview();
+ this->SetSelectedLabels({activeValue});
+
typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New();
filter->SetInput(inputImage);
filter->SetLowerThreshold(m_LowerThreshold);
filter->SetUpperThreshold(m_UpperThreshold);
- filter->SetInsideValue(this->GetUserDefinedActiveLabel());
+ filter->SetInsideValue(activeValue);
filter->SetOutsideValue(0);
filter->Update();
segmentation->SetVolume((void *)(filter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep);
}
diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h
index cac6e3f6af..ff8940d165 100644
--- a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h
+++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h
@@ -1,77 +1,78 @@
/*============================================================================
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 mitkBinaryThresholdBaseTool_h
#define mitkBinaryThresholdBaseTool_h
#include <MitkSegmentationExports.h>
#include <mitkSegWithPreviewTool.h>
#include <mitkCommon.h>
#include <mitkDataNode.h>
#include <itkBinaryThresholdImageFilter.h>
#include <itkImage.h>
namespace mitk
{
/**
\brief Base class for binary threshold tools.
\ingroup ToolManagerEtAl
\sa mitk::Tool
\sa QmitkInteractiveSegmentation
*/
class MITKSEGMENTATION_EXPORT BinaryThresholdBaseTool : public SegWithPreviewTool
{
public:
Message3<double, double, bool> IntervalBordersChanged;
Message2<ScalarType, ScalarType> ThresholdingValuesChanged;
mitkClassMacro(BinaryThresholdBaseTool, SegWithPreviewTool);
virtual void SetThresholdValues(double lower, double upper);
protected:
BinaryThresholdBaseTool(); // purposely hidden
~BinaryThresholdBaseTool() override;
itkSetMacro(LockedUpperThreshold, bool);
itkGetMacro(LockedUpperThreshold, bool);
itkBooleanMacro(LockedUpperThreshold);
itkGetMacro(SensibleMinimumThreshold, ScalarType);
itkGetMacro(SensibleMaximumThreshold, ScalarType);
void InitiateToolByInput() override;
void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep) override;
template <typename TPixel, unsigned int VImageDimension>
void ITKThresholding(const itk::Image<TPixel, VImageDimension>* inputImage,
- Image* segmentation, unsigned int timeStep);
+ LabelSetImage *segmentation,
+ unsigned int timeStep);
private:
ScalarType m_SensibleMinimumThreshold;
ScalarType m_SensibleMaximumThreshold;
ScalarType m_LowerThreshold;
ScalarType m_UpperThreshold;
/** Indicates if the tool should behave like a single threshold tool (true)
or like a upper/lower threshold tool (false)*/
bool m_LockedUpperThreshold = false;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkEditableContourTool.cpp b/Modules/Segmentation/Interactions/mitkEditableContourTool.cpp
index bb384c2487..ae9e623287 100644
--- a/Modules/Segmentation/Interactions/mitkEditableContourTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkEditableContourTool.cpp
@@ -1,459 +1,477 @@
/*============================================================================
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 "mitkEditableContourTool.h"
#include <mitkToolManager.h>
mitk::EditableContourTool::EditableContourTool() : FeedbackContourTool("EditableContourTool"), m_AutoConfirm(true), m_AddMode(true)
{}
mitk::EditableContourTool::~EditableContourTool()
{
this->ReleaseHelperObjects();
this->ReleaseInteractors();
}
void mitk::EditableContourTool::ConnectActionsAndFunctions()
{
CONNECT_FUNCTION("InitObject", OnInitContour);
CONNECT_FUNCTION("AddPoint", OnAddPoint);
CONNECT_FUNCTION("CtrlAddPoint", OnAddPoint);
CONNECT_FUNCTION("Drawing", OnDrawing);
CONNECT_FUNCTION("EndDrawing", OnEndDrawing);
CONNECT_FUNCTION("FinishContour", OnFinish);
CONNECT_FUNCTION("CtrlMovePoint", OnMouseMoved);
+ CONNECT_CONDITION("InsideCorrectPlane", OnCheckPlane);
}
void mitk::EditableContourTool::Activated()
{
Superclass::Activated();
this->ResetToStartState();
this->EnableContourInteraction(true);
}
void mitk::EditableContourTool::Deactivated()
{
this->ClearContour();
Superclass::Deactivated();
}
void mitk::EditableContourTool::ConfirmSegmentation(bool resetStatMachine)
{
auto referenceImage = this->GetReferenceData();
auto workingImage = this->GetWorkingData();
if (nullptr != referenceImage && nullptr != workingImage)
{
std::vector<SliceInformation> sliceInfos;
const auto currentTimePoint =
mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
TimeStepType workingImageTimeStep = workingImage->GetTimeGeometry()->TimePointToTimeStep(currentTimePoint);
auto contour = this->GetContour();
if (nullptr == contour || contour->IsEmpty())
return;
auto workingSlice =
this->GetAffectedImageSliceAs2DImage(m_PlaneGeometry, workingImage, workingImageTimeStep)->Clone();
sliceInfos.emplace_back(workingSlice, m_PlaneGeometry, workingImageTimeStep);
auto projectedContour = ContourModelUtils::ProjectContourTo2DSlice(workingSlice, contour);
int activePixelValue = ContourModelUtils::GetActivePixelValue(workingImage);
if (!m_AddMode)
{
activePixelValue = 0;
}
ContourModelUtils::FillContourInSlice(projectedContour, workingSlice, workingImage, activePixelValue);
this->WriteBackSegmentationResults(sliceInfos);
}
this->ReleaseHelperObjects();
this->ReleaseInteractors();
if (resetStatMachine) this->ResetToStartState();
}
void mitk::EditableContourTool::ClearContour()
{
this->ReleaseHelperObjects();
this->ReleaseInteractors();
this->ResetToStartState();
}
bool mitk::EditableContourTool::IsEditingContour() const
{
return (nullptr != GetContour()) && !this->IsDrawingContour();
};
bool mitk::EditableContourTool::IsDrawingContour() const
{
return m_PreviewContour.IsNotNull();
};
mitk::Point3D mitk::EditableContourTool::PrepareInitContour(const Point3D& clickedPoint)
{ //default implementation does nothing
return clickedPoint;
}
void mitk::EditableContourTool::OnInitContour(StateMachineAction *, InteractionEvent *interactionEvent)
{
auto positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
if (nullptr == positionEvent)
return;
auto workingDataNode = this->GetWorkingDataNode();
if (nullptr != this->GetContour())
{
this->ConfirmSegmentation(false);
}
if (!IsPositionEventInsideImageRegion(positionEvent, workingDataNode->GetData()))
{
this->ResetToStartState();
return;
}
m_LastEventSender = positionEvent->GetSender();
m_LastEventSlice = m_LastEventSender->GetSlice();
auto contour = this->CreateNewContour();
m_ContourNode = mitk::DataNode::New();
m_ContourNode->SetData(contour);
m_ContourNode->SetName("working contour node");
m_ContourNode->SetProperty("layer", IntProperty::New(100));
m_ContourNode->AddProperty("fixedLayer", BoolProperty::New(true));
m_ContourNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_ContourNode->AddProperty("contour.color", ColorProperty::New(1.0f, 1.0f, 0.0f), nullptr, true);
m_ContourNode->AddProperty("contour.points.color", ColorProperty::New(1.0f, 0.0f, 0.1f), nullptr, true);
m_ContourNode->AddProperty("contour.controlpoints.show", BoolProperty::New(true), nullptr, true);
m_PreviewContour = this->CreateNewContour();
m_PreviewContourNode = mitk::DataNode::New();
m_PreviewContourNode->SetData(m_PreviewContour);
m_PreviewContourNode->SetName("active preview node");
m_PreviewContourNode->SetProperty("layer", IntProperty::New(101));
m_PreviewContourNode->AddProperty("fixedLayer", BoolProperty::New(true));
m_PreviewContourNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PreviewContourNode->AddProperty("contour.color", ColorProperty::New(0.1f, 1.0f, 0.1f), nullptr, true);
m_PreviewContourNode->AddProperty("contour.width", mitk::FloatProperty::New(4.0f), nullptr, true);
m_ClosureContour = this->CreateNewContour();
m_ClosureContourNode = mitk::DataNode::New();
m_ClosureContourNode->SetData(m_ClosureContour);
m_ClosureContourNode->SetName("active closure node");
m_ClosureContourNode->SetProperty("layer", IntProperty::New(101));
m_ClosureContourNode->AddProperty("fixedLayer", BoolProperty::New(true));
m_ClosureContourNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_ClosureContourNode->AddProperty("contour.color", ColorProperty::New(0.0f, 1.0f, 0.1f), nullptr, true);
m_ClosureContourNode->AddProperty("contour.width", mitk::FloatProperty::New(2.0f), nullptr, true);
m_CurrentRestrictedArea = this->CreateNewContour();
auto dataStorage = this->GetToolManager()->GetDataStorage();
dataStorage->Add(m_ContourNode, workingDataNode);
dataStorage->Add(m_PreviewContourNode, workingDataNode);
dataStorage->Add(m_ClosureContourNode, workingDataNode);
m_ReferenceDataSlice = this->GetAffectedReferenceSlice(positionEvent);
auto origin = m_ReferenceDataSlice->GetSlicedGeometry()->GetOrigin();
m_ReferenceDataSlice->GetSlicedGeometry()->WorldToIndex(origin, origin);
m_ReferenceDataSlice->GetSlicedGeometry()->IndexToWorld(origin, origin);
m_ReferenceDataSlice->GetSlicedGeometry()->SetOrigin(origin);
// Remember PlaneGeometry to determine if events were triggered in the same plane
m_PlaneGeometry = interactionEvent->GetSender()->GetCurrentWorldPlaneGeometry();
// Map click to pixel coordinates
auto click = positionEvent->GetPositionInWorld();
click = this->PrepareInitContour(click);
this->InitializePreviewContour(click);
// Set initial start point
contour->AddVertex(click, true);
m_PreviewContour->AddVertex(click, false);
m_ClosureContour->AddVertex(click);
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
void mitk::EditableContourTool::FinalizePreviewContour(const Point3D& /*clickedPoint*/)
{ // Remove duplicate first vertex, it's already contained in m_ContourNode
m_PreviewContour->RemoveVertexAt(0);
m_PreviewContour->SetControlVertexAt(m_PreviewContour->GetNumberOfVertices() - 1);
}
void mitk::EditableContourTool::InitializePreviewContour(const Point3D& clickedPoint)
{ //default implementation only clears the preview and sets the start point
m_PreviewContour = this->CreateNewContour();
m_PreviewContour->AddVertex(clickedPoint);
m_PreviewContourNode->SetData(m_PreviewContour);
}
void mitk::EditableContourTool::UpdatePreviewContour(const Point3D& clickedPoint)
{ //default implementation draws just a simple line to position
if (m_PreviewContour->GetNumberOfVertices() > 2)
{
auto contour = this->GetContour();
this->InitializePreviewContour(contour->GetVertexAt(contour->GetNumberOfVertices() - 1)->Coordinates);
}
if (m_PreviewContour->GetNumberOfVertices() == 2)
{
m_PreviewContour->RemoveVertexAt(m_PreviewContour->GetNumberOfVertices()-1);
}
m_PreviewContour->AddVertex(clickedPoint);
}
void mitk::EditableContourTool::OnAddPoint(StateMachineAction*, InteractionEvent* interactionEvent)
{
auto positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
return;
if (m_PlaneGeometry.IsNotNull())
{
// Check if the point is in the correct slice
if (m_PlaneGeometry->DistanceFromPlane(positionEvent->GetPositionInWorld()) > mitk::sqrteps)
return;
}
this->FinalizePreviewContour(positionEvent->GetPositionInWorld());
// Merge contours
auto contour = this->GetContour();
contour->Concatenate(m_PreviewContour);
this->InitializePreviewContour(positionEvent->GetPositionInWorld());
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
void mitk::EditableContourTool::OnDrawing(StateMachineAction*, InteractionEvent* interactionEvent)
{
auto* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>(interactionEvent);
if (!positionEvent)
return;
m_PreviewContourNode->SetVisibility(false);
auto contour = this->GetContour();
contour->AddVertex(positionEvent->GetPositionInWorld(), false);
UpdateClosureContour(positionEvent->GetPositionInWorld());
assert(positionEvent->GetSender()->GetRenderWindow());
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
void mitk::EditableContourTool::OnEndDrawing(StateMachineAction*, InteractionEvent* interactionEvent)
{
auto* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>(interactionEvent);
if (!positionEvent)
return;
auto contour = this->GetContour();
auto controlVs = contour->GetControlVertices(0);
if (!controlVs.empty())
{ //add the last control point (after that the draw part start)
m_CurrentRestrictedArea->AddVertex(controlVs.back()->Coordinates);
}
m_PreviewContourNode->SetVisibility(true);
contour->SetControlVertexAt(contour->GetNumberOfVertices() - 1);
//add the just created/set last control point (with it the draw part ends)
m_CurrentRestrictedArea->AddVertex(contour->GetVertexAt(contour->GetNumberOfVertices() - 1)->Coordinates);
this->InitializePreviewContour(positionEvent->GetPositionInWorld());
mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
void mitk::EditableContourTool::OnMouseMoved(StateMachineAction*, InteractionEvent* interactionEvent)
{
auto positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>(interactionEvent);
if (nullptr == positionEvent)
return;
if (m_PlaneGeometry.IsNotNull())
{
// Check if the point is in the correct slice
if (m_PlaneGeometry->DistanceFromPlane(positionEvent->GetPositionInWorld()) > mitk::sqrteps)
return;
}
this->UpdatePreviewContour(positionEvent->GetPositionInWorld());
this->UpdateClosureContour(positionEvent->GetPositionInWorld());
RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
}
void mitk::EditableContourTool::OnFinish(StateMachineAction *, InteractionEvent *interactionEvent)
{
auto positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
if (nullptr == positionEvent)
return;
if (m_PlaneGeometry.IsNotNull())
{
// Check if the point is in the correct slice
if (m_PlaneGeometry->DistanceFromPlane(positionEvent->GetPositionInWorld()) > mitk::sqrteps)
return;
}
this->FinalizePreviewContour(positionEvent->GetPositionInWorld());
this->FinishTool();
// Merge contours
auto contour = this->GetContour();
contour->Concatenate(m_PreviewContour);
auto numberOfTimesteps = static_cast<int>(contour->GetTimeSteps());
for (int i = 0; i <= numberOfTimesteps; ++i)
contour->Close(i);
this->ReleaseHelperObjects(false);
if (m_AutoConfirm)
{
this->ConfirmSegmentation();
}
}
+bool mitk::EditableContourTool::OnCheckPlane(const InteractionEvent* interactionEvent)
+{
+ auto positionEvent = dynamic_cast<const mitk::InteractionPositionEvent*>(interactionEvent);
+
+ if (nullptr == positionEvent)
+ return false;
+
+ if (m_PlaneGeometry.IsNotNull())
+ {
+ // Check if the point is in the correct slice
+ if (m_PlaneGeometry->DistanceFromPlane(positionEvent->GetPositionInWorld()) > mitk::sqrteps)
+ return false;
+ }
+
+ return true;
+}
+
void mitk::EditableContourTool::ReleaseHelperObjects(bool includeWorkingContour)
{
this->RemoveHelperObjectsFromDataStorage(includeWorkingContour);
if (includeWorkingContour)
{
m_ContourNode = nullptr;
m_CurrentRestrictedArea = nullptr;
}
m_PreviewContourNode = nullptr;
m_PreviewContour = nullptr;
m_ClosureContourNode = nullptr;
m_ClosureContour = nullptr;
}
void mitk::EditableContourTool::RemoveHelperObjectsFromDataStorage(bool includeWorkingContour)
{
auto dataStorage = this->GetToolManager()->GetDataStorage();
if (nullptr == dataStorage)
return;
if (includeWorkingContour)
{
if (m_ContourNode.IsNotNull())
dataStorage->Remove(m_ContourNode);
}
if (m_PreviewContourNode.IsNotNull())
dataStorage->Remove(m_PreviewContourNode);
if (m_ClosureContourNode.IsNotNull())
dataStorage->Remove(m_ClosureContourNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
mitk::ContourModel::Pointer mitk::EditableContourTool::CreateNewContour() const
{
auto workingData = this->GetWorkingData();
if (nullptr == workingData)
{
this->InteractiveSegmentationBugMessage(
"Cannot create new contour. No valid working data is set. Application is in invalid state.");
mitkThrow() << "Cannot create new contour. No valid working data is set. Application is in invalid state.";
}
auto contour = ContourModel::New();
// generate a time geometry that is always visible as the working contour should always be.
auto contourTimeGeometry = ProportionalTimeGeometry::New();
contourTimeGeometry->SetStepDuration(std::numeric_limits<TimePointType>::max());
contourTimeGeometry->SetTimeStepGeometry(contour->GetTimeGeometry()->GetGeometryForTimeStep(0)->Clone(), 0);
contour->SetTimeGeometry(contourTimeGeometry);
return contour;
}
void mitk::EditableContourTool::UpdateClosureContour(mitk::Point3D endpoint)
{
if (m_ClosureContour->GetNumberOfVertices() > 2)
{
m_ClosureContour = this->CreateNewContour();
m_ClosureContourNode->SetData(m_ClosureContour);
}
if (m_ClosureContour->GetNumberOfVertices() == 0)
{
auto contour = this->GetContour();
m_ClosureContour->AddVertex(contour->GetVertexAt(0)->Coordinates);
m_ClosureContour->Update();
}
if (m_ClosureContour->GetNumberOfVertices() == 2)
{
m_ClosureContour->RemoveVertexAt(0);
}
m_ClosureContour->AddVertexAtFront(endpoint);
}
void mitk::EditableContourTool::EnableContourInteraction(bool on)
{
if (m_ContourInteractor.IsNotNull())
{
m_ContourInteractor->EnableInteraction(on);
}
}
void mitk::EditableContourTool::ReleaseInteractors()
{
this->EnableContourInteraction(false);
m_ContourInteractor = nullptr;
}
mitk::ContourModel* mitk::EditableContourTool::GetContour()
{
if (this->m_ContourNode.IsNotNull())
{
return dynamic_cast<ContourModel*>(this->m_ContourNode->GetData());
}
return nullptr;
};
const mitk::ContourModel* mitk::EditableContourTool::GetContour() const
{
if (this->m_ContourNode.IsNotNull())
{
return dynamic_cast<const ContourModel*>(this->m_ContourNode->GetData());
}
return nullptr;
};
\ No newline at end of file
diff --git a/Modules/Segmentation/Interactions/mitkEditableContourTool.h b/Modules/Segmentation/Interactions/mitkEditableContourTool.h
index 09cf7da2f7..cd19bd9206 100644
--- a/Modules/Segmentation/Interactions/mitkEditableContourTool.h
+++ b/Modules/Segmentation/Interactions/mitkEditableContourTool.h
@@ -1,125 +1,128 @@
/*============================================================================
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 mitkEditableContourTool_h
#define mitkEditableContourTool_h
#include <mitkFeedbackContourTool.h>
namespace mitk
{
/**
* Base class for lasso like tools that allow to draw closed contours with multiple ancor points.
* The segments between the ancor points may be freehand contour segments or computed segments
* (e.g. straight lines or live wire). Derive from the class to implement the computation of the non-freehand
* segments.
* @sa LassoTool LivewWireTool2D
*/
class MITKSEGMENTATION_EXPORT EditableContourTool : public FeedbackContourTool
{
public:
mitkClassMacro(EditableContourTool, FeedbackContourTool);
/// \brief Convert current contour to binary segmentations.
virtual void ConfirmSegmentation(bool resetStatMachine = true);
/// \brief Delete all current contours.
virtual void ClearContour();
itkBooleanMacro(AutoConfirm);
itkSetMacro(AutoConfirm, bool);
itkGetMacro(AutoConfirm, bool);
itkBooleanMacro(AddMode);
itkSetMacro(AddMode, bool);
itkGetMacro(AddMode, bool);
/* Indicated if a contour is drawn, but not confirmed yet. This tool is in interactor mode
to allow users to edit the contour. This state can be reached if AutoConfirm is false, after the finalizing double
click before the contour is confirmed.*/
bool IsEditingContour() const;
/* Indicate if a contour is currently drawn by the user (state between the initializing double click and
the finalizing double click).*/
bool IsDrawingContour() const;
protected:
EditableContourTool();
~EditableContourTool() override;
void ConnectActionsAndFunctions() override;
void Activated() override;
void Deactivated() override;
virtual Point3D PrepareInitContour(const Point3D& clickedPoint);
virtual void FinalizePreviewContour(const Point3D& clickedPoint);
virtual void InitializePreviewContour(const Point3D& clickedPoint);
virtual void UpdatePreviewContour(const Point3D& clickedPoint);
/// \brief Initialize tool.
virtual void OnInitContour(StateMachineAction *, InteractionEvent *interactionEvent);
/// \brief Add a control point and finish current segment.
virtual void OnAddPoint(StateMachineAction *, InteractionEvent *interactionEvent);
/// \brief Draw a contour according to the mouse movement when mouse button is pressed and mouse is moved.
virtual void OnDrawing(StateMachineAction *, InteractionEvent *interactionEvent);
virtual void OnEndDrawing(StateMachineAction *, InteractionEvent *interactionEvent);
/// \brief Computation of the preview contour.
virtual void OnMouseMoved(StateMachineAction *, InteractionEvent *interactionEvent);
/// \brief Finish EditableContour tool.
virtual void OnFinish(StateMachineAction *, InteractionEvent *interactionEvent);
+ /// \brief Check if the event happened on the current plane.
+ virtual bool OnCheckPlane(const InteractionEvent* interactionEvent);
+
/// \brief Finish contour interaction.
virtual void FinishTool() = 0;
void EnableContourInteraction(bool on);
void ReleaseInteractors();
virtual void ReleaseHelperObjects(bool includeWorkingContour = true);
virtual void RemoveHelperObjectsFromDataStorage(bool includeWorkingContour = true);
ContourModel::Pointer CreateNewContour() const;
virtual void UpdateClosureContour(mitk::Point3D endpoint);
mitk::ContourModel* GetContour();
const mitk::ContourModel* GetContour() const;
mitk::DataNode::Pointer m_ContourNode;
mitk::ContourModel::Pointer m_PreviewContour;
mitk::DataNode::Pointer m_PreviewContourNode;
mitk::ContourModel::Pointer m_ClosureContour;
mitk::DataNode::Pointer m_ClosureContourNode;
mitk::ContourModel::Pointer m_CurrentRestrictedArea;
/** Slice of the reference data the tool is currently actively working on to
define contours.*/
mitk::Image::Pointer m_ReferenceDataSlice;
PlaneGeometry::ConstPointer m_PlaneGeometry;
mitk::DataInteractor::Pointer m_ContourInteractor;
bool m_AutoConfirm;
bool m_AddMode;
};
}
#endif
diff --git a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp
index b7a4cd5ad5..7754a8e450 100644
--- a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp
+++ b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp
@@ -1,261 +1,262 @@
/*============================================================================
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 <mitkContourModelUtils.h>
#include <mitkLiveWireTool2D.h>
#include <mitkLiveWireTool2D.xpm>
#include <mitkToolManager.h>
+#include <mitkTimeNavigationController.h>
#include <usGetModuleContext.h>
#include <usModuleResource.h>
#include <type_traits>
namespace mitk
{
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, LiveWireTool2D, "LiveWire tool");
}
mitk::LiveWireTool2D::LiveWireTool2D()
: EditableContourTool(), m_CreateAndUseDynamicCosts(false)
{
}
mitk::LiveWireTool2D::~LiveWireTool2D()
{
}
void mitk::LiveWireTool2D::ConnectActionsAndFunctions()
{
mitk::EditableContourTool::ConnectActionsAndFunctions();
CONNECT_FUNCTION("MovePoint", OnMouseMoveNoDynamicCosts);
}
const char **mitk::LiveWireTool2D::GetXPM() const
{
return mitkLiveWireTool2D_xpm;
}
us::ModuleResource mitk::LiveWireTool2D::GetIconResource() const
{
return us::GetModuleContext()->GetModule()->GetResource("LiveWire.svg");
}
us::ModuleResource mitk::LiveWireTool2D::GetCursorIconResource() const
{
return us::GetModuleContext()->GetModule()->GetResource("LiveWire_Cursor.svg");
}
const char *mitk::LiveWireTool2D::GetName() const
{
return "Live Wire";
}
void mitk::LiveWireTool2D::UpdateLiveWireContour()
{
auto contour = this->GetContour();
if (nullptr != contour)
{
auto timeGeometry = contour->GetTimeGeometry()->Clone();
m_PreviewContour = this->m_LiveWireFilter->GetOutput();
// needed because the results of the filter are always from 0 ms
// to 1 ms and the filter also resets its outputs.
// generate a time geometry that is always visible as the working contour should always be.
auto contourTimeGeometry = ProportionalTimeGeometry::New();
contourTimeGeometry->SetStepDuration(std::numeric_limits<TimePointType>::max());
contourTimeGeometry->SetTimeStepGeometry(contour->GetTimeGeometry()->GetGeometryForTimeStep(0)->Clone(), 0);
m_PreviewContour->SetTimeGeometry(contourTimeGeometry);
m_PreviewContourNode->SetData(this->m_PreviewContour);
}
}
void mitk::LiveWireTool2D::OnTimePointChanged()
{
auto reference = this->GetReferenceData();
if (nullptr == reference || m_PlaneGeometry.IsNull() || m_LiveWireFilter.IsNull() || m_PreviewContourNode.IsNull())
return;
auto timeStep = reference->GetTimeGeometry()->TimePointToTimeStep(this->GetLastTimePointTriggered());
m_ReferenceDataSlice = GetAffectedImageSliceAs2DImageByTimePoint(m_PlaneGeometry, reference, timeStep);
m_LiveWireFilter->SetInput(m_ReferenceDataSlice);
m_LiveWireFilter->Update();
this->UpdateLiveWireContour();
RenderingManager::GetInstance()->RequestUpdateAll();
};
mitk::Point3D mitk::LiveWireTool2D::PrepareInitContour(const mitk::Point3D& clickedPoint)
{
// Set current slice as input for ImageToLiveWireContourFilter
m_LiveWireFilter = ImageLiveWireContourModelFilter::New();
m_LiveWireFilter->SetUseCostFunction(true);
m_LiveWireFilter->SetInput(m_ReferenceDataSlice);
itk::Index<3> idx;
m_ReferenceDataSlice->GetGeometry()->WorldToIndex(clickedPoint, idx);
// Get the pixel with the highest gradient in a 7x7 region
itk::Index<3> indexWithHighestGradient;
AccessFixedDimensionByItk_2(m_ReferenceDataSlice, FindHighestGradientMagnitudeByITK, 2, idx, indexWithHighestGradient);
Point3D adaptedClick;
m_ReferenceDataSlice->GetGeometry()->IndexToWorld(indexWithHighestGradient, adaptedClick);
m_CreateAndUseDynamicCosts = true;
return adaptedClick;
}
void mitk::LiveWireTool2D::FinalizePreviewContour(const Point3D& clickedPoint)
{
// Add repulsive points to avoid getting the same path again
std::for_each(m_PreviewContour->IteratorBegin(), m_PreviewContour->IteratorEnd(), [this](ContourElement::VertexType* vertex) {
ImageLiveWireContourModelFilter::InternalImageType::IndexType idx;
this->m_ReferenceDataSlice->GetGeometry()->WorldToIndex(vertex->Coordinates, idx);
this->m_LiveWireFilter->AddRepulsivePoint(idx);
});
EditableContourTool::FinalizePreviewContour(clickedPoint);
}
void mitk::LiveWireTool2D::InitializePreviewContour(const Point3D& clickedPoint)
{
m_PreviewContour->Clear();
// Set new start point
m_LiveWireFilter->SetStartPoint(clickedPoint);
if (m_CreateAndUseDynamicCosts)
{
auto contour = this->GetContour();
// Use dynamic cost map for next update
m_LiveWireFilter->CreateDynamicCostMap(contour);
m_LiveWireFilter->SetUseDynamicCostMap(true);
}
}
void mitk::LiveWireTool2D::UpdatePreviewContour(const Point3D& clickedPoint)
{ // Compute LiveWire segment from last control point to current mouse position
m_LiveWireFilter->SetEndPoint(clickedPoint);
m_LiveWireFilter->Update();
this->UpdateLiveWireContour();
}
void mitk::LiveWireTool2D::OnMouseMoveNoDynamicCosts(StateMachineAction *, InteractionEvent *interactionEvent)
{
m_LiveWireFilter->SetUseDynamicCostMap(false);
this->OnMouseMoved(nullptr, interactionEvent);
m_LiveWireFilter->SetUseDynamicCostMap(true);
}
void mitk::LiveWireTool2D::FinishTool()
{
m_LiveWireFilter->SetUseDynamicCostMap(false);
m_ContourInteractor = mitk::ContourModelLiveWireInteractor::New();
m_ContourInteractor->SetDataNode(m_ContourNode);
m_ContourInteractor->LoadStateMachine("ContourModelModificationInteractor.xml", us::GetModuleContext()->GetModule());
m_ContourInteractor->SetEventConfig("ContourModelModificationConfig.xml", us::GetModuleContext()->GetModule());
m_ContourInteractor->SetWorkingImage(this->m_ReferenceDataSlice);
m_ContourInteractor->SetRestrictedArea(this->m_CurrentRestrictedArea);
m_ContourNode->SetDataInteractor(m_ContourInteractor.GetPointer());
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::LiveWireTool2D::FindHighestGradientMagnitudeByITK(itk::Image<TPixel, VImageDimension> *inputImage,
itk::Index<3> &index,
itk::Index<3> &returnIndex)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef typename InputImageType::IndexType IndexType;
const auto MAX_X = inputImage->GetLargestPossibleRegion().GetSize()[0];
const auto MAX_Y = inputImage->GetLargestPossibleRegion().GetSize()[1];
returnIndex[0] = index[0];
returnIndex[1] = index[1];
returnIndex[2] = 0.0;
double gradientMagnitude = 0.0;
double maxGradientMagnitude = 0.0;
// The size and thus the region of 7x7 is only used to calculate the gradient magnitude in that region,
// not for searching the maximum value.
// Maximum value in each direction for size
typename InputImageType::SizeType size;
size[0] = 7;
size[1] = 7;
// Minimum value in each direction for startRegion
IndexType startRegion;
startRegion[0] = index[0] - 3;
startRegion[1] = index[1] - 3;
if (startRegion[0] < 0)
startRegion[0] = 0;
if (startRegion[1] < 0)
startRegion[1] = 0;
if (MAX_X - index[0] < 7)
startRegion[0] = MAX_X - 7;
if (MAX_Y - index[1] < 7)
startRegion[1] = MAX_Y - 7;
index[0] = startRegion[0] + 3;
index[1] = startRegion[1] + 3;
typename InputImageType::RegionType region;
region.SetSize(size);
region.SetIndex(startRegion);
typedef typename itk::GradientMagnitudeImageFilter<InputImageType, InputImageType> GradientMagnitudeFilterType;
typename GradientMagnitudeFilterType::Pointer gradientFilter = GradientMagnitudeFilterType::New();
gradientFilter->SetInput(inputImage);
gradientFilter->GetOutput()->SetRequestedRegion(region);
gradientFilter->Update();
typename InputImageType::Pointer gradientMagnitudeImage;
gradientMagnitudeImage = gradientFilter->GetOutput();
IndexType currentIndex;
currentIndex[0] = 0;
currentIndex[1] = 0;
// Search max (approximate) gradient magnitude
for (int x = -1; x <= 1; ++x)
{
currentIndex[0] = index[0] + x;
for (int y = -1; y <= 1; ++y)
{
currentIndex[1] = index[1] + y;
gradientMagnitude = gradientMagnitudeImage->GetPixel(currentIndex);
// Check for new max
if (maxGradientMagnitude < gradientMagnitude)
{
maxGradientMagnitude = gradientMagnitude;
returnIndex[0] = currentIndex[0];
returnIndex[1] = currentIndex[1];
returnIndex[2] = 0.0;
}
}
currentIndex[1] = index[1];
}
}
diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
index 84ab8d6774..688412dd2e 100644
--- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
+++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
@@ -1,103 +1,114 @@
/*============================================================================
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.
============================================================================*/
// MITK
#include "mitkOtsuTool3D.h"
#include "mitkOtsuSegmentationFilter.h"
#include <mitkLabelSetImageHelper.h>
#include <mitkImageStatisticsHolder.h>
// us
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <usModuleResource.h>
namespace mitk
{
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, OtsuTool3D, "Otsu Segmentation");
}
+mitk::OtsuTool3D::OtsuTool3D()
+ : SegWithPreviewTool()
+{
+ this->ResetsToEmptyPreviewOn();
+ this->UseSpecialPreviewColorOff();
+}
+
void mitk::OtsuTool3D::Activated()
{
Superclass::Activated();
m_NumberOfBins = 128;
m_NumberOfRegions = 2;
m_UseValley = false;
this->SetLabelTransferScope(LabelTransferScope::AllLabels);
this->SetLabelTransferMode(LabelTransferMode::AddLabel);
}
const char **mitk::OtsuTool3D::GetXPM() const
{
return nullptr;
}
us::ModuleResource mitk::OtsuTool3D::GetIconResource() const
{
us::Module *module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("Otsu.svg");
return resource;
}
const char* mitk::OtsuTool3D::GetName() const
{
return "Otsu";
}
void mitk::OtsuTool3D::DoUpdatePreview(const Image* inputAtTimeStep, const Image* /*oldSegAtTimeStep*/, LabelSetImage* previewImage, TimeStepType timeStep)
{
int numberOfThresholds = m_NumberOfRegions - 1;
mitk::OtsuSegmentationFilter::Pointer otsuFilter = mitk::OtsuSegmentationFilter::New();
otsuFilter->SetNumberOfThresholds(numberOfThresholds);
otsuFilter->SetValleyEmphasis(m_UseValley);
otsuFilter->SetNumberOfBins(m_NumberOfBins);
otsuFilter->SetInput(inputAtTimeStep);
otsuFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
try
{
otsuFilter->Update();
}
catch (...)
{
mitkThrow() << "itkOtsuFilter error (image dimension must be in {2, 3} and image must not be RGB)";
}
auto otsuResultImage = otsuFilter->GetOutput();
mitk::ImageReadAccessor newMitkImgAcc(otsuResultImage);
previewImage->SetVolume(newMitkImgAcc.GetData(), timeStep);
}
void mitk::OtsuTool3D::UpdatePrepare()
{
Superclass::UpdatePrepare();
auto preview = this->GetPreviewSegmentation();
auto labelset = preview->GetLabelSet(preview->GetActiveLayer());
- labelset->RemoveAllLabels();
+ for (LabelSetImage::GroupIndexType i = 0; i<preview->GetNumberOfLayers(); ++i)
+ {
+ preview->GetLabelSet(i)->RemoveAllLabels();
+ }
+
for (unsigned int i = 0; i < m_NumberOfRegions; ++i)
{
auto label = LabelSetImageHelper::CreateNewLabel(preview, "Otsu");
label->SetValue(i + 1);
labelset->AddLabel(label, false);
}
}
unsigned int mitk::OtsuTool3D::GetMaxNumberOfBins() const
{
const auto min = this->GetReferenceData()->GetStatistics()->GetScalarValueMin();
const auto max = this->GetReferenceData()->GetStatistics()->GetScalarValueMaxNoRecompute();
return static_cast<unsigned int>(max - min) + 1;
}
diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.h b/Modules/Segmentation/Interactions/mitkOtsuTool3D.h
index 7185fed298..b93690340a 100644
--- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.h
+++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.h
@@ -1,65 +1,65 @@
/*============================================================================
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 mitkOtsuTool3D_h
#define mitkOtsuTool3D_h
#include "mitkSegWithPreviewTool.h"
#include <MitkSegmentationExports.h>
namespace us
{
class ModuleResource;
}
namespace mitk
{
class Image;
class MITKSEGMENTATION_EXPORT OtsuTool3D : public SegWithPreviewTool
{
public:
mitkClassMacro(OtsuTool3D, SegWithPreviewTool);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
const char *GetName() const override;
const char **GetXPM() const override;
us::ModuleResource GetIconResource() const override;
void Activated() override;
itkSetMacro(NumberOfBins, unsigned int);
itkGetConstMacro(NumberOfBins, unsigned int);
itkSetMacro(NumberOfRegions, unsigned int);
itkGetConstMacro(NumberOfRegions, unsigned int);
itkSetMacro(UseValley, bool);
itkGetConstMacro(UseValley, bool);
itkBooleanMacro(UseValley);
/**Returns the number of max bins based on the current input image.*/
unsigned int GetMaxNumberOfBins() const;
protected:
- OtsuTool3D() = default;
+ OtsuTool3D();
~OtsuTool3D() = default;
void UpdatePrepare() override;
void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep) override;
unsigned int m_NumberOfBins = 128;
unsigned int m_NumberOfRegions = 2;
bool m_UseValley = false;
}; // class
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkPickingTool.cpp b/Modules/Segmentation/Interactions/mitkPickingTool.cpp
index 96afc90601..6478b66ed6 100644
--- a/Modules/Segmentation/Interactions/mitkPickingTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkPickingTool.cpp
@@ -1,256 +1,259 @@
/*============================================================================
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 "mitkPickingTool.h"
#include "mitkProperties.h"
#include "mitkToolManager.h"
#include "mitkInteractionPositionEvent.h"
// us
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <usModuleResource.h>
#include "mitkITKImageImport.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageCast.h"
#include "mitkImageTimeSelector.h"
#include <itkImage.h>
#include <itkConnectedThresholdImageFilter.h>
#include <itkOrImageFilter.h>
#include <mitkLabelSetImage.h>
namespace mitk
{
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, PickingTool, "PickingTool");
}
mitk::PickingTool::PickingTool() : SegWithPreviewTool(false, "PressMoveReleaseAndPointSetting")
{
this->ResetsToEmptyPreviewOn();
}
mitk::PickingTool::~PickingTool()
{
}
const char **mitk::PickingTool::GetXPM() const
{
return nullptr;
}
const char *mitk::PickingTool::GetName() const
{
return "Picking";
}
us::ModuleResource mitk::PickingTool::GetIconResource() const
{
us::Module *module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("Picking.svg");
return resource;
}
void mitk::PickingTool::Activated()
{
Superclass::Activated();
m_PointSet = mitk::PointSet::New();
//ensure that the seed points are visible for all timepoints.
dynamic_cast<ProportionalTimeGeometry*>(m_PointSet->GetTimeGeometry())->SetStepDuration(std::numeric_limits<TimePointType>::max());
m_PointSetNode = mitk::DataNode::New();
m_PointSetNode->SetData(m_PointSet);
m_PointSetNode->SetName(std::string(this->GetName()) + "_PointSet");
m_PointSetNode->SetBoolProperty("helper object", true);
m_PointSetNode->SetColor(0.0, 1.0, 0.0);
m_PointSetNode->SetVisibility(true);
this->GetDataStorage()->Add(m_PointSetNode, this->GetToolManager()->GetWorkingData(0));
}
void mitk::PickingTool::Deactivated()
{
this->ClearSeeds();
// remove from data storage and disable interaction
GetDataStorage()->Remove(m_PointSetNode);
m_PointSetNode = nullptr;
m_PointSet = nullptr;
Superclass::Deactivated();
}
void mitk::PickingTool::ConnectActionsAndFunctions()
{
CONNECT_FUNCTION("ShiftSecondaryButtonPressed", OnAddPoint);
CONNECT_FUNCTION("ShiftPrimaryButtonPressed", OnAddPoint);
CONNECT_FUNCTION("DeletePoint", OnDelete);
}
void mitk::PickingTool::OnAddPoint(StateMachineAction*, InteractionEvent* interactionEvent)
{
if (!this->IsUpdating() && m_PointSet.IsNotNull())
{
const auto positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>(interactionEvent);
if (positionEvent != nullptr)
{
m_PointSet->InsertPoint(m_PointSet->GetSize(), positionEvent->GetPositionInWorld());
this->UpdatePreview();
}
}
}
void mitk::PickingTool::OnDelete(StateMachineAction*, InteractionEvent* /*interactionEvent*/)
{
if (!this->IsUpdating() && m_PointSet.IsNotNull())
{
// delete last seed point
if (this->m_PointSet->GetSize() > 0)
{
m_PointSet->RemovePointAtEnd(0);
this->UpdatePreview();
}
}
}
void mitk::PickingTool::ClearPicks()
{
this->ClearSeeds();
this->UpdatePreview();
}
bool mitk::PickingTool::HasPicks() const
{
return this->m_PointSet.IsNotNull() && this->m_PointSet->GetSize()>0;
}
void mitk::PickingTool::ClearSeeds()
{
if (this->m_PointSet.IsNotNull())
{
// renew pointset
this->m_PointSet = mitk::PointSet::New();
//ensure that the seed points are visible for all timepoints.
dynamic_cast<ProportionalTimeGeometry*>(m_PointSet->GetTimeGeometry())->SetStepDuration(std::numeric_limits<TimePointType>::max());
this->m_PointSetNode->SetData(this->m_PointSet);
}
}
template <typename TPixel, unsigned int VImageDimension>
void DoITKRegionGrowing(const itk::Image<TPixel, VImageDimension>* oldSegImage,
mitk::Image* segmentation,
const mitk::PointSet* seedPoints,
unsigned int timeStep, const mitk::BaseGeometry* inputGeometry, const mitk::Label::PixelType outputValue,
const mitk::Label::PixelType backgroundValue,
bool& emptyTimeStep)
{
typedef itk::Image<TPixel, VImageDimension> InputImageType;
typedef itk::Image<mitk::Label::PixelType, VImageDimension> OutputImageType;
typedef typename InputImageType::IndexType IndexType;
typedef itk::ConnectedThresholdImageFilter<InputImageType, OutputImageType> RegionGrowingFilterType;
using IndexMapType = std::map < mitk::Label::PixelType, std::vector<IndexType> >;
IndexMapType indexMap;
// convert world coordinates to image indices
for (auto pos = seedPoints->Begin(); pos != seedPoints->End(); ++pos)
{
IndexType seedIndex;
inputGeometry->WorldToIndex(pos->Value(), seedIndex);
const auto selectedLabel = oldSegImage->GetPixel(seedIndex);
if (selectedLabel != backgroundValue)
{
indexMap[selectedLabel].push_back(seedIndex);
}
}
typename OutputImageType::Pointer itkResultImage;
try
{
bool first = true;
typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
regionGrower->SetInput(oldSegImage);
regionGrower->SetReplaceValue(outputValue);
for (const auto& [label, indeces] : indexMap)
{
// perform region growing in desired segmented region
regionGrower->ClearSeeds();
for (const auto& index : indeces)
{
regionGrower->AddSeed(index);
}
regionGrower->SetLower(label);
regionGrower->SetUpper(label);
regionGrower->Update();
if (first)
{
itkResultImage = regionGrower->GetOutput();
}
else
{
typename itk::OrImageFilter<OutputImageType, OutputImageType>::Pointer orFilter =
itk::OrImageFilter<OutputImageType, OutputImageType>::New();
orFilter->SetInput1(regionGrower->GetOutput());
orFilter->SetInput2(itkResultImage);
orFilter->Update();
itkResultImage = orFilter->GetOutput();
}
first = false;
itkResultImage->DisconnectPipeline();
}
}
catch (const itk::ExceptionObject&)
{
return; // can't work
}
catch (...)
{
return;
}
if (itkResultImage.IsNotNull())
{
segmentation->SetVolume((void*)(itkResultImage->GetPixelContainer()->GetBufferPointer()),timeStep);
}
emptyTimeStep = itkResultImage.IsNull();
}
void mitk::PickingTool::DoUpdatePreview(const Image* /*inputAtTimeStep*/, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep)
{
if (nullptr != oldSegAtTimeStep && nullptr != previewImage && m_PointSet.IsNotNull())
{
bool emptyTimeStep = true;
if (this->HasPicks())
{
- AccessFixedDimensionByItk_n(oldSegAtTimeStep, DoITKRegionGrowing, 3, (previewImage, this->m_PointSet, timeStep, oldSegAtTimeStep->GetGeometry(), this->GetUserDefinedActiveLabel(), mitk::LabelSetImage::UnlabeledValue, emptyTimeStep));
+ const auto activeValue = this->GetActiveLabelValueOfPreview();
+ this->SetSelectedLabels({activeValue});
+
+ AccessFixedDimensionByItk_n(oldSegAtTimeStep, DoITKRegionGrowing, 3, (previewImage, this->m_PointSet, timeStep, oldSegAtTimeStep->GetGeometry(), activeValue, mitk::LabelSetImage::UnlabeledValue, emptyTimeStep));
}
if (emptyTimeStep)
{
this->ResetPreviewContentAtTimeStep(timeStep);
}
}
}
diff --git a/Modules/Segmentation/Interactions/mitkSegTool2D.cpp b/Modules/Segmentation/Interactions/mitkSegTool2D.cpp
index d4c5bb1b6e..3cab141cdc 100644
--- a/Modules/Segmentation/Interactions/mitkSegTool2D.cpp
+++ b/Modules/Segmentation/Interactions/mitkSegTool2D.cpp
@@ -1,798 +1,798 @@
/*============================================================================
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 "mitkSegTool2D.h"
#include "mitkToolManager.h"
#include "mitkBaseRenderer.h"
#include "mitkDataStorage.h"
#include "mitkPlaneGeometry.h"
+#include <mitkTimeNavigationController.h>
// Include of the new ImageExtractor
#include "mitkMorphologicalOperations.h"
#include "mitkPlanarCircle.h"
#include "usGetModuleContext.h"
// Includes for 3DSurfaceInterpolation
#include "mitkImageTimeSelector.h"
#include "mitkImageToContourFilter.h"
#include "mitkSurfaceInterpolationController.h"
// includes for resling and overwriting
#include <mitkExtractSliceFilter.h>
#include <mitkVtkImageOverwrite.h>
#include <vtkImageData.h>
#include <vtkSmartPointer.h>
#include "mitkOperationEvent.h"
#include "mitkUndoController.h"
#include <mitkDiffSliceOperationApplier.h>
#include "mitkAbstractTransformGeometry.h"
#include "mitkLabelSetImage.h"
#include "mitkContourModelUtils.h"
// #include <itkImageRegionIterator.h>
#include <vtkAbstractArray.h>
#include <vtkFieldData.h>
#define ROUND(a) ((a) > 0 ? (int)((a) + 0.5) : -(int)(0.5 - (a)))
bool mitk::SegTool2D::m_SurfaceInterpolationEnabled = true;
mitk::SegTool2D::SliceInformation::SliceInformation(const mitk::Image* aSlice, const mitk::PlaneGeometry* aPlane, mitk::TimeStepType aTimestep) :
slice(aSlice), plane(aPlane), timestep(aTimestep)
{
}
mitk::SegTool2D::SegTool2D(const char *type, const us::Module *interactorModule)
: Tool(type, interactorModule), m_Contourmarkername("Position")
{
Tool::m_EventConfig = "DisplayConfigBlockLMB.xml";
}
mitk::SegTool2D::~SegTool2D()
{
}
bool mitk::SegTool2D::FilterEvents(InteractionEvent *interactionEvent, DataNode *)
{
const auto *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
bool isValidEvent =
(positionEvent && // Only events of type mitk::InteractionPositionEvent
interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D // Only events from the 2D renderwindows
);
return isValidEvent;
}
bool mitk::SegTool2D::DetermineAffectedImageSlice(const Image *image,
const PlaneGeometry *plane,
int &affectedDimension,
int &affectedSlice)
{
assert(image);
assert(plane);
// compare normal of plane to the three axis vectors of the image
Vector3D normal = plane->GetNormal();
Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0);
Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1);
Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2);
normal.Normalize();
imageNormal0.Normalize();
imageNormal1.Normalize();
imageNormal2.Normalize();
imageNormal0.SetVnlVector(vnl_cross_3d<ScalarType>(normal.GetVnlVector(), imageNormal0.GetVnlVector()));
imageNormal1.SetVnlVector(vnl_cross_3d<ScalarType>(normal.GetVnlVector(), imageNormal1.GetVnlVector()));
imageNormal2.SetVnlVector(vnl_cross_3d<ScalarType>(normal.GetVnlVector(), imageNormal2.GetVnlVector()));
double eps(0.00001);
// axial
if (imageNormal2.GetNorm() <= eps)
{
affectedDimension = 2;
}
// sagittal
else if (imageNormal1.GetNorm() <= eps)
{
affectedDimension = 1;
}
// coronal
else if (imageNormal0.GetNorm() <= eps)
{
affectedDimension = 0;
}
else
{
affectedDimension = -1; // no idea
return false;
}
// determine slice number in image
BaseGeometry *imageGeometry = image->GetGeometry(0);
Point3D testPoint = imageGeometry->GetCenter();
Point3D projectedPoint;
plane->Project(testPoint, projectedPoint);
Point3D indexPoint;
imageGeometry->WorldToIndex(projectedPoint, indexPoint);
affectedSlice = ROUND(indexPoint[affectedDimension]);
MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice "
<< affectedSlice;
// check if this index is still within the image
if (affectedSlice < 0 || affectedSlice >= static_cast<int>(image->GetDimension(affectedDimension)))
return false;
return true;
}
void mitk::SegTool2D::UpdateSurfaceInterpolation(const Image *slice,
const Image *workingImage,
const PlaneGeometry *plane,
bool detectIntersection)
{
std::vector<SliceInformation> slices = { SliceInformation(slice, plane, 0)};
Self::UpdateSurfaceInterpolation(slices, workingImage, detectIntersection, 0, 0);
}
void mitk::SegTool2D::RemoveContourFromInterpolator(const SliceInformation& sliceInfo)
{
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo;
contourInfo.ContourNormal = sliceInfo.plane->GetNormal();
contourInfo.ContourPoint = sliceInfo.plane->GetOrigin();
mitk::SurfaceInterpolationController::GetInstance()->RemoveContour(contourInfo);
}
void mitk::SegTool2D::UpdateSurfaceInterpolation(const std::vector<SliceInformation>& sliceInfos,
const Image* workingImage,
bool detectIntersection,
unsigned int activeLayerID,
mitk::Label::PixelType activeLabelValue)
{
if (!m_SurfaceInterpolationEnabled)
return;
//Remark: the ImageTimeSelector is just needed to extract a timestep/channel of
//the image in order to get the image dimension (time dimension and channel dimension
//stripped away). Therfore it is OK to always use time step 0 and channel 0
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(workingImage);
timeSelector->SetTimeNr(0);
timeSelector->SetChannelNr(0);
timeSelector->Update();
const auto dimRefImg = timeSelector->GetOutput()->GetDimension();
if (dimRefImg != 3)
return;
std::vector<mitk::Surface::Pointer> contourList;
contourList.reserve(sliceInfos.size());
ImageToContourFilter::Pointer contourExtractor = ImageToContourFilter::New();
std::vector<SliceInformation> relevantSlices = sliceInfos;
if (detectIntersection)
{
relevantSlices.clear();
for (const auto& sliceInfo : sliceInfos)
{
// Test whether there is something to extract or whether the slice just contains intersections of others
mitk::Image::Pointer slice2 = sliceInfo.slice->Clone();
mitk::MorphologicalOperations::Erode(slice2, 2, mitk::MorphologicalOperations::Ball);
contourExtractor->SetInput(slice2);
contourExtractor->Update();
mitk::Surface::Pointer contour = contourExtractor->GetOutput();
if (contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
{
Self::RemoveContourFromInterpolator(sliceInfo);
}
else
{
relevantSlices.push_back(sliceInfo);
}
}
}
if (relevantSlices.empty())
return;
std::vector<const mitk::PlaneGeometry*> contourPlanes;
for (const auto& sliceInfo : relevantSlices)
{
contourExtractor->SetInput(sliceInfo.slice);
contourExtractor->SetContourValue(activeLabelValue);
contourExtractor->Update();
mitk::Surface::Pointer contour = contourExtractor->GetOutput();
if (contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
{
Self::RemoveContourFromInterpolator(sliceInfo);
}
else
{
vtkSmartPointer<vtkIntArray> intArray = vtkSmartPointer<vtkIntArray>::New();
intArray->InsertNextValue(activeLabelValue);
intArray->InsertNextValue(activeLayerID);
contour->GetVtkPolyData()->GetFieldData()->AddArray(intArray);
contour->DisconnectPipeline();
contourList.push_back(contour);
contourPlanes.push_back(sliceInfo.plane);
}
}
mitk::SurfaceInterpolationController::GetInstance()->AddNewContours(contourList, contourPlanes);
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedImageSliceAs2DImage(const InteractionPositionEvent *positionEvent, const Image *image, unsigned int component /*= 0*/)
{
if (!positionEvent)
{
return nullptr;
}
assert(positionEvent->GetSender()); // sure, right?
const auto timeStep = positionEvent->GetSender()->GetTimeStep(image); // get the timestep of the visible part (time-wise) of the image
return GetAffectedImageSliceAs2DImage(positionEvent->GetSender()->GetCurrentWorldPlaneGeometry(), image, timeStep, component);
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(const PlaneGeometry* planeGeometry, const Image* image, TimePointType timePoint, unsigned int component /*= 0*/)
{
if (!image || !planeGeometry)
{
return nullptr;
}
if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint))
return nullptr;
return SegTool2D::GetAffectedImageSliceAs2DImage(planeGeometry, image, image->GetTimeGeometry()->TimePointToTimeStep(timePoint), component);
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedImageSliceAs2DImage(const PlaneGeometry *planeGeometry, const Image *image, TimeStepType timeStep, unsigned int component /*= 0*/)
{
if (!image || !planeGeometry)
{
return nullptr;
}
// Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk reslicer
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
// set to false to extract a slice
reslice->SetOverwriteMode(false);
reslice->Modified();
// use ExtractSliceFilter with our specific vtkImageReslice for overwriting and extracting
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput(image);
extractor->SetTimeStep(timeStep);
extractor->SetWorldGeometry(planeGeometry);
extractor->SetVtkOutputRequest(false);
extractor->SetResliceTransformByGeometry(image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
// additionally extract the given component
// default is 0; the extractor checks for multi-component images
extractor->SetComponent(component);
extractor->Modified();
extractor->Update();
Image::Pointer slice = extractor->GetOutput();
return slice;
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedWorkingSlice(const InteractionPositionEvent *positionEvent) const
{
const auto workingNode = this->GetWorkingDataNode();
if (!workingNode)
{
return nullptr;
}
const auto *workingImage = dynamic_cast<Image *>(workingNode->GetData());
if (!workingImage)
{
return nullptr;
}
return GetAffectedImageSliceAs2DImage(positionEvent, workingImage);
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedReferenceSlice(const InteractionPositionEvent *positionEvent) const
{
DataNode* referenceNode = this->GetReferenceDataNode();
if (!referenceNode)
{
return nullptr;
}
auto *referenceImage = dynamic_cast<Image *>(referenceNode->GetData());
if (!referenceImage)
{
return nullptr;
}
int displayedComponent = 0;
if (referenceNode->GetIntProperty("Image.Displayed Component", displayedComponent))
{
// found the displayed component
return GetAffectedImageSliceAs2DImage(positionEvent, referenceImage, displayedComponent);
}
else
{
return GetAffectedImageSliceAs2DImage(positionEvent, referenceImage);
}
}
mitk::Image::Pointer mitk::SegTool2D::GetAffectedReferenceSlice(const PlaneGeometry* planeGeometry, TimeStepType timeStep) const
{
DataNode* referenceNode = this->GetReferenceDataNode();
if (!referenceNode)
{
return nullptr;
}
auto* referenceImage = dynamic_cast<Image*>(referenceNode->GetData());
if (!referenceImage)
{
return nullptr;
}
int displayedComponent = 0;
if (referenceNode->GetIntProperty("Image.Displayed Component", displayedComponent))
{
// found the displayed component
return GetAffectedImageSliceAs2DImage(planeGeometry, referenceImage, timeStep, displayedComponent);
}
else
{
return GetAffectedImageSliceAs2DImage(planeGeometry, referenceImage, timeStep);
}
}
void mitk::SegTool2D::Activated()
{
Superclass::Activated();
this->GetToolManager()->SelectedTimePointChanged +=
mitk::MessageDelegate<mitk::SegTool2D>(this, &mitk::SegTool2D::OnTimePointChangedInternal);
m_LastTimePointTriggered = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
}
void mitk::SegTool2D::Deactivated()
{
this->GetToolManager()->SelectedTimePointChanged -=
mitk::MessageDelegate<mitk::SegTool2D>(this, &mitk::SegTool2D::OnTimePointChangedInternal);
Superclass::Deactivated();
}
void mitk::SegTool2D::OnTimePointChangedInternal()
{
if (m_IsTimePointChangeAware && nullptr != this->GetWorkingDataNode())
{
- const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
-
+ const TimePointType timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
if (timePoint != m_LastTimePointTriggered)
{
m_LastTimePointTriggered = timePoint;
this->OnTimePointChanged();
}
}
}
void mitk::SegTool2D::OnTimePointChanged()
{
//default implementation does nothing
}
mitk::DataNode* mitk::SegTool2D::GetWorkingDataNode() const
{
if (nullptr != this->GetToolManager())
{
return this->GetToolManager()->GetWorkingData(0);
}
return nullptr;
}
mitk::Image* mitk::SegTool2D::GetWorkingData() const
{
auto node = this->GetWorkingDataNode();
if (nullptr != node)
{
return dynamic_cast<Image*>(node->GetData());
}
return nullptr;
}
mitk::DataNode* mitk::SegTool2D::GetReferenceDataNode() const
{
if (nullptr != this->GetToolManager())
{
return this->GetToolManager()->GetReferenceData(0);
}
return nullptr;
}
mitk::Image* mitk::SegTool2D::GetReferenceData() const
{
auto node = this->GetReferenceDataNode();
if (nullptr != node)
{
return dynamic_cast<Image*>(node->GetData());
}
return nullptr;
}
void mitk::SegTool2D::WriteBackSegmentationResult(const InteractionPositionEvent *positionEvent, const Image * segmentationResult)
{
if (!positionEvent)
return;
const PlaneGeometry *planeGeometry((positionEvent->GetSender()->GetCurrentWorldPlaneGeometry()));
const auto *abstractTransformGeometry(
dynamic_cast<const AbstractTransformGeometry *>(positionEvent->GetSender()->GetCurrentWorldPlaneGeometry()));
if (planeGeometry && segmentationResult && !abstractTransformGeometry)
{
const auto workingNode = this->GetWorkingDataNode();
auto *image = dynamic_cast<Image *>(workingNode->GetData());
const auto timeStep = positionEvent->GetSender()->GetTimeStep(image);
this->WriteBackSegmentationResult(planeGeometry, segmentationResult, timeStep);
}
}
void mitk::SegTool2D::WriteBackSegmentationResult(const DataNode* workingNode, const PlaneGeometry* planeGeometry, const Image* segmentationResult, TimeStepType timeStep)
{
if (!planeGeometry || !segmentationResult)
return;
SliceInformation sliceInfo(segmentationResult, const_cast<mitk::PlaneGeometry*>(planeGeometry), timeStep);
Self::WriteBackSegmentationResults(workingNode, { sliceInfo }, true);
}
void mitk::SegTool2D::WriteBackSegmentationResult(const PlaneGeometry *planeGeometry,
const Image * segmentationResult,
TimeStepType timeStep)
{
if (!planeGeometry || !segmentationResult)
return;
if(m_LastEventSender == nullptr)
{
return;
}
- unsigned int currentSlicePosition = m_LastEventSender->GetSliceNavigationController()->GetSlice()->GetPos();
+ unsigned int currentSlicePosition = m_LastEventSender->GetSliceNavigationController()->GetStepper()->GetPos();
SliceInformation sliceInfo(segmentationResult, const_cast<mitk::PlaneGeometry *>(planeGeometry), timeStep);
sliceInfo.slicePosition = currentSlicePosition;
WriteBackSegmentationResults({ sliceInfo }, true);
}
void mitk::SegTool2D::WriteBackSegmentationResults(const std::vector<SegTool2D::SliceInformation> &sliceList,
bool writeSliceToVolume)
{
if (sliceList.empty())
{
return;
}
if (nullptr == m_LastEventSender)
{
MITK_WARN << "Cannot write tool results. Tool seems to be in an invalid state, as no interaction event was recieved but is expected.";
return;
}
const auto workingNode = this->GetWorkingDataNode();
// the first geometry is needed otherwise restoring the position is not working
const auto* plane3 =
dynamic_cast<const PlaneGeometry*>(dynamic_cast<const mitk::SlicedGeometry3D*>(
m_LastEventSender->GetSliceNavigationController()->GetCurrentGeometry3D())
->GetPlaneGeometry(0));
- unsigned int slicePosition = m_LastEventSender->GetSliceNavigationController()->GetSlice()->GetPos();
+ const unsigned int slicePosition = m_LastEventSender->GetSliceNavigationController()->GetStepper()->GetPos();
mitk::SegTool2D::WriteBackSegmentationResults(workingNode, sliceList, writeSliceToVolume);
/* A cleaner solution would be to add a contour marker for each slice info. It currently
does not work as the contour markers expect that the plane is always the plane of slice 0.
Had not the time to do it properly no. Should be solved by T28146*/
this->AddContourmarker(plane3, slicePosition);
}
void mitk::SegTool2D::WriteBackSegmentationResults(const DataNode* workingNode, const std::vector<SliceInformation>& sliceList, bool writeSliceToVolume)
{
if (sliceList.empty())
{
return;
}
if (nullptr == workingNode)
{
mitkThrow() << "Cannot write slice to working node. Working node is invalid.";
}
auto image = dynamic_cast<Image*>(workingNode->GetData());
mitk::Label::PixelType activeLabelValue = 0;
unsigned int activeLayerID = 0;
try{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
activeLayerID = labelSetImage->GetActiveLayer();
activeLabelValue = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetValue();
}
catch(...)
{
mitkThrow() << "Working node does not contain labelSetImage.";
}
if (nullptr == image)
{
mitkThrow() << "Cannot write slice to working node. Working node does not contain an image.";
}
for (const auto& sliceInfo : sliceList)
{
if (writeSliceToVolume && nullptr != sliceInfo.plane && sliceInfo.slice.IsNotNull())
{
SegTool2D::WriteSliceToVolume(image, sliceInfo, true);
}
}
SegTool2D::UpdateSurfaceInterpolation(sliceList, image, false, activeLayerID, activeLabelValue);
// also mark its node as modified (T27308). Can be removed if T27307
// is properly solved
if (workingNode != nullptr) workingNode->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::SegTool2D::WriteSliceToVolume(Image* workingImage, const PlaneGeometry* planeGeometry, const Image* slice, TimeStepType timeStep, bool allowUndo)
{
SliceInformation sliceInfo(slice, planeGeometry, timeStep);
WriteSliceToVolume(workingImage, sliceInfo, allowUndo);
}
void mitk::SegTool2D::WriteSliceToVolume(Image* workingImage, const SliceInformation &sliceInfo, bool allowUndo)
{
if (nullptr == workingImage)
{
mitkThrow() << "Cannot write slice to working node. Working node does not contain an image.";
}
DiffSliceOperation* undoOperation = nullptr;
if (allowUndo)
{
/*============= BEGIN undo/redo feature block ========================*/
// Create undo operation by caching the not yet modified slices
mitk::Image::Pointer originalSlice = GetAffectedImageSliceAs2DImage(sliceInfo.plane, workingImage, sliceInfo.timestep);
undoOperation =
new DiffSliceOperation(workingImage,
originalSlice,
dynamic_cast<SlicedGeometry3D*>(originalSlice->GetGeometry()),
sliceInfo.timestep,
sliceInfo.plane);
/*============= END undo/redo feature block ========================*/
}
// Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk
// reslicer
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
// Set the slice as 'input'
// casting const away is needed and OK as long the OverwriteMode of
// mitkVTKImageOverwrite is true.
// Reason: because then the input slice is not touched but
// used to overwrite the input of the ExtractSliceFilter.
auto noneConstSlice = const_cast<Image*>(sliceInfo.slice.GetPointer());
reslice->SetInputSlice(noneConstSlice->GetVtkImageData());
// set overwrite mode to true to write back to the image volume
reslice->SetOverwriteMode(true);
reslice->Modified();
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput(workingImage);
extractor->SetTimeStep(sliceInfo.timestep);
extractor->SetWorldGeometry(sliceInfo.plane);
extractor->SetVtkOutputRequest(false);
extractor->SetResliceTransformByGeometry(workingImage->GetGeometry(sliceInfo.timestep));
extractor->Modified();
extractor->Update();
// the image was modified within the pipeline, but not marked so
workingImage->Modified();
workingImage->GetVtkImageData()->Modified();
if (allowUndo)
{
/*============= BEGIN undo/redo feature block ========================*/
// specify the redo operation with the edited slice
auto* doOperation =
new DiffSliceOperation(workingImage,
extractor->GetOutput(),
dynamic_cast<SlicedGeometry3D*>(sliceInfo.slice->GetGeometry()),
sliceInfo.timestep,
sliceInfo.plane);
// create an operation event for the undo stack
OperationEvent* undoStackItem =
new OperationEvent(DiffSliceOperationApplier::GetInstance(), doOperation, undoOperation, "Segmentation");
// add it to the undo controller
UndoStackItem::IncCurrObjectEventId();
UndoStackItem::IncCurrGroupEventId();
UndoController::GetCurrentUndoModel()->SetOperationEvent(undoStackItem);
/*============= END undo/redo feature block ========================*/
}
}
void mitk::SegTool2D::SetShowMarkerNodes(bool status)
{
m_ShowMarkerNodes = status;
}
void mitk::SegTool2D::SetEnable3DInterpolation(bool enabled)
{
m_SurfaceInterpolationEnabled = enabled;
}
int mitk::SegTool2D::AddContourmarker(const PlaneGeometry* planeGeometry, unsigned int sliceIndex)
{
if (planeGeometry == nullptr)
return -1;
us::ServiceReference<PlanePositionManagerService> serviceRef =
us::GetModuleContext()->GetServiceReference<PlanePositionManagerService>();
PlanePositionManagerService *service = us::GetModuleContext()->GetService(serviceRef);
unsigned int size = service->GetNumberOfPlanePositions();
unsigned int id = service->AddNewPlanePosition(planeGeometry, sliceIndex);
mitk::PlanarCircle::Pointer contourMarker = mitk::PlanarCircle::New();
mitk::Point2D p1;
planeGeometry->Map(planeGeometry->GetCenter(), p1);
contourMarker->SetPlaneGeometry(planeGeometry->Clone());
contourMarker->PlaceFigure(p1);
contourMarker->SetCurrentControlPoint(p1);
contourMarker->SetProperty("initiallyplaced", mitk::BoolProperty::New(true));
std::stringstream markerStream;
auto workingNode = this->GetWorkingDataNode();
markerStream << m_Contourmarkername;
markerStream << " ";
markerStream << id + 1;
DataNode::Pointer rotatedContourNode = DataNode::New();
rotatedContourNode->SetData(contourMarker);
rotatedContourNode->SetProperty("name", StringProperty::New(markerStream.str()));
rotatedContourNode->SetProperty("isContourMarker", BoolProperty::New(true));
rotatedContourNode->SetBoolProperty("PlanarFigureInitializedWindow", true, m_LastEventSender);
rotatedContourNode->SetProperty("includeInBoundingBox", BoolProperty::New(false));
rotatedContourNode->SetProperty("helper object", mitk::BoolProperty::New(!m_ShowMarkerNodes));
rotatedContourNode->SetProperty("planarfigure.drawcontrolpoints", BoolProperty::New(false));
rotatedContourNode->SetProperty("planarfigure.drawname", BoolProperty::New(false));
rotatedContourNode->SetProperty("planarfigure.drawoutline", BoolProperty::New(false));
rotatedContourNode->SetProperty("planarfigure.drawshadow", BoolProperty::New(false));
if (planeGeometry)
{
if (id == size)
{
this->GetToolManager()->GetDataStorage()->Add(rotatedContourNode, workingNode);
}
else
{
mitk::NodePredicateProperty::Pointer isMarker =
mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true));
mitk::DataStorage::SetOfObjects::ConstPointer markers =
this->GetToolManager()->GetDataStorage()->GetDerivations(workingNode, isMarker);
for (auto iter = markers->begin(); iter != markers->end(); ++iter)
{
std::string nodeName = (*iter)->GetName();
unsigned int t = nodeName.find_last_of(" ");
unsigned int markerId = atof(nodeName.substr(t + 1).c_str()) - 1;
if (id == markerId)
{
return id;
}
}
this->GetToolManager()->GetDataStorage()->Add(rotatedContourNode, workingNode);
}
}
return id;
}
void mitk::SegTool2D::InteractiveSegmentationBugMessage(const std::string &message) const
{
MITK_ERROR << "********************************************************************************" << std::endl
<< " " << message << std::endl
<< "********************************************************************************" << std::endl
<< " " << std::endl
<< " If your image is rotated or the 2D views don't really contain the patient image, try to press the "
"button next to the image selection. "
<< std::endl
<< " " << std::endl
<< " Please file a BUG REPORT: " << std::endl
<< " https://phabricator.mitk.org/" << std::endl
<< " Contain the following information:" << std::endl
<< " - What image were you working on?" << std::endl
<< " - Which region of the image?" << std::endl
<< " - Which tool did you use?" << std::endl
<< " - What did you do?" << std::endl
<< " - What happened (not)? What did you expect?" << std::endl;
}
void mitk::SegTool2D::WritePreviewOnWorkingImage(
Image *targetSlice, const Image *sourceSlice, const Image *workingImage, int paintingPixelValue)
{
if (nullptr == targetSlice)
{
mitkThrow() << "Cannot write preview on working image. Target slice does not point to a valid instance.";
}
if (nullptr == sourceSlice)
{
mitkThrow() << "Cannot write preview on working image. Source slice does not point to a valid instance.";
}
if (nullptr == workingImage)
{
mitkThrow() << "Cannot write preview on working image. Working image does not point to a valid instance.";
}
auto constVtkSource = sourceSlice->GetVtkImageData();
/*Need to const cast because Vtk interface does not support const correctly.
(or I am not experienced enough to use it correctly)*/
auto nonConstVtkSource = const_cast<vtkImageData*>(constVtkSource);
ContourModelUtils::FillSliceInSlice(nonConstVtkSource, targetSlice->GetVtkImageData(), workingImage, paintingPixelValue, 1.0);
}
bool mitk::SegTool2D::IsPositionEventInsideImageRegion(mitk::InteractionPositionEvent* positionEvent,
const mitk::BaseData* data)
{
bool isPositionEventInsideImageRegion =
nullptr != data && data->GetGeometry()->IsInside(positionEvent->GetPositionInWorld());
if (!isPositionEventInsideImageRegion)
MITK_WARN("EditableContourTool") << "PositionEvent is outside ImageRegion!";
return isPositionEventInsideImageRegion;
}
diff --git a/Modules/Segmentation/Interactions/mitkSegTool2D.h b/Modules/Segmentation/Interactions/mitkSegTool2D.h
index d41c9f7d5f..99d6fdf91a 100644
--- a/Modules/Segmentation/Interactions/mitkSegTool2D.h
+++ b/Modules/Segmentation/Interactions/mitkSegTool2D.h
@@ -1,303 +1,303 @@
/*============================================================================
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 mitkSegTool2D_h
#define mitkSegTool2D_h
#include <mitkCommon.h>
#include <mitkImage.h>
#include <mitkTool.h>
#include <MitkSegmentationExports.h>
#include <mitkInteractionPositionEvent.h>
#include <mitkInteractionConst.h>
#include <mitkPlanePositionManager.h>
#include <mitkRestorePlanePositionOperation.h>
#include <mitkDiffSliceOperation.h>
namespace mitk
{
class BaseRenderer;
/**
\brief Abstract base class for segmentation tools.
\sa Tool
\ingroup Interaction
\ingroup ToolManagerEtAl
Implements 2D segmentation specific helper methods, that might be of use to
all kind of 2D segmentation tools. At the moment these are:
- Determination of the slice where the user paints upon (DetermineAffectedImageSlice)
- Projection of a 3D contour onto a 2D plane/slice
SegTool2D tries to structure the interaction a bit. If you pass "PressMoveRelease" as the interaction type
of your derived tool, you might implement the methods OnMousePressed, OnMouseMoved, and OnMouseReleased.
Yes, your guess about when they are called is correct.
\warning Only to be instantiated by mitk::ToolManager.
$Author$
*/
class MITKSEGMENTATION_EXPORT SegTool2D : public Tool
{
public:
mitkClassMacro(SegTool2D, Tool);
/**
\brief Calculates for a given Image and PlaneGeometry, which slice of the image (in index corrdinates) is meant by
the plane.
\return false, if no slice direction seems right (e.g. rotated planes)
\param image
\param plane
\param affectedDimension The image dimension, which is constant for all points in the plane, e.g. Axial --> 2
\param affectedSlice The index of the image slice
*/
static bool DetermineAffectedImageSlice(const Image *image,
const PlaneGeometry *plane,
int &affectedDimension,
int &affectedSlice);
/**
* @brief Updates the surface interpolation by extracting the contour form the given slice.
* @param slice the slice from which the contour should be extracted
* @param workingImage the segmentation image
* @param plane the plane in which the slice lies
* @param detectIntersection if true the slice is eroded before contour extraction. If the slice is empty after the
* erosion it is most
* likely an intersecting contour an will not be added to the SurfaceInterpolationController
*/
static void UpdateSurfaceInterpolation(const Image *slice,
const Image *workingImage,
const PlaneGeometry *plane,
bool detectIntersection);
/**
* \brief Extract the slice of an image that the user just scribbles on. The given component denotes the vector component of an vector image.
*
* \param positionEvent Event that specifies the plane that should be used to slice
* \param image Image that should be sliced
* \param component The component to be extracted of a given multi-component image. -1 is the default parameter to denote an invalid component.
*
* \return 'nullptr' if SegTool2D is either unable to determine which slice was affected, or if there was some problem
* getting the image data at that position.
*/
static Image::Pointer GetAffectedImageSliceAs2DImage(const InteractionPositionEvent* positionEvent, const Image* image, unsigned int component = 0);
/**
* \brief Extract the slice of an image cut by given plane. The given component denotes the vector component of a vector image.
*
* \param planeGeometry Geometry defining the slice that should be cut out.
* \param image Image that should be sliced
* \param timeStep TimeStep of the image that shold be sliced
* \param component The component to be extracted of a given multi-component image. -1 is the default parameter to denote an invalid component.
*
* \return 'nullptr' if SegTool2D is either unable to determine which slice was affected, or if there was some problem
* getting the image data at that position.
*/
static Image::Pointer GetAffectedImageSliceAs2DImage(const PlaneGeometry* planeGeometry,
const Image* image,
TimeStepType timeStep,
unsigned int component = 0);
static Image::Pointer GetAffectedImageSliceAs2DImageByTimePoint(const PlaneGeometry* planeGeometry,
const Image* image,
TimePointType timePoint,
unsigned int component = 0);
/** Convenience overloaded version that can be called for a given planeGeometry, slice image and time step.
* Calls static WriteBackSegmentationResults*/
static void WriteBackSegmentationResult(const DataNode* workingNode, const PlaneGeometry* planeGeometry, const Image* segmentationResult, TimeStepType timeStep);
/** Convenience overloaded version that can be called for a given planeGeometry, slice image and time step.
* For more details see protected WriteSliceToVolume version.*/
static void WriteSliceToVolume(Image* workingImage, const PlaneGeometry* planeGeometry, const Image* slice, TimeStepType timeStep, bool allowUndo);
void SetShowMarkerNodes(bool);
/**
* \brief Enables or disables the 3D interpolation after writing back the 2D segmentation result, and defaults to
* true.
*/
void SetEnable3DInterpolation(bool);
void Activated() override;
void Deactivated() override;
itkSetMacro(IsTimePointChangeAware, bool);
itkGetMacro(IsTimePointChangeAware, bool);
itkBooleanMacro(IsTimePointChangeAware);
protected:
SegTool2D(); // purposely hidden
SegTool2D(const char *, const us::Module *interactorModule = nullptr); // purposely hidden
~SegTool2D() override;
/**
* @brief returns the segmentation node that should be modified by the tool.
*/
DataNode* GetWorkingDataNode() const;
Image* GetWorkingData() const;
DataNode* GetReferenceDataNode() const;
Image* GetReferenceData() const;
/**
* This function can be reimplemented by derived classes to react on changes of the current
* time point. Default implementation does nothing.*/
virtual void OnTimePointChanged();
struct SliceInformation
{
mitk::Image::ConstPointer slice;
const mitk::PlaneGeometry *plane = nullptr;
mitk::TimeStepType timestep = 0;
unsigned int slicePosition;
SliceInformation() = default;
SliceInformation(const mitk::Image* aSlice, const mitk::PlaneGeometry* aPlane, mitk::TimeStepType aTimestep);
};
/**
* @brief Updates the surface interpolation by extracting the contour form the given slice.
* @param sliceInfos vector of slice information instances from which the contours should be extracted
* @param workingImage the segmentation image
* @param detectIntersection if true the slice is eroded before contour extraction. If the slice is empty after the
* @param activeLayerID The layer ID of the active label.
* @param activeLabelValue The label value of the active label.
* erosion it is most
* likely an intersecting contour an will not be added to the SurfaceInterpolationController
*/
static void UpdateSurfaceInterpolation(const std::vector<SliceInformation>& sliceInfos,
const Image* workingImage,
bool detectIntersection,
unsigned int activeLayerID,
mitk::Label::PixelType activeLabelValue);
/**
* \brief Filters events that cannot be handled by 2D segmentation tools
*
* Currently an event is discarded if it was not sent by a 2D renderwindow and if it is
* not of type InteractionPositionEvent
*/
bool FilterEvents(InteractionEvent *interactionEvent, DataNode *dataNode) override;
/**
\brief Extract the slice of the currently selected working image that the user just scribbles on.
\return nullptr if SegTool2D is either unable to determine which slice was affected, or if there was some problem
getting the image data at that position,
or just no working image is selected.
*/
Image::Pointer GetAffectedWorkingSlice(const InteractionPositionEvent *) const;
/**
\brief Extract the slice of the currently selected reference image that the user just scribbles on.
\return nullptr if SegTool2D is either unable to determine which slice was affected, or if there was some problem
getting the image data at that position,
or just no reference image is selected.
*/
Image::Pointer GetAffectedReferenceSlice(const InteractionPositionEvent *) const;
/** Overload version that gets the reference slice passed on the passed plane geometry and timestep.*/
Image::Pointer GetAffectedReferenceSlice(const PlaneGeometry* planeGeometry, TimeStepType timeStep) const;
/** Convenience version that can be called for a given event (which is used to deduce timepoint and plane) and a slice image.
* Calls non static WriteBackSegmentationResults*/
void WriteBackSegmentationResult(const InteractionPositionEvent *, const Image* segmentationResult);
/** Convenience version that can be called for a given planeGeometry, slice image and time step.
* Calls non static WriteBackSegmentationResults*/
void WriteBackSegmentationResult(const PlaneGeometry *planeGeometry, const Image* segmentationResult, TimeStepType timeStep);
/** Overloaded version that calls the static version and also adds the contour markers.
* @remark If the sliceList is empty, this function does nothing.*/
void WriteBackSegmentationResults(const std::vector<SliceInformation> &sliceList, bool writeSliceToVolume = true);
/** \brief Writes all provided source slices into the data of the passed workingNode.
* The function does the following: 1) for every passed slice write it to workingNode (and generate and undo/redo step);
- * 2) update the surface interpolation and 3) marke the node as modified.
+ * 2) update the surface interpolation and 3) mark the node as modified.
* @param workingNode Pointer to the node that contains the working image.
* @param sliceList Vector of all slices that should be written into the workingNode. If the list is
* empty, the function call does nothing.
* @param writeSliceToVolume If set to false the write operation (WriteSliceToVolume will be skipped)
* and only the surface interpolation will be updated.
* @pre workingNode must point to a valid instance and contain an image instance as data.*/
static void WriteBackSegmentationResults(const DataNode* workingNode, const std::vector<SliceInformation>& sliceList, bool writeSliceToVolume = true);
/** Writes the provided source slice into the target slice with the given pixel value.
* If passed workingImage is a LabelSetImage the label set rules will be applied when
* writing all non zero source pixels into the target slice (e.g. locked lables will not be touched)
* with the given paintingPixelValue.
* @param targetSlice Pointer to the slice that should be filled with the content of the sourceSlice.
* @param sourceSlice Pointer to the slice that is the source/preview every pixel will be (tried to be) transfered .
* @param workingImage Will be used to check if LabeSetImageRules have to be applied and the label set state.
* @param paintingPixelValue Value that will be used to paint onto target slice.
* @pre targetSlice must point to a valid instance.
* @pre sourceSlice must point to a valid instance.
* @pre workingImage must point to a valid instance.*/
static void WritePreviewOnWorkingImage(
Image *targetSlice, const Image *sourceSlice, const Image *workingImage, int paintingPixelValue);
/** Writes a provided slice into the passed working image. The content of working image that is covered
* by the slice will be completly overwritten. If asked for it also generates the needed
* undo/redo steps.
* @param workingImage Pointer to the image that is the target of the write operation.
* @param sliceInfo SliceInfo instance that containes the slice image, the defining plane geometry and time step.
* @param allowUndo Indicates if undo/redo operations should be registered for the write operation
* performed by this call. true: undo/redo will be generated; false: no undo/redo will be generated, so
* this operation cannot be revoked by the user.
* @pre workingImage must point to a valid instance.*/
static void WriteSliceToVolume(Image* workingImage, const SliceInformation &sliceInfo, bool allowUndo);
/**
\brief Adds a new node called Contourmarker to the datastorage which holds a mitk::PlanarFigure.
By selecting this node the slicestack will be reoriented according to the passed
PlanarFigure's Geometry
*/
int AddContourmarker(const PlaneGeometry* planeGeometry, unsigned int sliceIndex);
void InteractiveSegmentationBugMessage(const std::string &message) const;
/** Helper function to check if a position events points to a point inside the boundingbox of a passed
data instance.*/
static bool IsPositionEventInsideImageRegion(InteractionPositionEvent* positionEvent, const BaseData* data);
BaseRenderer *m_LastEventSender = nullptr;
unsigned int m_LastEventSlice = 0;
itkGetMacro(LastTimePointTriggered, TimePointType);
private:
/** Internal method that gets triggered as soon as the tool manager indicates a
* time point change. If the time point has changed since last time and tool
* is set to be time point change aware, OnTimePointChanged() will be called.*/
void OnTimePointChangedInternal();
static void RemoveContourFromInterpolator(const SliceInformation& sliceInfo);
// The prefix of the contourmarkername. Suffix is a consecutive number
const std::string m_Contourmarkername;
bool m_ShowMarkerNodes = false;
static bool m_SurfaceInterpolationEnabled;
bool m_IsTimePointChangeAware = true;
TimePointType m_LastTimePointTriggered = 0.;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.cpp b/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.cpp
index 9b89cc0b21..9ff48f4df5 100644
--- a/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.cpp
@@ -1,778 +1,819 @@
/*============================================================================
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 "mitkSegWithPreviewTool.h"
#include "mitkToolManager.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkDataStorage.h"
#include "mitkRenderingManager.h"
+#include <mitkTimeNavigationController.h>
#include "mitkImageAccessByItk.h"
#include "mitkImageCast.h"
#include "mitkLabelSetImage.h"
#include "mitkMaskAndCutRoiImageFilter.h"
#include "mitkPadImageFilter.h"
#include "mitkNodePredicateGeometry.h"
#include "mitkSegTool2D.h"
mitk::SegWithPreviewTool::SegWithPreviewTool(bool lazyDynamicPreviews): Tool("dummy"), m_LazyDynamicPreviews(lazyDynamicPreviews)
{
m_ProgressCommand = ToolCommand::New();
}
mitk::SegWithPreviewTool::SegWithPreviewTool(bool lazyDynamicPreviews, const char* interactorType, const us::Module* interactorModule) : Tool(interactorType, interactorModule), m_LazyDynamicPreviews(lazyDynamicPreviews)
{
m_ProgressCommand = ToolCommand::New();
}
mitk::SegWithPreviewTool::~SegWithPreviewTool()
{
}
void mitk::SegWithPreviewTool::SetMergeStyle(MultiLabelSegmentation::MergeStyle mergeStyle)
{
m_MergeStyle = mergeStyle;
this->Modified();
}
void mitk::SegWithPreviewTool::SetOverwriteStyle(MultiLabelSegmentation::OverwriteStyle overwriteStyle)
{
m_OverwriteStyle = overwriteStyle;
this->Modified();
}
void mitk::SegWithPreviewTool::SetLabelTransferScope(LabelTransferScope labelTransferScope)
{
m_LabelTransferScope = labelTransferScope;
this->Modified();
}
void mitk::SegWithPreviewTool::SetLabelTransferMode(LabelTransferMode labelTransferMode)
{
m_LabelTransferMode = labelTransferMode;
this->Modified();
}
void mitk::SegWithPreviewTool::SetSelectedLabels(const SelectedLabelVectorType& labelsToTransfer)
{
m_SelectedLabels = labelsToTransfer;
this->Modified();
}
bool mitk::SegWithPreviewTool::CanHandle(const BaseData* referenceData, const BaseData* workingData) const
{
if (!Superclass::CanHandle(referenceData, workingData))
return false;
if (workingData == nullptr)
return false;
auto* referenceImage = dynamic_cast<const Image*>(referenceData);
if (referenceImage == nullptr)
return false;
auto* labelSet = dynamic_cast<const LabelSetImage*>(workingData);
if (labelSet != nullptr)
return true;
auto* workingImage = dynamic_cast<const Image*>(workingData);
if (workingImage == nullptr)
return false;
// If the working image is a normal image and not a label set image
// it must have the same pixel type as a label set.
return MakeScalarPixelType< DefaultSegmentationDataType >() == workingImage->GetPixelType();
}
void mitk::SegWithPreviewTool::Activated()
{
Superclass::Activated();
this->GetToolManager()->RoiDataChanged +=
MessageDelegate<SegWithPreviewTool>(this, &SegWithPreviewTool::OnRoiDataChanged);
this->GetToolManager()->SelectedTimePointChanged +=
MessageDelegate<SegWithPreviewTool>(this, &SegWithPreviewTool::OnTimePointChanged);
m_ReferenceDataNode = this->GetToolManager()->GetReferenceData(0);
m_SegmentationInputNode = m_ReferenceDataNode;
m_LastTimePointOfUpdate = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
if (m_PreviewSegmentationNode.IsNull())
{
m_PreviewSegmentationNode = DataNode::New();
m_PreviewSegmentationNode->SetProperty("color", ColorProperty::New(0.0, 1.0, 0.0));
m_PreviewSegmentationNode->SetProperty("name", StringProperty::New(std::string(this->GetName())+" preview"));
m_PreviewSegmentationNode->SetProperty("opacity", FloatProperty::New(0.3));
m_PreviewSegmentationNode->SetProperty("binary", BoolProperty::New(true));
m_PreviewSegmentationNode->SetProperty("helper object", BoolProperty::New(true));
}
if (m_SegmentationInputNode.IsNotNull())
{
this->ResetPreviewNode();
this->InitiateToolByInput();
}
else
{
this->GetToolManager()->ActivateTool(-1);
}
}
void mitk::SegWithPreviewTool::Deactivated()
{
this->GetToolManager()->RoiDataChanged -=
MessageDelegate<SegWithPreviewTool>(this, &SegWithPreviewTool::OnRoiDataChanged);
this->GetToolManager()->SelectedTimePointChanged -=
MessageDelegate<SegWithPreviewTool>(this, &SegWithPreviewTool::OnTimePointChanged);
m_SegmentationInputNode = nullptr;
m_ReferenceDataNode = nullptr;
m_WorkingPlaneGeometry = nullptr;
try
{
if (DataStorage *storage = this->GetToolManager()->GetDataStorage())
{
storage->Remove(m_PreviewSegmentationNode);
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
catch (...)
{
// don't care
}
if (m_PreviewSegmentationNode.IsNotNull())
{
m_PreviewSegmentationNode->SetData(nullptr);
}
Superclass::Deactivated();
}
void mitk::SegWithPreviewTool::ConfirmSegmentation()
{
bool labelChanged = this->EnsureUpToDateUserDefinedActiveLabel();
if ((m_LazyDynamicPreviews && m_CreateAllTimeSteps) || labelChanged)
{ // The tool should create all time steps but is currently in lazy mode,
// thus ensure that a preview for all time steps is available.
this->UpdatePreview(true);
}
CreateResultSegmentationFromPreview();
RenderingManager::GetInstance()->RequestUpdateAll();
if (!m_KeepActiveAfterAccept)
{
this->GetToolManager()->ActivateTool(-1);
}
}
void mitk::SegWithPreviewTool::InitiateToolByInput()
{
//default implementation does nothing.
//implement in derived classes to change behavior
}
mitk::LabelSetImage* mitk::SegWithPreviewTool::GetPreviewSegmentation()
{
if (m_PreviewSegmentationNode.IsNull())
{
return nullptr;
}
return dynamic_cast<LabelSetImage*>(m_PreviewSegmentationNode->GetData());
}
const mitk::LabelSetImage* mitk::SegWithPreviewTool::GetPreviewSegmentation() const
{
if (m_PreviewSegmentationNode.IsNull())
{
return nullptr;
}
return dynamic_cast<LabelSetImage*>(m_PreviewSegmentationNode->GetData());
}
mitk::DataNode* mitk::SegWithPreviewTool::GetPreviewSegmentationNode()
{
return m_PreviewSegmentationNode;
}
const mitk::Image* mitk::SegWithPreviewTool::GetSegmentationInput() const
{
if (m_SegmentationInputNode.IsNull())
{
return nullptr;
}
return dynamic_cast<const Image*>(m_SegmentationInputNode->GetData());
}
const mitk::Image* mitk::SegWithPreviewTool::GetReferenceData() const
{
if (m_ReferenceDataNode.IsNull())
{
return nullptr;
}
return dynamic_cast<const Image*>(m_ReferenceDataNode->GetData());
}
template <typename ImageType>
void ClearBufferProcessing(ImageType* itkImage)
{
itkImage->FillBuffer(0);
}
void mitk::SegWithPreviewTool::ResetPreviewContentAtTimeStep(unsigned int timeStep)
{
auto previewImage = GetImageByTimeStep(this->GetPreviewSegmentation(), timeStep);
if (nullptr != previewImage)
{
AccessByItk(previewImage, ClearBufferProcessing);
}
}
void mitk::SegWithPreviewTool::ResetPreviewContent()
{
auto previewImage = this->GetPreviewSegmentation();
if (nullptr != previewImage)
{
auto castedPreviewImage =
dynamic_cast<LabelSetImage*>(previewImage);
if (nullptr == castedPreviewImage) mitkThrow() << "Application is on wrong state / invalid tool implementation. Preview image should always be of type LabelSetImage now.";
castedPreviewImage->ClearBuffer();
}
}
void mitk::SegWithPreviewTool::ResetPreviewNode()
{
if (m_IsUpdating)
{
mitkThrow() << "Used tool is implemented incorrectly. ResetPreviewNode is called while preview update is ongoing. Check implementation!";
}
itk::RGBPixel<float> previewColor;
previewColor[0] = 0.0f;
previewColor[1] = 1.0f;
previewColor[2] = 0.0f;
const auto image = this->GetSegmentationInput();
if (nullptr != image)
{
LabelSetImage::ConstPointer workingImage =
dynamic_cast<const LabelSetImage *>(this->GetToolManager()->GetWorkingData(0)->GetData());
if (workingImage.IsNotNull())
{
auto newPreviewImage = workingImage->Clone();
if (this->GetResetsToEmptyPreview())
{
newPreviewImage->ClearBuffer();
}
if (newPreviewImage.IsNull())
{
MITK_ERROR << "Cannot create preview helper objects. Unable to clone working image";
return;
}
m_PreviewSegmentationNode->SetData(newPreviewImage);
- auto* activeLayer = newPreviewImage->GetActiveLabelSet();
- auto* activeLabel = activeLayer->GetActiveLabel();
- if (m_UseSpecialPreviewColor)
+ auto* activeLabelSet = newPreviewImage->GetActiveLabelSet();
+ if (nullptr == activeLabelSet)
+ {
+ newPreviewImage->AddLayer();
+ activeLabelSet = newPreviewImage->GetActiveLabelSet();
+ }
+
+ auto* activeLabel = activeLabelSet->GetActiveLabel();
+ if (nullptr == activeLabel)
+ {
+ activeLabel = activeLabelSet->AddLabel("toolresult", previewColor);
+ activeLabelSet = newPreviewImage->GetActiveLabelSet();
+ activeLabelSet->UpdateLookupTable(activeLabel->GetValue());
+ }
+ else if (m_UseSpecialPreviewColor)
{
// Let's paint the feedback node green...
activeLabel->SetColor(previewColor);
- activeLayer->UpdateLookupTable(activeLabel->GetValue());
+ activeLabelSet->UpdateLookupTable(activeLabel->GetValue());
}
activeLabel->SetVisible(true);
}
else
{
Image::ConstPointer workingImageBin = dynamic_cast<const Image*>(this->GetToolManager()->GetWorkingData(0)->GetData());
if (workingImageBin.IsNotNull())
{
Image::Pointer newPreviewImage;
if (this->GetResetsToEmptyPreview())
{
newPreviewImage = Image::New();
newPreviewImage->Initialize(workingImageBin);
}
else
{
auto newPreviewImage = workingImageBin->Clone();
}
if (newPreviewImage.IsNull())
{
MITK_ERROR << "Cannot create preview helper objects. Unable to clone working image";
return;
}
m_PreviewSegmentationNode->SetData(newPreviewImage);
}
else
{
mitkThrow() << "Tool is an invalid state. Cannot setup preview node. Working data is an unsupported class and should have not been accepted by CanHandle().";
}
}
m_PreviewSegmentationNode->SetColor(previewColor);
m_PreviewSegmentationNode->SetOpacity(0.5);
int layer(50);
m_ReferenceDataNode->GetIntProperty("layer", layer);
m_PreviewSegmentationNode->SetIntProperty("layer", layer + 1);
if (DataStorage *ds = this->GetToolManager()->GetDataStorage())
{
if (!ds->Exists(m_PreviewSegmentationNode))
ds->Add(m_PreviewSegmentationNode, m_ReferenceDataNode);
}
}
}
mitk::SegWithPreviewTool::LabelMappingType mitk::SegWithPreviewTool::GetLabelMapping() const
{
LabelSetImage::LabelValueType offset = 0;
if (LabelTransferMode::AddLabel == m_LabelTransferMode && LabelTransferScope::ActiveLabel!=m_LabelTransferScope)
{
//If we are not just working on active label and transfer mode is add, we need to compute an offset for adding the
//preview labels instat of just mapping them to existing segmentation labels.
const auto segmentation = this->GetTargetSegmentation();
if (nullptr == segmentation)
mitkThrow() << "Invalid state of SegWithPreviewTool. Cannot GetLabelMapping if no target segmentation is set.";
auto labels = segmentation->GetLabels();
auto maxLabelIter = std::max_element(std::begin(labels), std::end(labels), [](const Label::Pointer& a, const Label::Pointer& b) {
return a->GetValue() < b->GetValue();
});
if (maxLabelIter != labels.end())
{
offset = maxLabelIter->GetPointer()->GetValue();
}
}
- LabelMappingType labelMapping = { { this->GetUserDefinedActiveLabel(),this->GetUserDefinedActiveLabel() } };
+ LabelMappingType labelMapping = {};
- if (LabelTransferScope::SelectedLabels == this->m_LabelTransferScope)
- {
- labelMapping.clear();
- for (auto label : this->m_SelectedLabels)
- {
- labelMapping.push_back({ label, label+offset });
- }
- }
- else if (LabelTransferScope::AllLabels == this->m_LabelTransferScope)
+ switch (this->m_LabelTransferScope)
{
- labelMapping.clear();
- const auto labelSet = this->GetPreviewSegmentation()->GetActiveLabelSet();
- for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelSet->IteratorConstEnd(); ++labelIter)
- {
- labelMapping.push_back({ labelIter->second->GetValue(),labelIter->second->GetValue()+offset });
- }
+ case LabelTransferScope::SelectedLabels:
+ {
+ for (auto label : this->m_SelectedLabels)
+ {
+ labelMapping.push_back({label, label + offset});
+ }
+ }
+ break;
+ case LabelTransferScope::AllLabels:
+ {
+ const auto labelSet = this->GetPreviewSegmentation()->GetActiveLabelSet();
+ for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelSet->IteratorConstEnd(); ++labelIter)
+ {
+ labelMapping.push_back({labelIter->second->GetValue(), labelIter->second->GetValue() + offset});
+ }
+ }
+ break;
+ default:
+ {
+ if (m_SelectedLabels.empty())
+ mitkThrow() << "Failed to generate label transfer mapping. Tool is in an invalid state, as "
+ "LabelTransferScope==ActiveLabel but no label is indicated as selected label. Check "
+ "implementation of derived tool class.";
+ if (m_SelectedLabels.size() > 1)
+ mitkThrow() << "Failed to generate label transfer mapping. Tool is in an invalid state, as "
+ "LabelTransferScope==ActiveLabel but more then one selected label is indicated."
+ "Should be only one. Check implementation of derived tool class.";
+ labelMapping.push_back({m_SelectedLabels.front(), this->GetUserDefinedActiveLabel()});
+ }
+ break;
}
return labelMapping;
}
void mitk::SegWithPreviewTool::TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep, const LabelMappingType& labelMapping)
{
try
{
Image::ConstPointer sourceImageAtTimeStep = this->GetImageByTimeStep(sourceImage, timeStep);
if (sourceImageAtTimeStep->GetPixelType() != destinationImage->GetPixelType())
{
mitkThrow() << "Cannot transfer images. Tool is in an invalid state, source image and destination image do not have the same pixel type. "
<< "Source pixel type: " << sourceImage->GetPixelType().GetTypeAsString()
<< "; destination pixel type: " << destinationImage->GetPixelType().GetTypeAsString();
}
if (!Equal(*(sourceImage->GetGeometry(timeStep)), *(destinationImage->GetGeometry(timeStep)), NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, false))
{
mitkThrow() << "Cannot transfer images. Tool is in an invalid state, source image and destination image do not have the same geometry.";
}
if (nullptr != this->GetWorkingPlaneGeometry())
{
auto sourceSlice = SegTool2D::GetAffectedImageSliceAs2DImage(this->GetWorkingPlaneGeometry(), sourceImage, timeStep);
SegTool2D::WriteBackSegmentationResult(this->GetTargetSegmentationNode(), m_WorkingPlaneGeometry, sourceSlice, timeStep);
}
else
{ //take care of the full segmentation volume
auto sourceLSImage = dynamic_cast<const LabelSetImage*>(sourceImage);
auto destLSImage = dynamic_cast<LabelSetImage*>(destinationImage);
TransferLabelContentAtTimeStep(sourceLSImage, destLSImage, timeStep, labelMapping, m_MergeStyle, m_OverwriteStyle);
}
}
- catch (...)
+ catch (mitk::Exception& e)
{
- Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation.");
- throw;
+ Tool::ErrorMessage(e.GetDescription());
+ mitkReThrow(e);
}
}
void mitk::SegWithPreviewTool::CreateResultSegmentationFromPreview()
{
const auto segInput = this->GetSegmentationInput();
auto previewImage = this->GetPreviewSegmentation();
if (nullptr != segInput && nullptr != previewImage)
{
DataNode::Pointer resultSegmentationNode = GetTargetSegmentationNode();
if (resultSegmentationNode.IsNotNull())
{
- const auto timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+ const TimePointType timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
auto resultSegmentation = dynamic_cast<Image*>(resultSegmentationNode->GetData());
// REMARK: the following code in this scope assumes that previewImage and resultSegmentation
// are clones of the working referenceImage (segmentation provided to the tool). Therefore they have
// the same time geometry.
if (previewImage->GetTimeSteps() != resultSegmentation->GetTimeSteps())
{
mitkThrow() << "Cannot confirm/transfer segmentation. Internal tool state is invalid."
<< " Preview segmentation and segmentation result image have different time geometries.";
}
auto labelMapping = this->GetLabelMapping();
this->PreparePreviewToResultTransfer(labelMapping);
if (m_CreateAllTimeSteps)
{
for (unsigned int timeStep = 0; timeStep < previewImage->GetTimeSteps(); ++timeStep)
{
this->TransferImageAtTimeStep(previewImage, resultSegmentation, timeStep, labelMapping);
}
}
else
{
const auto timeStep = resultSegmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint);
this->TransferImageAtTimeStep(previewImage, resultSegmentation, timeStep, labelMapping);
}
// since we are maybe working on a smaller referenceImage, pad it to the size of the original referenceImage
if (m_ReferenceDataNode.GetPointer() != m_SegmentationInputNode.GetPointer())
{
PadImageFilter::Pointer padFilter = PadImageFilter::New();
padFilter->SetInput(0, resultSegmentation);
padFilter->SetInput(1, dynamic_cast<Image*>(m_ReferenceDataNode->GetData()));
padFilter->SetBinaryFilter(true);
padFilter->SetUpperThreshold(1);
padFilter->SetLowerThreshold(1);
padFilter->Update();
resultSegmentationNode->SetData(padFilter->GetOutput());
}
this->EnsureTargetSegmentationNodeInDataStorage();
}
}
}
void mitk::SegWithPreviewTool::OnRoiDataChanged()
{
DataNode::ConstPointer node = this->GetToolManager()->GetRoiData(0);
if (node.IsNotNull())
{
MaskAndCutRoiImageFilter::Pointer roiFilter = MaskAndCutRoiImageFilter::New();
Image::Pointer image = dynamic_cast<Image *>(m_SegmentationInputNode->GetData());
if (image.IsNull())
return;
roiFilter->SetInput(image);
roiFilter->SetRegionOfInterest(node->GetData());
roiFilter->Update();
DataNode::Pointer tmpNode = DataNode::New();
tmpNode->SetData(roiFilter->GetOutput());
m_SegmentationInputNode = tmpNode;
}
else
m_SegmentationInputNode = m_ReferenceDataNode;
this->ResetPreviewNode();
this->InitiateToolByInput();
this->UpdatePreview();
}
void mitk::SegWithPreviewTool::OnTimePointChanged()
{
if (m_IsTimePointChangeAware && m_PreviewSegmentationNode.IsNotNull() && m_SegmentationInputNode.IsNotNull())
{
- const auto timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+ const TimePointType timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
const bool isStaticSegOnDynamicImage = m_PreviewSegmentationNode->GetData()->GetTimeSteps() == 1 && m_SegmentationInputNode->GetData()->GetTimeSteps() > 1;
if (timePoint!=m_LastTimePointOfUpdate && (isStaticSegOnDynamicImage || m_LazyDynamicPreviews))
{ //we only need to update either because we are lazzy
//or because we have a static segmentation with a dynamic referenceImage
this->UpdatePreview();
}
}
}
bool mitk::SegWithPreviewTool::EnsureUpToDateUserDefinedActiveLabel()
{
bool labelChanged = true;
const auto workingImage = dynamic_cast<const Image*>(this->GetToolManager()->GetWorkingData(0)->GetData());
if (const auto& labelSetImage = dynamic_cast<const LabelSetImage*>(workingImage))
{
// this is a fix for T28131 / T28986, which should be refactored if T28524 is being worked on
auto newLabel = labelSetImage->GetActiveLabel(labelSetImage->GetActiveLayer())->GetValue();
labelChanged = newLabel != m_UserDefinedActiveLabel;
m_UserDefinedActiveLabel = newLabel;
}
else
{
m_UserDefinedActiveLabel = 1;
labelChanged = false;
}
return labelChanged;
}
void mitk::SegWithPreviewTool::UpdatePreview(bool ignoreLazyPreviewSetting)
{
const auto inputImage = this->GetSegmentationInput();
auto previewImage = this->GetPreviewSegmentation();
int progress_steps = 200;
const auto workingImage = dynamic_cast<const Image*>(this->GetToolManager()->GetWorkingData(0)->GetData());
this->EnsureUpToDateUserDefinedActiveLabel();
this->CurrentlyBusy.Send(true);
m_IsUpdating = true;
this->UpdatePrepare();
- const auto timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+ const TimePointType timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
try
{
if (nullptr != inputImage && nullptr != previewImage)
{
m_ProgressCommand->AddStepsToDo(progress_steps);
if (previewImage->GetTimeSteps() > 1 && (ignoreLazyPreviewSetting || !m_LazyDynamicPreviews))
{
for (unsigned int timeStep = 0; timeStep < previewImage->GetTimeSteps(); ++timeStep)
{
Image::ConstPointer feedBackImage;
Image::ConstPointer currentSegImage;
auto previewTimePoint = previewImage->GetTimeGeometry()->TimeStepToTimePoint(timeStep);
auto inputTimeStep = inputImage->GetTimeGeometry()->TimePointToTimeStep(previewTimePoint);
if (nullptr != this->GetWorkingPlaneGeometry())
{ //only extract a specific slice defined by the working plane as feedback referenceImage.
feedBackImage = SegTool2D::GetAffectedImageSliceAs2DImage(this->GetWorkingPlaneGeometry(), inputImage, inputTimeStep);
currentSegImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), workingImage, previewTimePoint);
}
else
{ //work on the whole feedback referenceImage
feedBackImage = this->GetImageByTimeStep(inputImage, inputTimeStep);
currentSegImage = this->GetImageByTimePoint(workingImage, previewTimePoint);
}
this->DoUpdatePreview(feedBackImage, currentSegImage, previewImage, timeStep);
}
}
else
{
Image::ConstPointer feedBackImage;
Image::ConstPointer currentSegImage;
if (nullptr != this->GetWorkingPlaneGeometry())
{
feedBackImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), inputImage, timePoint);
currentSegImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), workingImage, timePoint);
}
else
{
feedBackImage = this->GetImageByTimePoint(inputImage, timePoint);
currentSegImage = this->GetImageByTimePoint(workingImage, timePoint);
}
auto timeStep = previewImage->GetTimeGeometry()->TimePointToTimeStep(timePoint);
this->DoUpdatePreview(feedBackImage, currentSegImage, previewImage, timeStep);
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
catch (itk::ExceptionObject & excep)
{
MITK_ERROR << "Exception caught: " << excep.GetDescription();
m_ProgressCommand->SetProgress(progress_steps);
std::string msg = excep.GetDescription();
ErrorMessage.Send(msg);
}
catch (...)
{
m_ProgressCommand->SetProgress(progress_steps);
m_IsUpdating = false;
CurrentlyBusy.Send(false);
throw;
}
this->UpdateCleanUp();
m_LastTimePointOfUpdate = timePoint;
m_ProgressCommand->SetProgress(progress_steps);
m_IsUpdating = false;
CurrentlyBusy.Send(false);
}
bool mitk::SegWithPreviewTool::IsUpdating() const
{
return m_IsUpdating;
}
void mitk::SegWithPreviewTool::UpdatePrepare()
{
// default implementation does nothing
//reimplement in derived classes for special behavior
}
void mitk::SegWithPreviewTool::UpdateCleanUp()
{
// default implementation does nothing
//reimplement in derived classes for special behavior
}
void mitk::SegWithPreviewTool::TransferLabelInformation(const LabelMappingType& labelMapping,
const mitk::LabelSetImage* source, mitk::LabelSetImage* target)
{
for (const auto& [sourceLabel, targetLabel] : labelMapping)
{
if (LabelSetImage::UnlabeledValue != sourceLabel &&
LabelSetImage::UnlabeledValue != targetLabel &&
!target->ExistLabel(targetLabel, target->GetActiveLayer()))
{
if (!source->ExistLabel(sourceLabel, source->GetActiveLayer()))
{
mitkThrow() << "Cannot prepare segmentation for preview transfer. Preview seems invalid as label is missing. Missing label: " << sourceLabel;
}
auto clonedLabel = source->GetLabel(sourceLabel)->Clone();
clonedLabel->SetValue(targetLabel);
target->GetActiveLabelSet()->AddLabel(clonedLabel);
}
}
}
void mitk::SegWithPreviewTool::PreparePreviewToResultTransfer(const LabelMappingType& labelMapping)
{
DataNode::Pointer resultSegmentationNode = GetTargetSegmentationNode();
if (resultSegmentationNode.IsNotNull())
{
auto resultSegmentation = dynamic_cast<LabelSetImage*>(resultSegmentationNode->GetData());
if (nullptr == resultSegmentation)
{
mitkThrow() << "Cannot prepare segmentation for preview transfer. Tool is in invalid state as segmentation is not existing or of right type";
}
auto preview = this->GetPreviewSegmentation();
TransferLabelInformation(labelMapping, preview, resultSegmentation);
}
}
mitk::TimePointType mitk::SegWithPreviewTool::GetLastTimePointOfUpdate() const
{
return m_LastTimePointOfUpdate;
}
+mitk::LabelSetImage::LabelValueType mitk::SegWithPreviewTool::GetActiveLabelValueOfPreview() const
+{
+ const auto previewImage = this->GetPreviewSegmentation();
+ const auto activeLabel = previewImage->GetActiveLabel(previewImage->GetActiveLayer());
+ if (nullptr == activeLabel)
+ mitkThrow() << this->GetNameOfClass() <<" is in an invalid state, as "
+ "preview has no active label indicated. Check "
+ "implementation of the class.";
+
+ return activeLabel->GetValue();
+}
+
const char* mitk::SegWithPreviewTool::GetGroup() const
{
return "autoSegmentation";
}
mitk::Image::ConstPointer mitk::SegWithPreviewTool::GetImageByTimeStep(const mitk::Image* image, TimeStepType timestep)
{
return SelectImageByTimeStep(image, timestep);
}
mitk::Image::Pointer mitk::SegWithPreviewTool::GetImageByTimeStep(mitk::Image* image, TimeStepType timestep)
{
return SelectImageByTimeStep(image, timestep);
}
mitk::Image::ConstPointer mitk::SegWithPreviewTool::GetImageByTimePoint(const mitk::Image* image, TimePointType timePoint)
{
return SelectImageByTimePoint(image, timePoint);
}
void mitk::SegWithPreviewTool::EnsureTargetSegmentationNodeInDataStorage() const
{
auto targetNode = this->GetTargetSegmentationNode();
auto dataStorage = this->GetToolManager()->GetDataStorage();
if (!dataStorage->Exists(targetNode))
{
dataStorage->Add(targetNode, this->GetToolManager()->GetReferenceData(0));
}
}
std::string mitk::SegWithPreviewTool::GetCurrentSegmentationName()
{
auto workingData = this->GetToolManager()->GetWorkingData(0);
return nullptr != workingData
? workingData->GetName()
: "";
}
mitk::DataNode* mitk::SegWithPreviewTool::GetTargetSegmentationNode() const
{
return this->GetToolManager()->GetWorkingData(0);
}
mitk::LabelSetImage* mitk::SegWithPreviewTool::GetTargetSegmentation() const
{
auto node = this->GetTargetSegmentationNode();
if (nullptr == node)
return nullptr;
return dynamic_cast<LabelSetImage*>(node->GetData());
}
void mitk::SegWithPreviewTool::TransferLabelSetImageContent(const LabelSetImage* source, LabelSetImage* target, TimeStepType timeStep)
{
mitk::ImageReadAccessor newMitkImgAcc(source);
LabelMappingType labelMapping;
const auto labelSet = source->GetActiveLabelSet();
for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelSet->IteratorConstEnd(); ++labelIter)
{
labelMapping.push_back({ labelIter->second->GetValue(),labelIter->second->GetValue() });
}
TransferLabelInformation(labelMapping, source, target);
target->SetVolume(newMitkImgAcc.GetData(), timeStep);
}
diff --git a/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.h b/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.h
index 3369d6be4d..a4141de0b1 100644
--- a/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.h
+++ b/Modules/Segmentation/Interactions/mitkSegWithPreviewTool.h
@@ -1,314 +1,321 @@
/*============================================================================
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 mitkSegWithPreviewTool_h
#define mitkSegWithPreviewTool_h
#include "mitkTool.h"
#include "mitkCommon.h"
#include "mitkDataNode.h"
#include "mitkToolCommand.h"
#include <MitkSegmentationExports.h>
namespace mitk
{
/**
\brief Base class for any auto segmentation tool that provides a preview of the new segmentation.
This tool class implements a lot basic logic to handle auto segmentation tools with preview,
Time point and ROI support. Derived classes will ask to update the segmentation preview if needed
(e.g. because the ROI or the current time point has changed) or because derived tools
indicated the need to update themselves.
This class also takes care to properly transfer a confirmed preview into the segementation
result.
\ingroup ToolManagerEtAl
\sa mitk::Tool
\sa QmitkInteractiveSegmentation
*/
class MITKSEGMENTATION_EXPORT SegWithPreviewTool : public Tool
{
public:
mitkClassMacro(SegWithPreviewTool, Tool);
void Activated() override;
void Deactivated() override;
void ConfirmSegmentation();
itkSetMacro(CreateAllTimeSteps, bool);
itkGetMacro(CreateAllTimeSteps, bool);
itkBooleanMacro(CreateAllTimeSteps);
itkSetMacro(KeepActiveAfterAccept, bool);
itkGetMacro(KeepActiveAfterAccept, bool);
itkBooleanMacro(KeepActiveAfterAccept);
itkSetMacro(IsTimePointChangeAware, bool);
itkGetMacro(IsTimePointChangeAware, bool);
itkBooleanMacro(IsTimePointChangeAware);
itkSetMacro(ResetsToEmptyPreview, bool);
itkGetMacro(ResetsToEmptyPreview, bool);
itkBooleanMacro(ResetsToEmptyPreview);
itkSetMacro(UseSpecialPreviewColor, bool);
itkGetMacro(UseSpecialPreviewColor, bool);
itkBooleanMacro(UseSpecialPreviewColor);
/*itk macro was not used on purpose, to aviod the change of mtime.*/
void SetMergeStyle(MultiLabelSegmentation::MergeStyle mergeStyle);
itkGetMacro(MergeStyle, MultiLabelSegmentation::MergeStyle);
/*itk macro was not used on purpose, to aviod the change of mtime.*/
void SetOverwriteStyle(MultiLabelSegmentation::OverwriteStyle overwriteStyle);
itkGetMacro(OverwriteStyle, MultiLabelSegmentation::OverwriteStyle);
enum class LabelTransferScope
{
- ActiveLabel, //Only the active label will be transfered from preview to segmentation.
+ ActiveLabel, //Only the selected label will be transfered from the preview segmentation
+ //to the result segmentation.
+ //If this mode is selected the class expects that GetSelectedLabels indicate
+ //the label in the preview.
SelectedLabels, //The labels defined as selected labels will be transfered.
AllLabels //Transfer all labels of the preview
};
/*itk macro was not used on purpose, to aviod the change of mtime.*/
void SetLabelTransferScope(LabelTransferScope labelTransferScope);
itkGetMacro(LabelTransferScope, LabelTransferScope);
using SelectedLabelVectorType = std::vector<Label::PixelType>;
/** Specifies the labels that should be transfered form preview to the working image,
- if the segmentation is confirmed. The setting will be used, if LabelTransferScope is set to "SelectedLabels".
- The selected label IDs corespond to the labels of the preview image.*/
+ if the segmentation is confirmed. The setting will be used, if LabelTransferScope is set to "ActiveLabel"
+ or "SelectedLabels".
+ @remark If the LabelTransferScope=="ActiveLabel", the class expects only one label to be selected.
+ @remark The selected label IDs corespond to the labels of the preview image.*/
void SetSelectedLabels(const SelectedLabelVectorType& labelsToTransfer);
itkGetMacro(SelectedLabels, SelectedLabelVectorType);
enum class LabelTransferMode
{
MapLabel, //Only the active label will be transfered from preview to segmentation.
AddLabel //The labels defined as selected labels will be transfered.
};
/*itk macro was not used on purpose, to aviod the change of mtime.*/
void SetLabelTransferMode(LabelTransferMode labelTransferMode);
itkGetMacro(LabelTransferMode, LabelTransferMode);
bool CanHandle(const BaseData* referenceData, const BaseData* workingData) const override;
/** Triggers the actualization of the preview
* @param ignoreLazyPreviewSetting If set true UpdatePreview will always
* generate the preview for all time steps. If set to false, UpdatePreview
* will regard the setting specified by the constructor.
* To define the update generation for time steps implement DoUpdatePreview.
* To alter what should be done directly before or after the update of the preview,
* reimplement UpdatePrepare() or UpdateCleanUp().*/
void UpdatePreview(bool ignoreLazyPreviewSetting = false);
/** Indicate if currently UpdatePreview is triggered (true) or not (false).*/
bool IsUpdating() const;
/**
* @brief Gets the name of the currently selected segmentation node
* @return the name of the segmentation node or an empty string if
* none is selected
*/
std::string GetCurrentSegmentationName();
/**
* @brief Returns the currently selected segmentation node
* @return a mitk::DataNode which contains a segmentation image
*/
virtual DataNode* GetTargetSegmentationNode() const;
LabelSetImage* GetTargetSegmentation() const;
/** Returns the image that contains the preview of the current segmentation.
* Returns null if the node is not set or does not contain an image.*/
LabelSetImage* GetPreviewSegmentation();
const LabelSetImage* GetPreviewSegmentation() const;
DataNode* GetPreviewSegmentationNode();
protected:
ToolCommand::Pointer m_ProgressCommand;
SegWithPreviewTool(bool lazyDynamicPreviews = false); // purposely hidden
SegWithPreviewTool(bool lazyDynamicPreviews, const char* interactorType, const us::Module* interactorModule = nullptr); // purposely hidden
~SegWithPreviewTool() override;
const char* GetGroup() const override;
/** Helper that extracts the image for the passed timestep, if the image has multiple time steps.*/
static Image::ConstPointer GetImageByTimeStep(const Image* image, TimeStepType timestep);
/** Helper that extracts the image for the passed timestep, if the image has multiple time steps.*/
static Image::Pointer GetImageByTimeStep(Image* image, TimeStepType timestep);
/** Helper that extracts the image for the passed time point, if the image has multiple time steps.*/
static Image::ConstPointer GetImageByTimePoint(const Image* image, TimePointType timePoint);
void EnsureTargetSegmentationNodeInDataStorage() const;
/** Member is always called if GetSegmentationInput() has changed
* (e.g. because a new ROI was defined, or on activation) to give derived
* classes the posibility to initiate their state accordingly.
* Reimplement this function to implement special behavior.
*/
virtual void InitiateToolByInput();
/** This member function offers derived classes the possibility to alter what should
happen directly before the update of the preview is performed. It is called by
UpdatePreview. Default implementation does nothing.*/
virtual void UpdatePrepare();
/** This member function offers derived classes the possibility to alter what should
happen directly after the update of the preview is performed. It is called by
UpdatePreview. Default implementation does nothing.*/
virtual void UpdateCleanUp();
using LabelMappingType = std::vector<std::pair<Label::PixelType, Label::PixelType> >;
/** This member function offers derived classes the possibility to alter what should
happen directly before the content of the preview is transfered to the segmentation,
when the segmentation is confirmed. It is called by CreateResultSegmentationFromPreview.
Default implementation ensure that all labels that will be transfered, exist in the
segmentation. If they are not existing before the transfer, the will be added by
cloning the label information of the preview.
@param labelMapping the mapping that should be used for transfering the labels.
*/
virtual void PreparePreviewToResultTransfer(const LabelMappingType& labelMapping);
static void TransferLabelInformation(const LabelMappingType& labelMapping,
const mitk::LabelSetImage* source, mitk::LabelSetImage* target);
/**Helper function that can be used to move the content of an LabelSetImage (the pixels of the active source layer and the labels).
This is e.g. helpfull if you generate an LabelSetImage content in DoUpdatePreview and you want to transfer it into the preview image.*/
static void TransferLabelSetImageContent(const LabelSetImage* source, LabelSetImage* target, TimeStepType timeStep);
/** This function does the real work. Here the preview for a given
* input image should be computed and stored in the also passed
* preview image at the passed time step.
* It also provides the current/old segmentation at the time point,
* which can be used, if the preview depends on the the segmenation so far.
*/
virtual void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep) = 0;
/** Returns the input that should be used for any segmentation/preview or tool update.
* It is either the data of ReferenceDataNode itself or a part of it defined by a ROI mask
* provided by the tool manager. Derived classes should regard this as the relevant
* input data for any processing.
* Returns null if the node is not set or does not contain an image.*/
const Image* GetSegmentationInput() const;
/** Returns the image that is provided by the ReferenceDataNode.
* Returns null if the node is not set or does not contain an image.*/
const Image* GetReferenceData() const;
/** Resets the preview node so it is empty and ready to be filled by the tool
@remark Calling this function will generate a new preview image, and the old
might be invalidated. Therefore this function should not be used within the
scope of UpdatePreview (m_IsUpdating == true).*/
void ResetPreviewNode();
/** Resets the complete content of the preview image. The instance of the preview image and its settings
* stay the same.*/
void ResetPreviewContent();
/** Resets only the image content of the specified timeStep of the preview image. If the preview image or the specified
time step does not exist, nothing happens.*/
void ResetPreviewContentAtTimeStep(unsigned int timeStep);
TimePointType GetLastTimePointOfUpdate() const;
+ LabelSetImage::LabelValueType GetActiveLabelValueOfPreview() const;
+
itkGetConstMacro(UserDefinedActiveLabel, Label::PixelType);
itkSetObjectMacro(WorkingPlaneGeometry, PlaneGeometry);
itkGetConstObjectMacro(WorkingPlaneGeometry, PlaneGeometry);
private:
void TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep, const LabelMappingType& labelMapping);
void CreateResultSegmentationFromPreview();
void OnRoiDataChanged();
void OnTimePointChanged();
/**Internal helper that ensures that the stored active label is up to date.
This is a fix for T28131 / T28986. It should be refactored if T28524 is being worked on.
On the long run, the active label will be communicated/set by the user/toolmanager as a
state of the tool and the tool should react accordingly (like it does for other external
state changes).
@return indicates if the label has changed (true) or not.
*/
bool EnsureUpToDateUserDefinedActiveLabel();
/**Returns that label mapping between preview segmentation (first element of pair) and
result segmentation (second element of pair).
The content depends on the settings of LabelTransferMode and LabelTransferScope*/
LabelMappingType GetLabelMapping() const;
/** Node that containes the preview data generated and managed by this class or derived ones.*/
DataNode::Pointer m_PreviewSegmentationNode;
/** The reference data recieved from ToolManager::GetReferenceData when tool was activated.*/
DataNode::Pointer m_ReferenceDataNode;
/** Node that containes the data that should be used as input for any auto segmentation. It might
* be the same like m_ReferenceDataNode (if no ROI is set) or a sub region (if ROI is set).*/
DataNode::Pointer m_SegmentationInputNode;
/** Indicates if Accepting the threshold should transfer/create the segmentations
of all time steps (true) or only of the currently selected timepoint (false).*/
bool m_CreateAllTimeSteps = false;
/** Indicates if the tool should kept active after accepting the segmentation or not.*/
bool m_KeepActiveAfterAccept = false;
/** Relevant if the working data / preview image has multiple time steps (dynamic segmentations).
* This flag has to be set by derived classes accordingly to there way to generate dynamic previews.
* If LazyDynamicPreview is true, the tool generates only the preview for the current time step.
* Therefore it always has to update the preview if current time point has changed and it has to (re)compute
* all timeframes if ConfirmSegmentation() is called.*/
bool m_LazyDynamicPreviews = false;
bool m_IsTimePointChangeAware = true;
/** Controls if ResetPreviewNode generates an empty content (true) or clones the current
segmentation (false).*/
bool m_ResetsToEmptyPreview = false;
/** Controls if for the preview of the active label a special preview color is used.
* If set to false, coloring will stay in the preview like it is in the working image.*/
bool m_UseSpecialPreviewColor = true;
TimePointType m_LastTimePointOfUpdate = 0.;
bool m_IsUpdating = false;
Label::PixelType m_UserDefinedActiveLabel = 1;
/** This variable indicates if for the tool a working plane geometry is defined.
* If a working plane is defined the tool will only work an the slice of the input
* and the segmentation. Thus only the relevant input slice will be passed to
* DoUpdatePreview(...) and only the relevant slice of the preview will be transfered when
* ConfirmSegmentation() is called.*/
PlaneGeometry::Pointer m_WorkingPlaneGeometry;
/** This variable controles how the label pixel content of the preview should be transfered into the
segmentation- For more details of the behavior see documentation of MultiLabelSegmentation::MergeStyle. */
MultiLabelSegmentation::MergeStyle m_MergeStyle = MultiLabelSegmentation::MergeStyle::Replace;
/** This variable controles how the label pixel content of the preview should be transfered into the
segmentation- For more details of the behavior see documentation of MultiLabelSegmentation::OverwriteStyle. */
MultiLabelSegmentation::OverwriteStyle m_OverwriteStyle = MultiLabelSegmentation::OverwriteStyle::RegardLocks;
LabelTransferScope m_LabelTransferScope = LabelTransferScope::ActiveLabel;
SelectedLabelVectorType m_SelectedLabels = {};
LabelTransferMode m_LabelTransferMode = LabelTransferMode::MapLabel;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.cpp b/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.cpp
index 908f933b7e..4fd38ddb56 100644
--- a/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkTotalSegmentatorTool.cpp
@@ -1,369 +1,374 @@
/*============================================================================
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.
============================================================================*/
// MITK
#include "mitkTotalSegmentatorTool.h"
#include <mitkIOUtil.h>
#include <mitkImageReadAccessor.h>
#include <algorithm>
#include <filesystem>
#include <itksys/SystemTools.hxx>
+#include <regex>
// us
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <usModuleResource.h>
#include <usServiceReference.h>
namespace mitk
{
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, TotalSegmentatorTool, "Total Segmentator");
}
mitk::TotalSegmentatorTool::~TotalSegmentatorTool()
{
std::filesystem::remove_all(this->GetMitkTempDir());
}
mitk::TotalSegmentatorTool::TotalSegmentatorTool() : SegWithPreviewTool(true) // prevents auto-compute across all timesteps
{
this->IsTimePointChangeAwareOff();
}
void mitk::TotalSegmentatorTool::Activated()
{
Superclass::Activated();
this->SetLabelTransferScope(LabelTransferScope::AllLabels);
this->SetLabelTransferMode(LabelTransferMode::AddLabel);
}
const char **mitk::TotalSegmentatorTool::GetXPM() const
{
return nullptr;
}
us::ModuleResource mitk::TotalSegmentatorTool::GetIconResource() const
{
us::Module *module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("AI.svg");
return resource;
}
const char *mitk::TotalSegmentatorTool::GetName() const
{
return "TotalSegmentator";
}
void mitk::TotalSegmentatorTool::onPythonProcessEvent(itk::Object * /*pCaller*/, const itk::EventObject &e, void *)
{
std::string testCOUT;
std::string testCERR;
const auto *pEvent = dynamic_cast<const mitk::ExternalProcessStdOutEvent *>(&e);
if (pEvent)
{
testCOUT = testCOUT + pEvent->GetOutput();
MITK_INFO << testCOUT;
}
const auto *pErrEvent = dynamic_cast<const mitk::ExternalProcessStdErrEvent *>(&e);
if (pErrEvent)
{
testCERR = testCERR + pErrEvent->GetOutput();
MITK_ERROR << testCERR;
}
}
void mitk::TotalSegmentatorTool::DoUpdatePreview(const Image *inputAtTimeStep,
const Image * /*oldSegAtTimeStep*/,
LabelSetImage *previewImage,
TimeStepType timeStep)
{
if (this->m_MitkTempDir.empty())
{
this->SetMitkTempDir(IOUtil::CreateTemporaryDirectory("mitk-XXXXXX"));
}
ProcessExecutor::Pointer spExec = ProcessExecutor::New();
itk::CStyleCommand::Pointer spCommand = itk::CStyleCommand::New();
spCommand->SetCallback(&onPythonProcessEvent);
spExec->AddObserver(ExternalProcessOutputEvent(), spCommand);
std::string inDir, outDir, inputImagePath, outputImagePath, scriptPath;
inDir = IOUtil::CreateTemporaryDirectory("totalseg-in-XXXXXX", this->GetMitkTempDir());
std::ofstream tmpStream;
inputImagePath = IOUtil::CreateTemporaryFile(tmpStream, TEMPLATE_FILENAME, inDir + IOUtil::GetDirectorySeparator());
tmpStream.close();
std::size_t found = inputImagePath.find_last_of(IOUtil::GetDirectorySeparator());
std::string fileName = inputImagePath.substr(found + 1);
std::string token = fileName.substr(0, fileName.find("_"));
outDir = IOUtil::CreateTemporaryDirectory("totalseg-out-XXXXXX", this->GetMitkTempDir());
LabelSetImage::Pointer outputBuffer;
IOUtil::Save(inputAtTimeStep, inputImagePath);
outputImagePath = outDir + IOUtil::GetDirectorySeparator() + token + "_000.nii.gz";
const bool isSubTask = (this->GetSubTask() != DEFAULT_TOTAL_TASK);
if (isSubTask)
{
outputImagePath = outDir;
}
this->run_totalsegmentator(
spExec, inputImagePath, outputImagePath, this->GetFast(), !isSubTask, this->GetGpuId(), DEFAULT_TOTAL_TASK);
if (isSubTask)
{ // Run total segmentator again
this->run_totalsegmentator(
spExec, inputImagePath, outputImagePath, !isSubTask, !isSubTask, this->GetGpuId(), this->GetSubTask());
// Construct Label Id map
std::vector<std::string> files = SUBTASKS_MAP.at(this->GetSubTask());
// Agglomerate individual mask files into one multi-label image.
std::for_each(files.begin(),
files.end(),
[&](std::string &fileName) { fileName = (outDir + IOUtil::GetDirectorySeparator() + fileName); });
outputBuffer = AgglomerateLabelFiles(files, inputAtTimeStep->GetDimensions(), inputAtTimeStep->GetGeometry());
}
else
{
Image::Pointer outputImage = IOUtil::Load<Image>(outputImagePath);
outputBuffer = mitk::LabelSetImage::New();
outputBuffer->InitializeByLabeledImage(outputImage);
outputBuffer->SetGeometry(inputAtTimeStep->GetGeometry());
}
mitk::ImageReadAccessor newMitkImgAcc(outputBuffer.GetPointer());
this->MapLabelsToSegmentation(outputBuffer, previewImage, m_LabelMapTotal);
previewImage->SetVolume(newMitkImgAcc.GetData(), timeStep);
}
void mitk::TotalSegmentatorTool::UpdatePrepare()
{
Superclass::UpdatePrepare();
auto preview = this->GetPreviewSegmentation();
- auto labelset = preview->GetLabelSet(preview->GetActiveLayer());
- labelset->RemoveAllLabels();
+ for (LabelSetImage::GroupIndexType i = 0; i < preview->GetNumberOfLayers(); ++i)
+ {
+ preview->GetLabelSet(i)->RemoveAllLabels();
+ }
if (m_LabelMapTotal.empty())
{
this->ParseLabelMapTotalDefault();
}
const bool isSubTask = (this->GetSubTask() != DEFAULT_TOTAL_TASK);
if (isSubTask)
{
std::vector<std::string> files = SUBTASKS_MAP.at(this->GetSubTask());
m_LabelMapTotal.clear();
mitk::Label::PixelType labelId = 1;
for (auto const &file : files)
{
std::string labelName = file.substr(0, file.find('.'));
m_LabelMapTotal[labelId] = labelName;
labelId++;
}
}
}
mitk::LabelSetImage::Pointer mitk::TotalSegmentatorTool::AgglomerateLabelFiles(std::vector<std::string> &filePaths,
const unsigned int *dimensions,
mitk::BaseGeometry *geometry)
{
Label::PixelType labelId = 1;
auto aggloLabelImage = mitk::LabelSetImage::New();
auto initImage = mitk::Image::New();
initImage->Initialize(mitk::MakeScalarPixelType<mitk::Label::PixelType>(), 3, dimensions);
aggloLabelImage->Initialize(initImage);
aggloLabelImage->SetGeometry(geometry);
mitk::LabelSet::Pointer newlayer = mitk::LabelSet::New();
newlayer->SetLayer(0);
aggloLabelImage->AddLayer(newlayer);
for (auto const &outputImagePath : filePaths)
{
double rgba[4];
aggloLabelImage->GetActiveLabelSet()->GetLookupTable()->GetTableValue(labelId, rgba);
mitk::Color color;
color.SetRed(rgba[0]);
color.SetGreen(rgba[1]);
color.SetBlue(rgba[2]);
auto label = mitk::Label::New();
label->SetName("object-" + std::to_string(labelId));
label->SetValue(labelId);
label->SetColor(color);
label->SetOpacity(rgba[3]);
aggloLabelImage->GetActiveLabelSet()->AddLabel(label);
Image::Pointer outputImage = IOUtil::Load<Image>(outputImagePath);
auto source = mitk::LabelSetImage::New();
source->InitializeByLabeledImage(outputImage);
source->SetGeometry(geometry);
auto labelSet = aggloLabelImage->GetActiveLabelSet();
mitk::TransferLabelContent(source, aggloLabelImage, labelSet, 0, 0, false, {{1, labelId}});
labelId++;
}
return aggloLabelImage;
}
void mitk::TotalSegmentatorTool::run_totalsegmentator(ProcessExecutor* spExec,
const std::string &inputImagePath,
const std::string &outputImagePath,
bool isFast,
bool isMultiLabel,
unsigned int gpuId,
const std::string &subTask)
{
ProcessExecutor::ArgumentListType args;
std::string command = "TotalSegmentator";
#if defined(__APPLE__) || defined(_WIN32)
command = "python";
#endif
args.clear();
#ifdef _WIN32
std::string ending = "Scripts";
if (0 == this->GetPythonPath().compare(this->GetPythonPath().length() - ending.length(), ending.length(), ending))
{
args.push_back("TotalSegmentator");
}
else
{
args.push_back("Scripts/TotalSegmentator");
}
#endif
#if defined(__APPLE__)
args.push_back("TotalSegmentator");
#endif
args.push_back("-i");
args.push_back(inputImagePath);
args.push_back("-o");
args.push_back(outputImagePath);
if (subTask != DEFAULT_TOTAL_TASK)
{
args.push_back("-ta");
args.push_back(subTask);
}
if (isMultiLabel)
{
args.push_back("--ml");
}
if (isFast)
{
args.push_back("--fast");
}
try
{
std::string cudaEnv = "CUDA_VISIBLE_DEVICES=" + std::to_string(gpuId);
itksys::SystemTools::PutEnv(cudaEnv.c_str());
std::stringstream logStream;
for (const auto &arg : args)
logStream << arg << " ";
logStream << this->GetPythonPath();
MITK_INFO << logStream.str();
spExec->Execute(this->GetPythonPath(), command, args);
}
catch (const mitk::Exception &e)
{
MITK_ERROR << e.GetDescription();
return;
}
}
void mitk::TotalSegmentatorTool::ParseLabelMapTotalDefault()
{
if (!this->GetLabelMapPath().empty())
{
+ std::regex sanitizer(R"([^A-Za-z0-9_])");
std::fstream newfile;
newfile.open(this->GetLabelMapPath(), ios::in);
std::stringstream buffer;
if (newfile.is_open())
{
int line = 0;
std::string temp;
while (std::getline(newfile, temp))
{
if (line > 1 && line < 106)
{
buffer << temp;
}
++line;
}
}
std::string key, val;
while (std::getline(std::getline(buffer, key, ':'), val, ','))
{
- m_LabelMapTotal[std::stoi(key)] = val;
+ std::string sanitized = std::regex_replace(val, sanitizer, "");
+ m_LabelMapTotal[std::stoi(key)] = sanitized;
}
}
}
void mitk::TotalSegmentatorTool::MapLabelsToSegmentation(const mitk::LabelSetImage* source,
mitk::LabelSetImage* dest,
std::map<mitk::Label::PixelType, std::string> &labelMap)
{
auto labelset = dest->GetLabelSet();
auto lookupTable = mitk::LookupTable::New();
lookupTable->SetType(mitk::LookupTable::LookupTableType::MULTILABEL);
for (auto const &[key, val] : labelMap)
{
if (source->ExistLabel(key, source->GetActiveLayer()))
{
Label::Pointer label = Label::New(key, val);
std::array<double, 3> lookupTableColor;
lookupTable->GetColor(key, lookupTableColor.data());
Color color;
color.SetRed(lookupTableColor[0]);
color.SetGreen(lookupTableColor[1]);
color.SetBlue(lookupTableColor[2]);
label->SetColor(color);
labelset->AddLabel(label, false);
}
}
}
std::string mitk::TotalSegmentatorTool::GetLabelMapPath()
{
std::string pythonFileName;
std::filesystem::path pathToLabelMap(this->GetPythonPath());
pathToLabelMap = pathToLabelMap.parent_path();
#ifdef _WIN32
pythonFileName = pathToLabelMap.string() + "/Lib/site-packages/totalsegmentator/map_to_binary.py";
#else
pathToLabelMap.append("lib");
for (auto const &dir_entry : std::filesystem::directory_iterator{pathToLabelMap})
{
if (dir_entry.is_directory())
{
auto dirName = dir_entry.path().filename().string();
if (dirName.rfind("python", 0) == 0)
{
pathToLabelMap.append(dir_entry.path().filename().string());
break;
}
}
}
pythonFileName = pathToLabelMap.string() + "/site-packages/totalsegmentator/map_to_binary.py";
#endif
return pythonFileName;
}
diff --git a/Modules/Segmentation/Interactions/mitknnUnetTool.cpp b/Modules/Segmentation/Interactions/mitknnUnetTool.cpp
index 49b6b589b3..d2e923b8e0 100644
--- a/Modules/Segmentation/Interactions/mitknnUnetTool.cpp
+++ b/Modules/Segmentation/Interactions/mitknnUnetTool.cpp
@@ -1,314 +1,323 @@
/*============================================================================
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 "mitknnUnetTool.h"
#include "mitkIOUtil.h"
#include "mitkProcessExecutor.h"
#include <itksys/SystemTools.hxx>
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <usModuleResource.h>
#include <filesystem>
namespace mitk
{
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, nnUNetTool, "nnUNet tool");
}
mitk::nnUNetTool::~nnUNetTool()
{
std::filesystem::remove_all(this->GetMitkTempDir());
}
void mitk::nnUNetTool::Activated()
{
Superclass::Activated();
this->SetLabelTransferScope(LabelTransferScope::AllLabels);
+ this->SetLabelTransferMode(LabelTransferMode::AddLabel);
}
void mitk::nnUNetTool::RenderOutputBuffer()
{
if (m_OutputBuffer != nullptr)
{
try
{
if (nullptr != this->GetPreviewSegmentationNode())
{
auto previewImage = this->GetPreviewSegmentation();
previewImage->InitializeByLabeledImage(m_OutputBuffer);
}
}
catch (const mitk::Exception &e)
{
MITK_INFO << e.GetDescription();
}
}
}
void mitk::nnUNetTool::SetOutputBuffer(LabelSetImage::Pointer segmentation)
{
m_OutputBuffer = segmentation;
}
mitk::LabelSetImage::Pointer mitk::nnUNetTool::GetOutputBuffer()
{
return m_OutputBuffer;
}
void mitk::nnUNetTool::ClearOutputBuffer()
{
m_OutputBuffer = nullptr;
}
us::ModuleResource mitk::nnUNetTool::GetIconResource() const
{
us::Module *module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("AI.svg");
return resource;
}
const char **mitk::nnUNetTool::GetXPM() const
{
return nullptr;
}
const char *mitk::nnUNetTool::GetName() const
{
return "nnUNet";
}
mitk::DataStorage *mitk::nnUNetTool::GetDataStorage()
{
return this->GetToolManager()->GetDataStorage();
}
mitk::DataNode *mitk::nnUNetTool::GetRefNode()
{
return this->GetToolManager()->GetReferenceData(0);
}
+void mitk::nnUNetTool::UpdatePrepare()
+{
+ Superclass::UpdatePrepare();
+ auto preview = this->GetPreviewSegmentation();
+ auto labelset = preview->GetLabelSet(preview->GetActiveLayer());
+ labelset->RemoveAllLabels();
+}
+
namespace
{
void onPythonProcessEvent(itk::Object * /*pCaller*/, const itk::EventObject &e, void *)
{
std::string testCOUT;
std::string testCERR;
const auto *pEvent = dynamic_cast<const mitk::ExternalProcessStdOutEvent *>(&e);
if (pEvent)
{
testCOUT = testCOUT + pEvent->GetOutput();
MITK_INFO << testCOUT;
}
const auto *pErrEvent = dynamic_cast<const mitk::ExternalProcessStdErrEvent *>(&e);
if (pErrEvent)
{
testCERR = testCERR + pErrEvent->GetOutput();
MITK_ERROR << testCERR;
}
}
} // namespace
void mitk::nnUNetTool::DoUpdatePreview(const Image* inputAtTimeStep, const Image* /*oldSegAtTimeStep*/, LabelSetImage* previewImage, TimeStepType /*timeStep*/)
{
if (this->GetMitkTempDir().empty())
{
this->SetMitkTempDir(IOUtil::CreateTemporaryDirectory("mitk-nnunet-XXXXXX"));
}
std::string inDir, outDir, inputImagePath, outputImagePath, scriptPath;
ProcessExecutor::Pointer spExec = ProcessExecutor::New();
itk::CStyleCommand::Pointer spCommand = itk::CStyleCommand::New();
spCommand->SetCallback(&onPythonProcessEvent);
spExec->AddObserver(ExternalProcessOutputEvent(), spCommand);
ProcessExecutor::ArgumentListType args;
inDir = IOUtil::CreateTemporaryDirectory("nnunet-in-XXXXXX", this->GetMitkTempDir());
std::ofstream tmpStream;
inputImagePath = IOUtil::CreateTemporaryFile(tmpStream, m_TEMPLATE_FILENAME, inDir + IOUtil::GetDirectorySeparator());
tmpStream.close();
std::size_t found = inputImagePath.find_last_of(IOUtil::GetDirectorySeparator());
std::string fileName = inputImagePath.substr(found + 1);
std::string token = fileName.substr(0, fileName.find("_"));
if (this->GetNoPip())
{
scriptPath = this->GetnnUNetDirectory() + IOUtil::GetDirectorySeparator() + "nnunet" +
IOUtil::GetDirectorySeparator() + "inference" + IOUtil::GetDirectorySeparator() + "predict_simple.py";
}
try
{
if (this->GetMultiModal())
{
const std::string fileFormat(".nii.gz");
const std::string fileNamePart("_000_000");
std::string outModalFile;
size_t len = inDir.length() + 1 + token.length() + fileNamePart.length() + 1 + fileFormat.length();
outModalFile.reserve(len); // The 1(s) indicates a directory separator char and an underscore.
for (size_t i = 0; i < m_OtherModalPaths.size(); ++i)
{
mitk::Image::ConstPointer modalImage = m_OtherModalPaths[i];
outModalFile.append(inDir);
outModalFile.push_back(IOUtil::GetDirectorySeparator());
outModalFile.append(token);
outModalFile.append(fileNamePart);
outModalFile.append(std::to_string(i));
outModalFile.append(fileFormat);
IOUtil::Save(modalImage.GetPointer(), outModalFile);
outModalFile.clear();
}
}
else
{
IOUtil::Save(inputAtTimeStep, inputImagePath);
}
}
catch (const mitk::Exception &e)
{
MITK_ERROR << e.GetDescription();
return;
}
// Code calls external process
std::string command = "nnUNet_predict";
if (this->GetNoPip())
{
#ifdef _WIN32
command = "python";
#else
command = "python3";
#endif
}
for (ModelParams &modelparam : m_ParamQ)
{
outDir = IOUtil::CreateTemporaryDirectory("nnunet-out-XXXXXX", this->GetMitkTempDir());
outputImagePath = outDir + IOUtil::GetDirectorySeparator() + token + "_000.nii.gz";
modelparam.outputDir = outDir;
args.clear();
if (this->GetNoPip())
{
args.push_back(scriptPath);
}
args.push_back("-i");
args.push_back(inDir);
args.push_back("-o");
args.push_back(outDir);
args.push_back("-t");
args.push_back(modelparam.task);
if (modelparam.model.find("cascade") != std::string::npos)
{
args.push_back("-ctr");
}
else
{
args.push_back("-tr");
}
args.push_back(modelparam.trainer);
args.push_back("-m");
args.push_back(modelparam.model);
args.push_back("-p");
args.push_back(modelparam.planId);
if (!modelparam.folds.empty())
{
args.push_back("-f");
for (auto fold : modelparam.folds)
{
args.push_back(fold);
}
}
args.push_back("--num_threads_nifti_save");
args.push_back("1"); // fixing to 1
if (!this->GetMirror())
{
args.push_back("--disable_tta");
}
if (!this->GetMixedPrecision())
{
args.push_back("--disable_mixed_precision");
}
if (this->GetEnsemble())
{
args.push_back("--save_npz");
}
try
{
std::string resultsFolderEnv = "RESULTS_FOLDER=" + this->GetModelDirectory();
itksys::SystemTools::PutEnv(resultsFolderEnv.c_str());
std::string cudaEnv = "CUDA_VISIBLE_DEVICES=" + std::to_string(this->GetGpuId());
itksys::SystemTools::PutEnv(cudaEnv.c_str());
spExec->Execute(this->GetPythonPath(), command, args);
}
catch (const mitk::Exception &e)
{
/*
Can't throw mitk exception to the caller. Refer: T28691
*/
MITK_ERROR << e.GetDescription();
return;
}
}
if (this->GetEnsemble() && !this->GetPostProcessingJsonDirectory().empty())
{
args.clear();
command = "nnUNet_ensemble";
outDir = IOUtil::CreateTemporaryDirectory("nnunet-ensemble-out-XXXXXX", this->GetMitkTempDir());
outputImagePath = outDir + IOUtil::GetDirectorySeparator() + token + "_000.nii.gz";
args.push_back("-f");
for (ModelParams &modelparam : m_ParamQ)
{
args.push_back(modelparam.outputDir);
}
args.push_back("-o");
args.push_back(outDir);
if (!this->GetPostProcessingJsonDirectory().empty())
{
args.push_back("-pp");
args.push_back(this->GetPostProcessingJsonDirectory());
}
spExec->Execute(this->GetPythonPath(), command, args);
}
try
{
Image::Pointer outputImage = IOUtil::Load<Image>(outputImagePath);
previewImage->InitializeByLabeledImage(outputImage);
previewImage->SetGeometry(inputAtTimeStep->GetGeometry());
m_InputBuffer = inputAtTimeStep;
m_OutputBuffer = mitk::LabelSetImage::New();
m_OutputBuffer->InitializeByLabeledImage(outputImage);
m_OutputBuffer->SetGeometry(inputAtTimeStep->GetGeometry());
}
catch (const mitk::Exception &e)
{
MITK_ERROR << e.GetDescription();
return;
}
}
diff --git a/Modules/Segmentation/Interactions/mitknnUnetTool.h b/Modules/Segmentation/Interactions/mitknnUnetTool.h
index af8f1f6465..e6e3fc9bb1 100644
--- a/Modules/Segmentation/Interactions/mitknnUnetTool.h
+++ b/Modules/Segmentation/Interactions/mitknnUnetTool.h
@@ -1,214 +1,215 @@
/*============================================================================
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 mitknnUnetTool_h
#define mitknnUnetTool_h
#include "mitkSegWithPreviewTool.h"
#include "mitkCommon.h"
#include "mitkToolManager.h"
#include <MitkSegmentationExports.h>
#include <mitkStandardFileLocations.h>
#include <numeric>
#include <utility>
namespace us
{
class ModuleResource;
}
namespace mitk
{
/**
* @brief nnUNet parameter request object holding all model parameters for input.
* Also holds output temporary directory path.
*/
struct ModelParams
{
std::string task;
std::vector<std::string> folds;
std::string model;
std::string trainer;
std::string planId;
std::string outputDir;
std::string inputName;
std::string timeStamp;
size_t generateHash() const
{
std::string toHash;
std::string foldsConcatenated = std::accumulate(folds.begin(), folds.end(), std::string(""));
toHash += this->task;
toHash += this->model;
toHash += this->inputName;
toHash += foldsConcatenated;
toHash += this->timeStamp;
size_t hashVal = std::hash<std::string>{}(toHash);
return hashVal;
}
};
/**
\brief nnUNet segmentation tool.
\ingroup Interaction
\ingroup ToolManagerEtAl
\warning Only to be instantiated by mitk::ToolManager.
*/
class MITKSEGMENTATION_EXPORT nnUNetTool : public SegWithPreviewTool
{
public:
mitkClassMacro(nnUNetTool, SegWithPreviewTool);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
const char **GetXPM() const override;
const char *GetName() const override;
us::ModuleResource GetIconResource() const override;
void Activated() override;
itkSetMacro(nnUNetDirectory, std::string);
itkGetConstMacro(nnUNetDirectory, std::string);
itkSetMacro(ModelDirectory, std::string);
itkGetConstMacro(ModelDirectory, std::string);
itkSetMacro(PythonPath, std::string);
itkGetConstMacro(PythonPath, std::string);
itkSetMacro(MitkTempDir, std::string);
itkGetConstMacro(MitkTempDir, std::string);
itkSetMacro(PostProcessingJsonDirectory, std::string);
itkGetConstMacro(PostProcessingJsonDirectory, std::string);
itkSetMacro(MixedPrecision, bool);
itkGetConstMacro(MixedPrecision, bool);
itkBooleanMacro(MixedPrecision);
itkSetMacro(Mirror, bool);
itkGetConstMacro(Mirror, bool);
itkBooleanMacro(Mirror);
itkSetMacro(MultiModal, bool);
itkGetConstMacro(MultiModal, bool);
itkBooleanMacro(MultiModal);
itkSetMacro(NoPip, bool);
itkGetConstMacro(NoPip, bool);
itkBooleanMacro(NoPip);
itkSetMacro(Ensemble, bool);
itkGetConstMacro(Ensemble, bool);
itkBooleanMacro(Ensemble);
itkSetMacro(Predict, bool);
itkGetConstMacro(Predict, bool);
itkBooleanMacro(Predict);
itkSetMacro(GpuId, unsigned int);
itkGetConstMacro(GpuId, unsigned int);
/**
* @brief vector of ModelParams.
* Size > 1 only for ensemble prediction.
*/
std::vector<ModelParams> m_ParamQ;
/**
* @brief Holds paths to other input image modalities.
*
*/
std::vector<mitk::Image::ConstPointer> m_OtherModalPaths;
mitk::Image::ConstPointer m_InputBuffer;
/**
* @brief Renders the output LabelSetImage.
* To called in the main thread.
*/
void RenderOutputBuffer();
/**
* @brief Get the Output Buffer object
*
* @return LabelSetImage::Pointer
*/
LabelSetImage::Pointer GetOutputBuffer();
/**
* @brief Sets the outputBuffer to nullptr
*
*/
void ClearOutputBuffer();
/**
* @brief Returns the DataStorage from the ToolManager
*/
mitk::DataStorage *GetDataStorage();
mitk::DataNode *GetRefNode();
void SetOutputBuffer(LabelSetImage::Pointer);
protected:
/**
* @brief Construct a new nnUNet Tool object.
*
*/
nnUNetTool() = default;
/**
* @brief Destroy the nnUNet Tool object and deletes the temp directory.
*
*/
~nnUNetTool();
/**
* @brief Overriden method from the tool manager to execute the segmentation
* Implementation:
* 1. Saves the inputAtTimeStep in a temporary directory.
* 2. Copies other modalities, renames and saves in the temporary directory, if required.
* 3. Sets RESULTS_FOLDER and CUDA_VISIBLE_DEVICES variables in the environment.
* 3. Iterates through the parameter queue (m_ParamQ) and executes "nnUNet_predict" command with the parameters
* 4. Expects an output image to be saved in the temporary directory by the python proces. Loads it as
* LabelSetImage and sets to previewImage.
*
* @param inputAtTimeStep
* @param oldSegAtTimeStep
* @param previewImage
* @param timeStep
*/
void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep) override;
+ void UpdatePrepare() override;
private:
std::string m_MitkTempDir;
std::string m_nnUNetDirectory;
std::string m_ModelDirectory;
std::string m_PythonPath;
std::string m_PostProcessingJsonDirectory;
// bool m_UseGPU; kept for future
// bool m_AllInGPU;
bool m_MixedPrecision;
bool m_Mirror;
bool m_NoPip;
bool m_MultiModal;
bool m_Ensemble = false;
bool m_Predict;
LabelSetImage::Pointer m_OutputBuffer;
unsigned int m_GpuId;
const std::string m_TEMPLATE_FILENAME = "XXXXXX_000_0000.nii.gz";
};
} // namespace mitk
#endif
diff --git a/Modules/Segmentation/Resources/Interactions/EditableContourTool.xml b/Modules/Segmentation/Resources/Interactions/EditableContourTool.xml
index c9ba8da33f..d208e132b7 100644
--- a/Modules/Segmentation/Resources/Interactions/EditableContourTool.xml
+++ b/Modules/Segmentation/Resources/Interactions/EditableContourTool.xml
@@ -1,42 +1,44 @@
<statemachine name="LiveWireTool">
<state name="Start" ID="1" startstate="true">
<transition event_class="MouseDoubleClickEvent" event_variant="PrimaryButtonDoubleClick" target="PressedState" >
<action name="InitObject" ID="5" />
</transition>
</state>
<state name="Active" ID="2" >
<transition event_class="MousePressEvent" event_variant="PrimaryButtonPressed" target="PressedState" >
<action name="AddPoint" ID="10" />
</transition>
<transition event_class="MouseMoveEvent" event_variant="MouseMove" target="Active" >
<action name="MovePoint" ID="92" />
</transition>
<transition event_class="MouseDoubleClickEvent" event_variant="PrimaryButtonDoubleClick" target="Start" >
<action name="FinishContour" ID="44" />
</transition>
<transition event_class="MouseMoveEvent" event_variant="CtrlMouseMove" target="Active" >
<action name="CtrlMovePoint" ID="12"/>
</transition>
<transition event_class="MousePressEvent" event_variant="CtrlPrimaryButtonPressed" target="Active" >
<action name="CtrlAddPoint" ID="10" />
</transition>
</state>
<state name="PressedState" ID="3">
<transition event_class="MouseMoveEvent" event_variant="PrimaryButtonMoved" target="Drawing" >
<action name="Drawing"/>
+ <condition name="InsideCorrectPlane"/>
</transition>
<transition event_class="MouseMoveEvent" event_variant="MouseMove" target="Active" >
<action name="MovePoint" ID="92" />
</transition>
<transition event_class="MouseReleaseEvent" event_variant="PrimaryButtonReleased" target="Active" >
</transition>
</state>
<state name="Drawing" ID="4">
<transition event_class="MouseMoveEvent" event_variant="PrimaryButtonMoved" target="Drawing" >
<action name="Drawing"/>
+ <condition name="InsideCorrectPlane"/>
</transition>
<transition event_class="MouseReleaseEvent" event_variant="PrimaryButtonReleased" target="Active" >
<action name="EndDrawing"/>
</transition>
</state>
</statemachine>
diff --git a/Modules/Segmentation/Testing/mitkOverwriteSliceFilterObliquePlaneTest.cpp b/Modules/Segmentation/Testing/mitkOverwriteSliceFilterObliquePlaneTest.cpp
index a6bb783040..e5839fa022 100644
--- a/Modules/Segmentation/Testing/mitkOverwriteSliceFilterObliquePlaneTest.cpp
+++ b/Modules/Segmentation/Testing/mitkOverwriteSliceFilterObliquePlaneTest.cpp
@@ -1,254 +1,254 @@
/*============================================================================
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 <mitkExtractSliceFilter.h>
#include <mitkGeometry3D.h>
#include <mitkImageCast.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkInteractionConst.h>
#include <mitkRotationOperation.h>
#include <mitkVtkImageOverwrite.h>
#include <itkImage.h>
#include <itkImageRegionIterator.h>
#include <vtkImageData.h>
#include <vtkSmartPointer.h>
int ObliquePlaneTestVolumeSize = 128;
static void OverwriteObliquePlaneTest(mitk::Image *workingImage, mitk::Image *refImg)
{
/*==============TEST WITHOUT MITK CONVERTION=============================*/
/* ============= setup plane ============*/
auto sliceindex = (int)(ObliquePlaneTestVolumeSize / 2); // rand() % 32;
bool isFrontside = true;
bool isRotated = false;
mitk::PlaneGeometry::Pointer obliquePlane = mitk::PlaneGeometry::New();
obliquePlane->InitializeStandardPlane(
workingImage->GetGeometry(), mitk::AnatomicalPlane::Axial, sliceindex, isFrontside, isRotated);
mitk::Point3D origin = obliquePlane->GetOrigin();
mitk::Vector3D normal;
normal = obliquePlane->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
obliquePlane->SetOrigin(origin);
mitk::Vector3D rotationVector = obliquePlane->GetAxisVector(0);
rotationVector.Normalize();
float degree = 45.0;
auto op = new mitk::RotationOperation(mitk::OpROTATE, obliquePlane->GetCenter(), rotationVector, degree);
obliquePlane->ExecuteOperation(op);
delete op;
/* ============= extract slice ============*/
mitk::ExtractSliceFilter::Pointer slicer = mitk::ExtractSliceFilter::New();
slicer->SetInput(workingImage);
slicer->SetWorldGeometry(obliquePlane);
slicer->SetVtkOutputRequest(true);
slicer->Modified();
slicer->Update();
vtkSmartPointer<vtkImageData> slice = vtkSmartPointer<vtkImageData>::New();
slice = slicer->GetVtkOutput();
/* ============= overwrite slice ============*/
vtkSmartPointer<mitkVtkImageOverwrite> resliceIdx = vtkSmartPointer<mitkVtkImageOverwrite>::New();
mitk::ExtractSliceFilter::Pointer overwriter = mitk::ExtractSliceFilter::New(resliceIdx);
resliceIdx->SetOverwriteMode(true);
resliceIdx->SetInputSlice(slice);
resliceIdx->Modified();
overwriter->SetInput(workingImage);
overwriter->SetWorldGeometry(obliquePlane);
overwriter->SetVtkOutputRequest(true);
overwriter->Modified();
overwriter->Update();
typedef mitk::ImagePixelReadAccessor<unsigned short, 3> ReadAccessorType;
ReadAccessorType refImgReadAccessor(refImg);
ReadAccessorType workingImgReadAccessor(workingImage);
/* ============= check ref == working ============*/
bool areSame = true;
itk::Index<3> id;
id[0] = id[1] = id[2] = 0;
for (int x = 0; x < ObliquePlaneTestVolumeSize; ++x)
{
id[0] = x;
for (int y = 0; y < ObliquePlaneTestVolumeSize; ++y)
{
id[1] = y;
for (int z = 0; z < ObliquePlaneTestVolumeSize; ++z)
{
id[2] = z;
areSame = refImgReadAccessor.GetPixelByIndex(id) == workingImgReadAccessor.GetPixelByIndex(id);
if (!areSame)
goto stop;
}
}
}
stop:
MITK_TEST_CONDITION(areSame, "comparing images (no mitk convertion) [oblique]");
/*==============TEST WITH MITK CONVERTION=============================*/
/* ============= extract slice ============*/
mitk::ExtractSliceFilter::Pointer slicer2 = mitk::ExtractSliceFilter::New();
slicer2->SetInput(workingImage);
slicer2->SetWorldGeometry(obliquePlane);
slicer2->Modified();
slicer2->Update();
mitk::Image::Pointer sliceInMitk = slicer2->GetOutput();
vtkSmartPointer<vtkImageData> slice2 = vtkSmartPointer<vtkImageData>::New();
slice2 = sliceInMitk->GetVtkImageData();
/* ============= overwrite slice ============*/
vtkSmartPointer<mitkVtkImageOverwrite> resliceIdx2 = vtkSmartPointer<mitkVtkImageOverwrite>::New();
mitk::ExtractSliceFilter::Pointer overwriter2 = mitk::ExtractSliceFilter::New(resliceIdx2);
resliceIdx2->SetOverwriteMode(true);
resliceIdx2->SetInputSlice(slice2);
resliceIdx2->Modified();
overwriter2->SetInput(workingImage);
overwriter2->SetWorldGeometry(obliquePlane);
overwriter2->SetVtkOutputRequest(true);
overwriter2->Modified();
overwriter2->Update();
/* ============= check ref == working ============*/
areSame = true;
id[0] = id[1] = id[2] = 0;
for (int x = 0; x < ObliquePlaneTestVolumeSize; ++x)
{
id[0] = x;
for (int y = 0; y < ObliquePlaneTestVolumeSize; ++y)
{
id[1] = y;
for (int z = 0; z < ObliquePlaneTestVolumeSize; ++z)
{
id[2] = z;
areSame = refImgReadAccessor.GetPixelByIndex(id) == workingImgReadAccessor.GetPixelByIndex(id);
if (!areSame)
goto stop2;
}
}
}
stop2:
MITK_TEST_CONDITION(areSame, "comparing images (with mitk convertion) [oblique]");
/*==============TEST EDIT WITHOUT MITK CONVERTION=============================*/
/* ============= edit slice ============*/
int idX = std::abs(ObliquePlaneTestVolumeSize - 59);
int idY = std::abs(ObliquePlaneTestVolumeSize - 23);
int idZ = 0;
int component = 0;
double val = 33.0;
slice->SetScalarComponentFromDouble(idX, idY, idZ, component, val);
mitk::Vector3D indx;
indx[0] = idX;
indx[1] = idY;
indx[2] = idZ;
sliceInMitk->GetGeometry()->IndexToWorld(indx, indx);
/* ============= overwrite slice ============*/
vtkSmartPointer<mitkVtkImageOverwrite> resliceIdx3 = vtkSmartPointer<mitkVtkImageOverwrite>::New();
resliceIdx3->SetOverwriteMode(true);
resliceIdx3->SetInputSlice(slice);
mitk::ExtractSliceFilter::Pointer overwriter3 = mitk::ExtractSliceFilter::New(resliceIdx3);
overwriter3->SetInput(workingImage);
overwriter3->SetWorldGeometry(obliquePlane);
overwriter3->SetVtkOutputRequest(true);
overwriter3->Modified();
overwriter3->Update();
/* ============= check ============*/
areSame = true;
int x = 0;
int y = 0;
int z = 0;
for (x = 0; x < ObliquePlaneTestVolumeSize; ++x)
{
id[0] = x;
for (y = 0; y < ObliquePlaneTestVolumeSize; ++y)
{
id[1] = y;
for (z = 0; z < ObliquePlaneTestVolumeSize; ++z)
{
id[2] = z;
areSame = refImgReadAccessor.GetPixelByIndex(id) == workingImgReadAccessor.GetPixelByIndex(id);
if (!areSame)
goto stop3;
}
}
}
stop3:
MITK_TEST_CONDITION(x == idX && y == z, "overwrited the right index [oblique]");
}
/*================ #BEGIN test main ================*/
int mitkOverwriteSliceFilterObliquePlaneTest(int, char *[])
{
MITK_TEST_BEGIN("mitkOverwriteSliceFilterObliquePlaneTest")
typedef itk::Image<unsigned short, 3> ImageType;
typedef itk::ImageRegionConstIterator<ImageType> ImageIterator;
ImageType::Pointer image = ImageType::New();
ImageType::IndexType start;
start[0] = start[1] = start[2] = 0;
ImageType::SizeType size;
size[0] = size[1] = size[2] = ObliquePlaneTestVolumeSize;
ImageType::RegionType imgRegion;
imgRegion.SetSize(size);
imgRegion.SetIndex(start);
image->SetRegions(imgRegion);
- image->SetSpacing(1.0);
+ image->SetSpacing(mitk::Vector(1.0));
image->Allocate();
ImageIterator imageIterator(image, image->GetLargestPossibleRegion());
imageIterator.GoToBegin();
unsigned short pixelValue = 0;
// fill the image with distinct values
while (!imageIterator.IsAtEnd())
{
image->SetPixel(imageIterator.GetIndex(), pixelValue);
++imageIterator;
++pixelValue;
}
/* end setup itk image */
mitk::Image::Pointer refImage;
CastToMitkImage(image, refImage);
mitk::Image::Pointer workingImg;
CastToMitkImage(image, workingImg);
OverwriteObliquePlaneTest(workingImg, refImage);
MITK_TEST_END()
}
diff --git a/Modules/Segmentation/Testing/mitkOverwriteSliceFilterTest.cpp b/Modules/Segmentation/Testing/mitkOverwriteSliceFilterTest.cpp
index 6b67791740..f522844be6 100644
--- a/Modules/Segmentation/Testing/mitkOverwriteSliceFilterTest.cpp
+++ b/Modules/Segmentation/Testing/mitkOverwriteSliceFilterTest.cpp
@@ -1,181 +1,181 @@
/*============================================================================
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 <mitkExtractSliceFilter.h>
#include <mitkGeometry3D.h>
#include <mitkImageCast.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkInteractionConst.h>
#include <mitkRotationOperation.h>
#include <mitkVtkImageOverwrite.h>
#include <itkImage.h>
#include <itkImageRegionIterator.h>
#include <vtkImageData.h>
#include <vtkSmartPointer.h>
int VolumeSize = 128;
/*================ #BEGIN test main ================*/
int mitkOverwriteSliceFilterTest(int, char *[])
{
MITK_TEST_BEGIN("mitkOverwriteSliceFilterTest")
typedef itk::Image<unsigned short, 3> ImageType;
typedef itk::ImageRegionConstIterator<ImageType> ImageIterator;
ImageType::Pointer image = ImageType::New();
ImageType::IndexType start;
start[0] = start[1] = start[2] = 0;
ImageType::SizeType size;
size[0] = size[1] = size[2] = VolumeSize;
ImageType::RegionType imgRegion;
imgRegion.SetSize(size);
imgRegion.SetIndex(start);
image->SetRegions(imgRegion);
- image->SetSpacing(1.0);
+ image->SetSpacing(mitk::Vector(1.0));
image->Allocate();
ImageIterator imageIterator(image, image->GetLargestPossibleRegion());
imageIterator.GoToBegin();
unsigned short pixelValue = 0;
// fill the image with distinct values
while (!imageIterator.IsAtEnd())
{
image->SetPixel(imageIterator.GetIndex(), pixelValue);
++imageIterator;
++pixelValue;
}
/* end setup itk image */
mitk::Image::Pointer referenceImage;
CastToMitkImage(image, referenceImage);
mitk::Image::Pointer workingImage;
CastToMitkImage(image, workingImage);
typedef mitk::ImagePixelReadAccessor<unsigned short, 3> ReadAccessorType;
ReadAccessorType refImgReadAccessor(referenceImage);
ReadAccessorType workingImgReadAccessor(workingImage);
/* ============= setup plane ============*/
int sliceindex = 55; // rand() % 32;
bool isFrontside = true;
bool isRotated = false;
mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New();
plane->InitializeStandardPlane(
workingImage->GetGeometry(), mitk::AnatomicalPlane::Axial, sliceindex, isFrontside, isRotated);
mitk::Point3D origin = plane->GetOrigin();
mitk::Vector3D normal;
normal = plane->GetNormal();
normal.Normalize();
origin += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
plane->SetOrigin(origin);
/* ============= extract slice ============*/
vtkSmartPointer<mitkVtkImageOverwrite> resliceIdx = vtkSmartPointer<mitkVtkImageOverwrite>::New();
mitk::ExtractSliceFilter::Pointer slicer = mitk::ExtractSliceFilter::New(resliceIdx);
slicer->SetInput(workingImage);
slicer->SetWorldGeometry(plane);
slicer->SetVtkOutputRequest(true);
slicer->Modified();
slicer->Update();
vtkSmartPointer<vtkImageData> slice = vtkSmartPointer<vtkImageData>::New();
slice = slicer->GetVtkOutput();
/* ============= overwrite slice ============*/
resliceIdx->SetOverwriteMode(true);
resliceIdx->Modified();
slicer->Modified();
slicer->Update(); // implicit overwrite
/* ============= check ref == working ============*/
bool areSame = true;
itk::Index<3> id;
id[0] = id[1] = id[2] = 0;
for (int x = 0; x < VolumeSize; ++x)
{
id[0] = x;
for (int y = 0; y < VolumeSize; ++y)
{
id[1] = y;
for (int z = 0; z < VolumeSize; ++z)
{
id[2] = z;
areSame = refImgReadAccessor.GetPixelByIndex(id) == workingImgReadAccessor.GetPixelByIndex(id);
if (!areSame)
goto stop;
}
}
}
stop:
MITK_TEST_CONDITION(areSame, "test overwrite unmodified slice");
/* ============= edit slice ============*/
int idX = std::abs(VolumeSize - 59);
int idY = std::abs(VolumeSize - 23);
int idZ = 0;
int component = 0;
double val = 33.0;
slice->SetScalarComponentFromDouble(idX, idY, idZ, component, val);
/* ============= overwrite slice ============*/
vtkSmartPointer<mitkVtkImageOverwrite> resliceIdx2 = vtkSmartPointer<mitkVtkImageOverwrite>::New();
resliceIdx2->SetOverwriteMode(true);
resliceIdx2->SetInputSlice(slice);
mitk::ExtractSliceFilter::Pointer slicer2 = mitk::ExtractSliceFilter::New(resliceIdx2);
slicer2->SetInput(workingImage);
slicer2->SetWorldGeometry(plane);
slicer2->SetVtkOutputRequest(true);
slicer2->Modified();
slicer2->Update();
/* ============= check ============*/
areSame = true;
int xx = 0;
int yy = 0;
int zz = 0;
for (xx = 0; xx < VolumeSize; ++xx)
{
id[0] = xx;
for (yy = 0; yy < VolumeSize; ++yy)
{
id[1] = yy;
for (zz = 0; zz < VolumeSize; ++zz)
{
id[2] = zz;
areSame = refImgReadAccessor.GetPixelByIndex(id) == workingImgReadAccessor.GetPixelByIndex(id);
if (!areSame)
goto stop2;
}
}
}
stop2:
// MITK_INFO << "index: [" << x << ", " << y << ", " << z << "]";
MITK_TEST_CONDITION(xx == idX && yy == idY && zz == sliceindex, "test overwrite modified slice");
MITK_TEST_END()
}
diff --git a/Modules/Segmentation/cmdapps/CMakeLists.txt b/Modules/Segmentation/cmdapps/CMakeLists.txt
new file mode 100644
index 0000000000..cd901f3528
--- /dev/null
+++ b/Modules/Segmentation/cmdapps/CMakeLists.txt
@@ -0,0 +1,8 @@
+option(BUILD_SegmentationCmdApps "Build command-line apps of the MitkSegmentation module" OFF)
+
+if(BUILD_SegmentationCmdApps OR MITK_BUILD_ALL_APPS)
+ mitkFunctionCreateCommandLineApp(
+ NAME ContoursToImage
+ DEPENDS MitkSegmentation
+ )
+endif()
diff --git a/Modules/Segmentation/cmdapps/ContoursToImage.cpp b/Modules/Segmentation/cmdapps/ContoursToImage.cpp
new file mode 100644
index 0000000000..d6f865c9fa
--- /dev/null
+++ b/Modules/Segmentation/cmdapps/ContoursToImage.cpp
@@ -0,0 +1,312 @@
+/*============================================================================
+
+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 <mitkCommandLineParser.h>
+#include <mitkContourModelSet.h>
+#include <mitkContourModelSetToImageFilter.h>
+#include <mitkDataStorage.h>
+#include <mitkImageReadAccessor.h>
+#include <mitkImageWriteAccessor.h>
+#include <mitkIOUtil.h>
+#include <mitkLabelSetImage.h>
+#include <mitkLabelSetImageHelper.h>
+
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+#include <filesystem>
+
+enum class OutputFormat
+{
+ Binary,
+ Label,
+ Multilabel
+};
+
+void InitializeCommandLineParser(mitkCommandLineParser& parser)
+{
+ parser.setTitle("Contour to Image Converter");
+ parser.setCategory("Segmentation");
+ parser.setDescription("Converts contours (i. e. RTSTRUCT or MITK Contour Model Set) to binary image masks or (multi-)label segmentations.");
+ parser.setContributor("German Cancer Research Center (DKFZ)");
+ parser.setArgumentPrefix("--", "-");
+
+ parser.addArgument("input", "i", mitkCommandLineParser::File, "Input file:", "Input contour(s)", us::Any(), false, false, false, mitkCommandLineParser::Input);
+ parser.addArgument("reference", "r", mitkCommandLineParser::Image, "Reference image:", "Input reference image", us::Any(), false, false, false, mitkCommandLineParser::Input);
+ parser.addArgument("output", "o", mitkCommandLineParser::Image, "Output file:", "Output image", us::Any(), false, false, false, mitkCommandLineParser::Output);
+ parser.addArgument("format", "f", mitkCommandLineParser::String, "Output format:", "Output format (binary, label, or multilabel)", std::string("binary"));
+}
+
+std::string GetSafeName(const mitk::IPropertyProvider* propertyProvider)
+{
+ std::string name;
+
+ if (propertyProvider != nullptr)
+ {
+ name = propertyProvider->GetConstProperty("name")->GetValueAsString();
+
+ if (!name.empty())
+ {
+ boost::trim(name);
+ boost::replace_all(name, "/", "_");
+ boost::replace_all(name, "\\", "_");
+
+ // If you read this, feel free to handle invalid filename characters here. :)
+ }
+ }
+
+ return name;
+}
+
+void CreateParentDirectories(const std::filesystem::path& path)
+{
+ if (path.has_parent_path())
+ {
+ auto parentPath = path.parent_path();
+
+ if (!std::filesystem::exists(parentPath))
+ std::filesystem::create_directories(parentPath);
+ }
+}
+
+bool SetLabelName(const mitk::IPropertyProvider* propertyProvider, mitk::Label* label)
+{
+ if (propertyProvider != nullptr)
+ {
+ if (auto property = propertyProvider->GetConstProperty("name"); property.IsNotNull())
+ {
+ if (auto nameProperty = dynamic_cast<const mitk::StringProperty*>(property.GetPointer()); nameProperty != nullptr)
+ {
+ if (auto name = nameProperty->GetValueAsString(); !name.empty())
+ {
+ label->SetName(name);
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool SetLabelColor(const mitk::IPropertyProvider* propertyProvider, mitk::Label* label)
+{
+ if (propertyProvider != nullptr)
+ {
+ if (auto property = propertyProvider->GetConstProperty("color"); property.IsNotNull())
+ {
+ if (auto colorProperty = dynamic_cast<const mitk::ColorProperty*>(property.GetPointer()); colorProperty != nullptr)
+ {
+ label->SetColor(colorProperty->GetColor());
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void CopyImageToActiveLayerImage(const mitk::Image* image, mitk::LabelSetImage* labelSetImage)
+{
+ mitk::ImageReadAccessor readAccessor(image);
+ mitk::ImageWriteAccessor writeAccessor(labelSetImage);
+
+ auto size = sizeof(mitk::Label::PixelType);
+
+ for (size_t dim = 0; dim < image->GetDimension(); ++dim)
+ size *= image->GetDimension(dim);
+
+ memcpy(writeAccessor.GetData(), readAccessor.GetData(), size);
+}
+
+OutputFormat ParseOutputFormat(const mitk::IFileIO::Options& args)
+{
+ auto it = args.find("format");
+
+ if (it != args.end())
+ {
+ auto format = us::any_cast<std::string>(it->second);
+
+ if (format == "multilabel")
+ return OutputFormat::Multilabel;
+
+ if (format == "label")
+ return OutputFormat::Label;
+
+ if (format != "binary")
+ mitkThrow() << "Unknown output format \"" << format << "\" (must be \"binary\", \"label\" or \"multilabel\").";
+ }
+
+ return OutputFormat::Binary;
+}
+
+std::vector<mitk::ContourModelSet::Pointer> FilterValidInputs(const std::vector<mitk::BaseData::Pointer>& inputs)
+{
+ std::vector<mitk::ContourModelSet::Pointer> validInputs;
+
+ for (auto input : inputs)
+ {
+ if (input.IsNull())
+ {
+ MITK_WARN << "Skipping null input.";
+ continue;
+ }
+
+ auto* validInput = dynamic_cast<mitk::ContourModelSet*>(input.GetPointer());
+
+ if (validInput == nullptr)
+ {
+ MITK_WARN << "Skipping input of type \"" << input->GetNameOfClass() << "\".";
+ continue;
+ }
+
+ validInputs.push_back(validInput);
+ }
+
+ return validInputs;
+}
+
+int main(int argc, char* argv[])
+{
+ int returnValue = EXIT_SUCCESS;
+
+ mitkCommandLineParser parser;
+ InitializeCommandLineParser(parser);
+
+ auto args = parser.parseArguments(argc, argv);
+
+ if (args.empty())
+ return EXIT_FAILURE;
+
+ try
+ {
+ auto inputFilename = us::any_cast<std::string>(args["input"]);
+ auto referenceFilename = us::any_cast<std::string>(args["reference"]);
+ auto outputFilename = us::any_cast<std::string>(args["output"]);
+ auto format = ParseOutputFormat(args);
+
+ auto referenceImage = mitk::IOUtil::Load<mitk::Image>(referenceFilename);
+ auto inputs = FilterValidInputs(mitk::IOUtil::Load(inputFilename));
+
+ MITK_INFO << "Found " << inputs.size() << " input contour set(s)";
+
+ std::filesystem::path outputPath(outputFilename);
+ CreateParentDirectories(outputPath);
+
+ mitk::LabelSetImage::Pointer labelSetImage; // Only used for "multilabel" output
+ unsigned int nonameCounter = 0; // Helper variable to generate placeholder names for nameless contour sets
+
+ for (auto input : inputs)
+ {
+ // If the input file contains multiple contour sets but the output format is not set to "multilabel",
+ // we create separate output files for each contour set. In this case the specified output filename
+ // is used only as a base filename and the names of the individual contour sets are appended accordingly.
+
+ if (inputs.size() > 1 && format != OutputFormat::Multilabel)
+ {
+ outputPath = outputFilename;
+ auto name = GetSafeName(input);
+
+ if (name.empty())
+ name = "nameless_" + std::to_string(nonameCounter++);
+
+ outputPath.replace_filename(outputPath.stem().string() + '_' + name + outputPath.extension().string());
+ }
+
+ // Do the actual conversion from a contour set to an image with a background pixel value of 0.
+ // - For "binary" output, use pixel value 1 and unsigned char as pixel type.
+ // - For "label" output, use pixel value 1 and our label pixel type.
+ // - For "multilabel" output, use the next available label value instead.
+
+ const auto labelValue = labelSetImage.IsNotNull()
+ ? static_cast<mitk::Label::PixelType>(labelSetImage->GetTotalNumberOfLabels() + 1)
+ : 1;
+
+ auto filter = mitk::ContourModelSetToImageFilter::New();
+ filter->SetMakeOutputLabelPixelType(format != OutputFormat::Binary);
+ filter->SetPaintingPixelValue(labelValue);
+ filter->SetImage(referenceImage);
+ filter->SetInput(input);
+
+ filter->Update();
+
+ mitk::Image::Pointer image = filter->GetOutput();
+ filter = nullptr;
+
+ if (image.IsNull())
+ {
+ MITK_ERROR << "Contour set to image conversion failed without exception. Continue with next contour set... ";
+ returnValue = EXIT_FAILURE;
+ continue;
+ }
+
+ if (format == OutputFormat::Binary)
+ {
+ mitk::IOUtil::Save(image, outputPath.string());
+ }
+ else
+ {
+ if (labelSetImage.IsNull())
+ {
+ labelSetImage = mitk::LabelSetImage::New();
+ labelSetImage->Initialize(image);
+
+ CopyImageToActiveLayerImage(image, labelSetImage);
+ }
+ else
+ {
+ labelSetImage->AddLayer(image);
+ }
+
+ auto label = mitk::LabelSetImageHelper::CreateNewLabel(labelSetImage);
+ label->SetValue(labelValue);
+
+ SetLabelName(input, label);
+ SetLabelColor(input, label);
+
+ if (format == OutputFormat::Multilabel)
+ MITK_INFO << "Creating label: " << label->GetName() << " [" << labelValue << ']';
+
+ labelSetImage->GetActiveLabelSet()->AddLabel(label, false);
+
+ if (format == OutputFormat::Label)
+ {
+ mitk::IOUtil::Save(labelSetImage, outputPath.string());
+ labelSetImage = nullptr;
+ }
+ }
+ }
+
+ // In case of the "multilabel" output format, eventually save the single output file.
+ // For all other output formats, the output file(s) have been saved already while iterating
+ // over the inputs.
+
+ if (labelSetImage.IsNotNull())
+ mitk::IOUtil::Save(labelSetImage, outputPath.string());
+ }
+ catch (const mitk::Exception& e)
+ {
+ MITK_ERROR << e.GetDescription();
+ return EXIT_FAILURE;
+ }
+ catch (const std::exception& e)
+ {
+ MITK_ERROR << e.what();
+ return EXIT_FAILURE;
+ }
+ catch (...)
+ {
+ return EXIT_FAILURE;
+ }
+
+ return returnValue;
+}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.cpp b/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.cpp
index 15cb4647b8..e4968b6769 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.cpp
@@ -1,100 +1,122 @@
/*============================================================================
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 "QmitkEditableContourToolGUIBase.h"
+#include <QmitkEditableContourToolGUIBase.h>
+#include <ui_QmitkEditableContourToolGUIControls.h>
-QmitkEditableContourToolGUIBase::QmitkEditableContourToolGUIBase() : QmitkToolGUI()
+#include <QButtonGroup>
+
+#include <mitkEditableContourTool.h>
+
+QmitkEditableContourToolGUIBase::QmitkEditableContourToolGUIBase()
+ : QmitkToolGUI(),
+ m_Controls(new Ui::QmitkEditableContourToolGUIControls),
+ m_ModeButtonGroup(new QButtonGroup(this))
{
- m_Controls.setupUi(this);
- m_Controls.m_Information->hide();
- m_Controls.m_AutoCheck->setChecked(true);
- m_Controls.m_ConfirmButton->hide();
- m_Controls.m_AddMode->setChecked(true);
- m_Controls.m_SubtractMode->hide();
- m_Controls.m_AddMode->hide();
-
- m_Controls.m_ClearButton->hide();
-
- connect(m_Controls.m_ConfirmButton, SIGNAL(clicked()), this, SLOT(OnConfirmSegmentation()));
- connect(m_Controls.m_ClearButton, SIGNAL(clicked()), this, SLOT(OnClearContour()));
- connect(this, SIGNAL(NewToolAssociated(mitk::Tool *)), this, SLOT(OnNewToolAssociated(mitk::Tool *)));
- connect(m_Controls.m_InformationCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnShowInformation(bool)));
- connect(m_Controls.m_AutoCheck, SIGNAL(toggled(bool)), this, SLOT(OnAutoConfirm(bool)));
- connect(m_Controls.m_AddMode, SIGNAL(toggled(bool)), this, SLOT(OnAddModeToogled(bool)));
+ m_Controls->setupUi(this);
+
+ m_Controls->m_ConfirmButton->hide();
+ m_Controls->m_AddMode->hide();
+ m_Controls->m_SubtractMode->hide();
+ m_Controls->m_ClearButton->hide();
+ m_Controls->m_Information->hide();
+
+ m_ModeButtonGroup->addButton(m_Controls->m_AddMode, static_cast<int>(Mode::Add));
+ m_ModeButtonGroup->addButton(m_Controls->m_SubtractMode, static_cast<int>(Mode::Subtract));
+
+#if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
+ auto onModeToggled = [this](QAbstractButton* button) {
+ Mode mode = button == m_Controls->m_AddMode
+ ? Mode::Add
+ : Mode::Subtract;
+
+ this->OnModeToggled(mode);
+ };
+
+ connect(m_ModeButtonGroup, QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked), onModeToggled);
+#else
+ connect(m_ModeButtonGroup, &QButtonGroup::idClicked, [this](int id) { this->OnModeToggled(static_cast<Mode>(id)); });
+#endif
+
+ connect(this, &Self::NewToolAssociated, this, &Self::OnNewToolAssociated);
+ connect(m_Controls->m_AutoCheck, &QCheckBox::toggled, this, &Self::OnAutoConfirm);
+ connect(m_Controls->m_ConfirmButton, &QPushButton::clicked, this, &Self::OnConfirmSegmentation);
+ connect(m_Controls->m_ClearButton, &QPushButton::clicked, this, &Self::OnClearContour);
+ connect(m_Controls->m_InformationCheckBox, &QCheckBox::toggled, this, &Self::OnShowInformation);
}
QmitkEditableContourToolGUIBase::~QmitkEditableContourToolGUIBase()
{
}
-void QmitkEditableContourToolGUIBase::OnNewToolAssociated(mitk::Tool *tool)
+void QmitkEditableContourToolGUIBase::OnNewToolAssociated(mitk::Tool* tool)
{
- m_NewTool = dynamic_cast<mitk::EditableContourTool *>(tool);
+ m_NewTool = dynamic_cast<mitk::EditableContourTool*>(tool);
+
if (m_NewTool.IsNull())
- {
mitkThrow() << "Tool is in an invalid state. QmitkEditableContourToolGUIBase needs tools based on EditableContourTool.";
- }
const auto autoConfirm = m_NewTool->GetAutoConfirm();
- m_Controls.m_AutoCheck->setChecked(autoConfirm);
- const auto addMode = m_NewTool->GetAddMode();
- m_Controls.m_AddMode->setChecked(addMode);
+ m_Controls->m_AutoCheck->setChecked(autoConfirm);
+
+ const auto mode = m_NewTool->GetAddMode()
+ ? Mode::Add
+ : Mode::Subtract;
+
+ m_ModeButtonGroup->button(static_cast<int>(mode))->setChecked(true);
+
this->OnAutoConfirm(autoConfirm);
+ this->OnModeToggled(mode);
}
-void QmitkEditableContourToolGUIBase::OnConfirmSegmentation()
+void QmitkEditableContourToolGUIBase::OnAutoConfirm(bool on)
{
+ m_Controls->m_ConfirmButton->setVisible(!on);
+ m_Controls->m_ClearButton->setVisible(!on);
+ m_Controls->m_AddMode->setVisible(!on);
+ m_Controls->m_SubtractMode->setVisible(!on);
+
+ if (on)
+ m_Controls->m_AddMode->setChecked(true);
+
if (m_NewTool.IsNotNull())
{
- m_NewTool->ConfirmSegmentation();
+ if (on && m_NewTool->IsEditingContour())
+ this->OnConfirmSegmentation();
+
+ m_NewTool->SetAutoConfirm(on);
+ m_NewTool->SetAddMode(m_Controls->m_AddMode->isChecked());
}
}
-void QmitkEditableContourToolGUIBase::OnClearContour()
+void QmitkEditableContourToolGUIBase::OnModeToggled(Mode mode)
{
if (m_NewTool.IsNotNull())
- m_NewTool->ClearContour();
+ m_NewTool->SetAddMode(Mode::Add == mode);
}
-void QmitkEditableContourToolGUIBase::OnShowInformation(bool on)
+void QmitkEditableContourToolGUIBase::OnConfirmSegmentation()
{
- m_Controls.m_Information->setVisible(on);
+ if (m_NewTool.IsNotNull())
+ m_NewTool->ConfirmSegmentation();
}
-void QmitkEditableContourToolGUIBase::OnAutoConfirm(bool on)
+void QmitkEditableContourToolGUIBase::OnClearContour()
{
- m_Controls.m_ConfirmButton->setVisible(!on);
- m_Controls.m_ClearButton->setVisible(!on);
- m_Controls.m_AddMode->setVisible(!on);
- if (on)
- {
- m_Controls.m_AddMode->setChecked(true);
- }
- m_Controls.m_SubtractMode->setVisible(!on);
-
if (m_NewTool.IsNotNull())
- {
- if (on && m_NewTool->IsEditingContour())
- {
- this->OnConfirmSegmentation();
- }
- m_NewTool->SetAutoConfirm(on);
- }
+ m_NewTool->ClearContour();
}
-void QmitkEditableContourToolGUIBase::OnAddModeToogled(bool on)
+void QmitkEditableContourToolGUIBase::OnShowInformation(bool on)
{
- if (m_NewTool.IsNotNull())
- {
- m_NewTool->SetAddMode(on);
- }
+ m_Controls->m_Information->setVisible(on);
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.h b/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.h
index 28e89d4fb9..dac754e16e 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.h
+++ b/Modules/SegmentationUI/Qmitk/QmitkEditableContourToolGUIBase.h
@@ -1,59 +1,70 @@
/*============================================================================
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 QmitkEditableContourToolGUIBase_h
#define QmitkEditableContourToolGUIBase_h
-#include "QmitkToolGUI.h"
-#include "mitkEditableContourTool.h"
-#include "ui_QmitkEditableContourToolGUIControls.h"
+#include <QmitkToolGUI.h>
#include <MitkSegmentationUIExports.h>
-class QmitkEditableContourToolGUIBaseControls;
+class QButtonGroup;
+
+namespace mitk
+{
+ class EditableContourTool;
+}
+
+namespace Ui
+{
+ class QmitkEditableContourToolGUIControls;
+}
/**
\ingroup org_mitk_gui_qt_interactivesegmentation_internal
\brief GUI for mitk::EditableContourTool based classes.
\sa mitk::LassoTool
*/
class MITKSEGMENTATIONUI_EXPORT QmitkEditableContourToolGUIBase : public QmitkToolGUI
{
Q_OBJECT
public:
+ /// \cond
+ enum class MITKSEGMENTATIONUI_EXPORT Mode
+ {
+ Add,
+ Subtract
+ };
+ /// \endcond
+
mitkClassMacro(QmitkEditableContourToolGUIBase, QmitkToolGUI);
itkFactorylessNewMacro(Self);
- itkCloneMacro(Self);
-protected slots :
-
- void OnNewToolAssociated(mitk::Tool *);
+protected slots:
+ void OnNewToolAssociated(mitk::Tool*);
void OnConfirmSegmentation();
-
void OnClearContour();
-
void OnAutoConfirm(bool on);
- void OnAddModeToogled(bool on);
-
+ void OnModeToggled(Mode mode);
void OnShowInformation(bool on);
protected:
QmitkEditableContourToolGUIBase();
~QmitkEditableContourToolGUIBase() override;
- Ui::QmitkEditableContourToolGUIControls m_Controls;
-
- mitk::EditableContourTool::Pointer m_NewTool;
+ Ui::QmitkEditableContourToolGUIControls* m_Controls;
+ QButtonGroup* m_ModeButtonGroup;
+ itk::SmartPointer<mitk::EditableContourTool> m_NewTool;
};
#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.cpp b/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.cpp
new file mode 100644
index 0000000000..dc682cc594
--- /dev/null
+++ b/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.cpp
@@ -0,0 +1,247 @@
+/*============================================================================
+
+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 <QmitkFindSegmentationTaskDialog.h>
+#include <ui_QmitkFindSegmentationTaskDialog.h>
+
+#include <mitkCoreServices.h>
+#include <mitkIPreferencesService.h>
+#include <mitkIPreferences.h>
+
+namespace
+{
+ struct Preferences
+ {
+ std::vector<std::byte> geometry;
+ std::array<int, 7> columnWidths;
+ };
+
+ Preferences GetPreferences()
+ {
+ auto* node = mitk::CoreServices::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.views.segmentationtasklist");
+
+ Preferences prefs;
+
+ prefs.geometry = node->GetByteArray("QmitkFindSegmentationTaskDialog geometry", nullptr, 0);
+
+ for (size_t column = 0; column < prefs.columnWidths.size(); ++column)
+ prefs.columnWidths[column] = node->GetInt("QmitkFindSegmentationTaskDialog column width " + std::to_string(column), 125);
+
+ return prefs;
+ }
+
+ void SaveGeometry(const QByteArray& geometry)
+ {
+ auto* node = mitk::CoreServices::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.views.segmentationtasklist");
+ node->PutByteArray("QmitkFindSegmentationTaskDialog geometry", reinterpret_cast<const std::byte*>(geometry.data()), geometry.size());
+ }
+
+ void SaveColumnWidths(const QTableWidget* table)
+ {
+ auto* node = mitk::CoreServices::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.views.segmentationtasklist");
+ const int numberOfColumns = table->columnCount();
+
+ for (int column = 0; column < numberOfColumns; ++column)
+ node->PutInt("QmitkFindSegmentationTaskDialog column width " + std::to_string(column), table->columnWidth(column));
+ }
+}
+
+QmitkFindSegmentationTaskDialog::QmitkFindSegmentationTaskDialog(QWidget* parent)
+ : QDialog(parent),
+ m_Ui(new Ui::QmitkFindSegmentationTaskDialog)
+{
+ this->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
+
+ m_Ui->setupUi(this);
+
+ using Self = QmitkFindSegmentationTaskDialog;
+
+ connect(m_Ui->tableWidget, &QTableWidget::itemSelectionChanged, this, &Self::OnItemSelectionChanged);
+ connect(m_Ui->tableWidget, &QTableWidget::itemDoubleClicked, this, &Self::OnItemDoubleClicked);
+ connect(this, &Self::finished, this, &Self::OnFinished);
+
+ auto applyFilter = [this](const QString&) { this->ApplyFilter(); };
+
+ connect(m_Ui->noLineEdit, &QLineEdit::textChanged, this, applyFilter);
+ connect(m_Ui->nameLineEdit, &QLineEdit::textChanged, this, applyFilter);
+ connect(m_Ui->statusComboBox, &QComboBox::currentTextChanged, applyFilter);
+
+ auto prefs = GetPreferences();
+
+ if (!prefs.geometry.empty())
+ this->restoreGeometry(QByteArray(reinterpret_cast<const char*>(prefs.geometry.data()), prefs.geometry.size()));
+
+ for (int column = 0; column < static_cast<int>(prefs.columnWidths.size()); ++column)
+ m_Ui->tableWidget->setColumnWidth(column, prefs.columnWidths[column]);
+}
+
+QmitkFindSegmentationTaskDialog::~QmitkFindSegmentationTaskDialog()
+{
+ delete m_Ui;
+}
+
+void QmitkFindSegmentationTaskDialog::SetTaskList(const mitk::SegmentationTaskList* taskList)
+{
+ if (m_TaskList != taskList)
+ {
+ m_TaskList = taskList;
+
+ auto* table = m_Ui->tableWidget;
+ table->setSortingEnabled(false); // Do not sort while populating the table
+ table->reset();
+
+ if (m_TaskList.IsNotNull())
+ {
+ const int numberOfRows = static_cast<int>(m_TaskList->GetNumberOfTasks());
+ const int numberOfColumns = table->columnCount();
+
+ table->setRowCount(numberOfRows);
+
+ for (int row = 0; row < numberOfRows; ++row)
+ {
+ for (int column = 0; column < numberOfColumns; ++column)
+ {
+ auto* item = new QTableWidgetItem();
+ item->setData(Qt::UserRole, row);
+
+ switch (column)
+ {
+ case Column::Number:
+ item->setText(QString::number(row + 1));
+ break;
+
+ case Column::Name:
+ if (m_TaskList->HasName(row))
+ item->setText(QString::fromStdString(m_TaskList->GetName(row)));
+
+ break;
+
+ case Column::Status:
+ item->setText(m_TaskList->IsDone(row) ? "Done" : "Not done");
+ break;
+
+ case Column::Image:
+ if (m_TaskList->HasImage(row))
+ item->setText(QString::fromStdString(m_TaskList->GetImage(row).string()));
+
+ break;
+
+ case Column::Segmentation:
+ if (m_TaskList->HasSegmentation(row))
+ item->setText(QString::fromStdString(m_TaskList->GetSegmentation(row).string()));
+
+ break;
+
+ case Column::Result:
+ if (m_TaskList->HasResult(row))
+ item->setText(QString::fromStdString(m_TaskList->GetResult(row).string()));
+
+ break;
+
+ case Column::Description:
+ if (m_TaskList->HasDescription(row))
+ item->setText(QString::fromStdString(m_TaskList->GetDescription(row)));
+
+ break;
+ }
+
+ table->setItem(row, column, item);
+ }
+ }
+
+ table->setSortingEnabled(true); // Sort fully populated table
+ }
+ }
+}
+
+std::optional<size_t> QmitkFindSegmentationTaskDialog::GetSelectedTask() const
+{
+ return m_SelectedTask;
+}
+
+bool QmitkFindSegmentationTaskDialog::LoadSelectedTask() const
+{
+ return m_Ui->loadCheckBox->isChecked();
+}
+
+void QmitkFindSegmentationTaskDialog::OnItemSelectionChanged()
+{
+ auto selectedItems = m_Ui->tableWidget->selectedItems();
+
+ if (!selectedItems.empty())
+ {
+ m_SelectedTask = static_cast<size_t>(selectedItems.front()->data(Qt::UserRole).toInt());
+ }
+ else
+ {
+ m_SelectedTask.reset();
+ }
+}
+
+void QmitkFindSegmentationTaskDialog::OnItemDoubleClicked(QTableWidgetItem*)
+{
+ this->done(m_SelectedTask.has_value() ? QDialog::Accepted : QDialog::Rejected);
+}
+
+void QmitkFindSegmentationTaskDialog::OnFinished(int)
+{
+ SaveGeometry(this->saveGeometry());
+ SaveColumnWidths(m_Ui->tableWidget);
+}
+
+void QmitkFindSegmentationTaskDialog::ApplyFilter()
+{
+ auto* table = m_Ui->tableWidget;
+ const int numberOfRows = table->rowCount();
+ bool foundSomething = false;
+
+ for (int row = 0; row < numberOfRows; ++row)
+ {
+ if (!this->ContainsNumber(row) || !this->ContainsName(row) || !this->HasStatus(row))
+ {
+ table->hideRow(row);
+ continue;
+ }
+
+ table->showRow(row);
+
+ if (!foundSomething)
+ {
+ // Select the *first* finding to accelerate user interaction. For example, in a fresh dialog, typing
+ // '4', '2', '<Return>' will close the dialog and load task 42. In combination with the Ctrl+F shortcut
+ // for this dialog, no mouse interaction is necessary at all to jump to specific tasks.
+ table->selectRow(row);
+ foundSomething = true;
+ }
+ }
+
+ if (!foundSomething)
+ table->clearSelection(); // Hidden rows do not automatically lose selection
+}
+
+bool QmitkFindSegmentationTaskDialog::ContainsNumber(int row) const
+{
+ auto numberText = m_Ui->noLineEdit->text().trimmed();
+ return numberText.isEmpty() || m_Ui->tableWidget->item(row, Column::Number)->text().contains(numberText);
+}
+
+bool QmitkFindSegmentationTaskDialog::ContainsName(int row) const
+{
+ auto name = m_Ui->nameLineEdit->text().trimmed();
+ return name.isEmpty() || m_Ui->tableWidget->item(row, Column::Name)->text().contains(name, Qt::CaseInsensitive);
+}
+
+bool QmitkFindSegmentationTaskDialog::HasStatus(int row) const
+{
+ auto status = m_Ui->statusComboBox->currentText();
+ return status.isEmpty() || status == QStringLiteral("All") || m_Ui->tableWidget->item(row, Column::Status)->text() == status;
+}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.h b/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.h
new file mode 100644
index 0000000000..331a1a31ff
--- /dev/null
+++ b/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.h
@@ -0,0 +1,64 @@
+/*============================================================================
+
+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 QmitkFindSegmentationTaskDialog_h
+#define QmitkFindSegmentationTaskDialog_h
+
+#include <QDialog>
+#include <mitkSegmentationTaskList.h>
+
+class QTableWidgetItem;
+
+namespace Ui
+{
+ class QmitkFindSegmentationTaskDialog;
+}
+
+class QmitkFindSegmentationTaskDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit QmitkFindSegmentationTaskDialog(QWidget* parent = nullptr);
+ ~QmitkFindSegmentationTaskDialog() override;
+
+ void SetTaskList(const mitk::SegmentationTaskList* taskList);
+ std::optional<size_t> GetSelectedTask() const;
+ bool LoadSelectedTask() const;
+
+private:
+ enum Column
+ {
+ Number,
+ Name,
+ Status,
+ Image,
+ Segmentation,
+ Result,
+ Description
+ };
+
+ void OnItemSelectionChanged();
+ void OnItemDoubleClicked(QTableWidgetItem* item);
+ void OnFinished(int result);
+
+ void ApplyFilter();
+ bool ContainsNumber(int row) const;
+ bool ContainsName(int row) const;
+ bool HasStatus(int row) const;
+
+ Ui::QmitkFindSegmentationTaskDialog* m_Ui;
+ mitk::SegmentationTaskList::ConstPointer m_TaskList;
+ std::optional<size_t> m_SelectedTask;
+};
+
+#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.ui b/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.ui
new file mode 100644
index 0000000000..0ccaa4e109
--- /dev/null
+++ b/Modules/SegmentationUI/Qmitk/QmitkFindSegmentationTaskDialog.ui
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QmitkFindSegmentationTaskDialog</class>
+ <widget class="QDialog" name="QmitkFindSegmentationTaskDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1024</width>
+ <height>768</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Find Segmentation Task</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="noLabel">
+ <property name="text">
+ <string>#:</string>
+ </property>
+ <property name="buddy">
+ <cstring>noLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="noLineEdit">
+ <property name="clearButtonEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="nameLabel">
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ <property name="buddy">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="nameLineEdit">
+ <property name="clearButtonEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="statusLabel">
+ <property name="text">
+ <string>Status:</string>
+ </property>
+ <property name="buddy">
+ <cstring>statusComboBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="statusComboBox">
+ <item>
+ <property name="text">
+ <string>All</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Not done</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Done</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTableWidget" name="tableWidget">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <attribute name="horizontalHeaderDefaultSectionSize">
+ <number>125</number>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ <column>
+ <property name="text">
+ <string>#</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Status</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Image</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Segmentation</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Result</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Description</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QCheckBox" name="loadCheckBox">
+ <property name="text">
+ <string>Load selected task</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>noLineEdit</tabstop>
+ <tabstop>nameLineEdit</tabstop>
+ <tabstop>statusComboBox</tabstop>
+ <tabstop>tableWidget</tabstop>
+ <tabstop>loadCheckBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>QmitkFindSegmentationTaskDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>QmitkFindSegmentationTaskDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp
index 1b20855f43..6311220ef5 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp
@@ -1,1129 +1,1131 @@
/*============================================================================
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 <QmitkMultiLabelInspector.h>
// mitk
#include <mitkRenderingManager.h>
#include <mitkLabelSetImageHelper.h>
#include <mitkDICOMSegmentationPropertyHelper.h>
// Qmitk
#include <QmitkMultiLabelTreeModel.h>
#include <QmitkLabelColorItemDelegate.h>
#include <QmitkLabelToggleItemDelegate.h>
#include <QmitkStyleManager.h>
// Qt
#include <QMenu>
#include <QLabel>
#include <QWidgetAction>
#include <QMessageBox>
#include <ui_QmitkMultiLabelInspectorControls.h>
QmitkMultiLabelInspector::QmitkMultiLabelInspector(QWidget* parent/* = nullptr*/)
: QWidget(parent), m_Controls(new Ui::QmitkMultiLabelInspector)
{
m_Controls->setupUi(this);
m_Model = new QmitkMultiLabelTreeModel(this);
m_Controls->view->setModel(m_Model);
m_ColorItemDelegate = new QmitkLabelColorItemDelegate(this);
auto visibleIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg"));
auto invisibleIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/invisible.svg"));
m_VisibilityItemDelegate = new QmitkLabelToggleItemDelegate(visibleIcon, invisibleIcon, this);
auto lockIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/lock.svg"));
auto unlockIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/unlock.svg"));
m_LockItemDelegate = new QmitkLabelToggleItemDelegate(lockIcon, unlockIcon, this);
auto* view = this->m_Controls->view;
view->setItemDelegateForColumn(1, m_LockItemDelegate);
view->setItemDelegateForColumn(2, m_ColorItemDelegate);
view->setItemDelegateForColumn(3, m_VisibilityItemDelegate);
auto* header = view->header();
header->setSectionResizeMode(0,QHeaderView::Stretch);
header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
header->setSectionResizeMode(2, QHeaderView::ResizeToContents);
header->setSectionResizeMode(3, QHeaderView::ResizeToContents);
view->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_Model, &QAbstractItemModel::modelReset, this, &QmitkMultiLabelInspector::OnModelReset);
connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), SLOT(OnChangeModelSelection(const QItemSelection&, const QItemSelection&)));
connect(view, &QAbstractItemView::customContextMenuRequested, this, &QmitkMultiLabelInspector::OnContextMenuRequested);
connect(view, &QAbstractItemView::doubleClicked, this, &QmitkMultiLabelInspector::OnItemDoubleClicked);
}
QmitkMultiLabelInspector::~QmitkMultiLabelInspector()
{
delete m_Controls;
}
void QmitkMultiLabelInspector::Initialize()
{
m_LastValidSelectedLabels = {};
m_ModelManipulationOngoing = false;
m_Model->SetSegmentation(m_Segmentation);
m_Controls->view->expandAll();
m_LastValidSelectedLabels = {};
//in singel selection mode, if at least one label exist select the first label of the mode.
if (m_Segmentation.IsNotNull() && !this->GetMultiSelectionMode() && m_Segmentation->GetTotalNumberOfLabels() > 0)
{
auto firstIndex = m_Model->FirstLabelInstanceIndex(QModelIndex());
auto labelVariant = firstIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
if (labelVariant.isValid())
{
this->SetSelectedLabel(labelVariant.value<LabelValueType>());
m_Controls->view->selectionModel()->setCurrentIndex(firstIndex, QItemSelectionModel::NoUpdate);
}
}
}
void QmitkMultiLabelInspector::SetMultiSelectionMode(bool multiMode)
{
m_Controls->view->setSelectionMode(multiMode
? QAbstractItemView::SelectionMode::MultiSelection
: QAbstractItemView::SelectionMode::SingleSelection);
}
bool QmitkMultiLabelInspector::GetMultiSelectionMode() const
{
return QAbstractItemView::SelectionMode::MultiSelection == m_Controls->view->selectionMode();
}
void QmitkMultiLabelInspector::SetAllowVisibilityModification(bool visibilityMod)
{
m_AllowVisibilityModification = visibilityMod;
this->m_Model->SetAllowVisibilityModification(visibilityMod);
}
void QmitkMultiLabelInspector::SetAllowLabelModification(bool labelMod)
{
m_AllowLabelModification = labelMod;
}
bool QmitkMultiLabelInspector::GetAllowVisibilityModification() const
{
return m_AllowVisibilityModification;
}
void QmitkMultiLabelInspector::SetAllowLockModification(bool lockMod)
{
m_AllowLockModification = lockMod;
this->m_Model->SetAllowLockModification(lockMod);
}
bool QmitkMultiLabelInspector::GetAllowLockModification() const
{
return m_AllowLockModification;
}
bool QmitkMultiLabelInspector::GetAllowLabelModification() const
{
return m_AllowLabelModification;
}
void QmitkMultiLabelInspector::SetDefaultLabelNaming(bool defaultLabelNaming)
{
m_DefaultLabelNaming = defaultLabelNaming;
}
void QmitkMultiLabelInspector::SetMultiLabelSegmentation(mitk::LabelSetImage* segmentation)
{
if (segmentation != m_Segmentation)
{
m_Segmentation = segmentation;
this->Initialize();
}
}
bool QmitkMultiLabelInspector::GetModelManipulationOngoing() const
{
return m_ModelManipulationOngoing;
}
void QmitkMultiLabelInspector::OnModelReset()
{
m_LastValidSelectedLabels = {};
m_ModelManipulationOngoing = false;
}
bool EqualLabelSelections(const QmitkMultiLabelInspector::LabelValueVectorType& selection1, const QmitkMultiLabelInspector::LabelValueVectorType& selection2)
{
if (selection1.size() == selection2.size())
{
// lambda to compare node pointer inside both lists
return std::is_permutation(selection1.begin(), selection1.end(), selection2.begin());
}
return false;
}
void QmitkMultiLabelInspector::SetSelectedLabels(const LabelValueVectorType& selectedLabels)
{
if (EqualLabelSelections(this->GetSelectedLabels(), selectedLabels))
{
return;
}
this->UpdateSelectionModel(selectedLabels);
m_LastValidSelectedLabels = selectedLabels;
}
void QmitkMultiLabelInspector::UpdateSelectionModel(const LabelValueVectorType& selectedLabels)
{
// create new selection by retrieving the corresponding indices of the labels
QItemSelection newCurrentSelection;
for (const auto& labelID : selectedLabels)
{
QModelIndexList matched = m_Model->match(m_Model->index(0, 0), QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole, QVariant(labelID), 1, Qt::MatchRecursive);
if (!matched.empty())
{
newCurrentSelection.select(matched.front(), matched.front());
}
}
m_Controls->view->selectionModel()->select(newCurrentSelection, QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Current);
}
void QmitkMultiLabelInspector::SetSelectedLabel(mitk::LabelSetImage::LabelValueType selectedLabel)
{
this->SetSelectedLabels({ selectedLabel });
}
QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetSelectedLabelsFromSelectionModel() const
{
LabelValueVectorType result;
QModelIndexList selectedIndexes = m_Controls->view->selectionModel()->selectedIndexes();
for (const auto& index : qAsConst(selectedIndexes))
{
QVariant qvariantDataNode = m_Model->data(index, QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
if (qvariantDataNode.canConvert<mitk::LabelSetImage::LabelValueType>())
{
result.push_back(qvariantDataNode.value<mitk::LabelSetImage::LabelValueType>());
}
}
return result;
}
QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetSelectedLabels() const
{
return m_LastValidSelectedLabels;
}
mitk::Label* QmitkMultiLabelInspector::GetFirstSelectedLabelObject() const
{
if (m_LastValidSelectedLabels.empty() || m_Segmentation.IsNull())
return nullptr;
return m_Segmentation->GetLabel(m_LastValidSelectedLabels.front());
}
void QmitkMultiLabelInspector::OnChangeModelSelection(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/)
{
if (!m_ModelManipulationOngoing)
{
auto internalSelection = GetSelectedLabelsFromSelectionModel();
if (internalSelection.empty())
{
//empty selections are not allowed by UI interactions, there should always be at least on label selected.
//but selections are e.g. also cleared if the model is updated (e.g. due to addition of labels)
UpdateSelectionModel(m_LastValidSelectedLabels);
}
else
{
m_LastValidSelectedLabels = internalSelection;
emit CurrentSelectionChanged(GetSelectedLabels());
}
}
}
void QmitkMultiLabelInspector::WaitCursorOn() const
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
}
void QmitkMultiLabelInspector::WaitCursorOff() const
{
this->RestoreOverrideCursor();
}
void QmitkMultiLabelInspector::RestoreOverrideCursor() const
{
QApplication::restoreOverrideCursor();
}
mitk::Label* QmitkMultiLabelInspector::GetCurrentLabel() const
{
auto currentIndex = this->m_Controls->view->currentIndex();
auto labelVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelDataRole);
mitk::Label::Pointer currentIndexLabel = nullptr;
if (labelVariant.isValid())
{
auto uncastedLabel = labelVariant.value<void*>();
currentIndexLabel = static_cast<mitk::Label*>(uncastedLabel);
}
return currentIndexLabel;
}
QmitkMultiLabelInspector::IndexLevelType QmitkMultiLabelInspector::GetCurrentLevelType() const
{
auto currentIndex = this->m_Controls->view->currentIndex();
auto labelInstanceVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceDataRole);
auto labelVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelDataRole);
if (labelInstanceVariant.isValid() )
{
return IndexLevelType::LabelInstance;
}
else if (labelVariant.isValid())
{
return IndexLevelType::LabelClass;
}
return IndexLevelType::Group;
}
QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetCurrentlyAffactedLabelInstances() const
{
auto currentIndex = m_Controls->view->currentIndex();
return m_Model->GetLabelsInSubTree(currentIndex);
}
QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetLabelInstancesOfSelectedFirstLabel() const
{
if (m_Segmentation.IsNull())
return {};
if (this->GetSelectedLabels().empty())
return {};
const auto index = m_Model->indexOfLabel(this->GetSelectedLabels().front());
return m_Model->GetLabelInstancesOfSameLabelClass(index);
}
mitk::Label* QmitkMultiLabelInspector::AddNewLabelInstanceInternal(mitk::Label* templateLabel)
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of AddNewLabelInstance.";
if (nullptr == templateLabel)
mitkThrow() << "QmitkMultiLabelInspector is in an invalid state. AddNewLabelInstanceInternal was called with a non existing label as template";
auto groupID = m_Segmentation->GetGroupIndexOfLabel(templateLabel->GetValue());
auto group = m_Segmentation->GetLabelSet(groupID);
m_ModelManipulationOngoing = true;
auto newLabel = group->AddLabel(templateLabel, true);
m_ModelManipulationOngoing = false;
this->SetSelectedLabel(newLabel->GetValue());
auto index = m_Model->indexOfLabel(newLabel->GetValue());
if (index.isValid())
{
m_Controls->view->expand(index.parent());
}
else
{
mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the model after adding it to the segmentation. Label value: " << newLabel->GetValue();
}
emit ModelUpdated();
return newLabel;
}
mitk::Label* QmitkMultiLabelInspector::AddNewLabelInstance()
{
auto currentLabel = this->GetFirstSelectedLabelObject();
if (nullptr == currentLabel)
return nullptr;
return this->AddNewLabelInstanceInternal(currentLabel);
}
mitk::Label* QmitkMultiLabelInspector::AddNewLabelInternal(const mitk::LabelSetImage::GroupIndexType& containingGroup)
{
auto newLabel = mitk::LabelSetImageHelper::CreateNewLabel(m_Segmentation);
if (!m_DefaultLabelNaming)
emit LabelRenameRequested(newLabel, false);
auto group = m_Segmentation->GetLabelSet(containingGroup);
m_ModelManipulationOngoing = true;
group->AddLabel(newLabel, false);
m_ModelManipulationOngoing = false;
this->SetSelectedLabel(newLabel->GetValue());
auto index = m_Model->indexOfLabel(newLabel->GetValue());
if (!index.isValid())
mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the "
"model after adding it to the segmentation. Label value: " << newLabel->GetValue();
m_Controls->view->expand(index.parent());
emit ModelUpdated();
return newLabel;
}
mitk::Label* QmitkMultiLabelInspector::AddNewLabel()
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of AddNewLabel.";
if (m_Segmentation.IsNull())
{
return nullptr;
}
auto currentLabel = this->GetFirstSelectedLabelObject();
mitk::LabelSetImage::GroupIndexType groupID = nullptr != currentLabel
? m_Segmentation->GetGroupIndexOfLabel(currentLabel->GetValue())
: 0;
return AddNewLabelInternal(groupID);
}
void QmitkMultiLabelInspector::DeleteLabelInstance()
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of DeleteLabelInstance.";
if (m_Segmentation.IsNull())
return;
auto label = this->GetFirstSelectedLabelObject();
if (nullptr == label)
return;
auto index = m_Model->indexOfLabel(label->GetValue());
auto instanceName = index.data(Qt::DisplayRole);
auto question = "Do you really want to delete label instance \"" + instanceName.toString() + "\"?";
auto answer = QMessageBox::question(this, QString("Delete label instances"), question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answer == QMessageBox::Yes)
this->DeleteLabelInternal({ label->GetValue() });
}
void QmitkMultiLabelInspector::DeleteLabel()
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of DeleteLabel.";
if (m_Segmentation.IsNull())
return;
const auto label = this->GetFirstSelectedLabelObject();
if (nullptr == label)
return;
const auto relevantLabels = this->GetLabelInstancesOfSelectedFirstLabel();
if (relevantLabels.empty())
return;
auto question = "Do you really want to delete label \"" + QString::fromStdString(label->GetName());
question = relevantLabels.size()==1 ? question + "\"?" : question + "\" with all "+QString::number(relevantLabels.size()) +" instances?";
auto answer = QMessageBox::question(this, QString("Delete label"), question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answer == QMessageBox::Yes)
this->DeleteLabelInternal(relevantLabels);
}
void QmitkMultiLabelInspector::DeleteLabelInternal(const LabelValueVectorType& labelValues)
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of DeleteLabelInternal.";
if (m_Segmentation.IsNull())
{
return;
}
QVariant nextLabelVariant;
this->WaitCursorOn();
m_ModelManipulationOngoing = true;
for (auto labelValue : labelValues)
{
if (labelValue == labelValues.back())
{
auto currentIndex = m_Model->indexOfLabel(labelValue);
auto nextIndex = m_Model->ClosestLabelInstanceIndex(currentIndex);
nextLabelVariant = nextIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
}
m_Segmentation->RemoveLabel(labelValue);
}
m_ModelManipulationOngoing = false;
this->WaitCursorOff();
if (nextLabelVariant.isValid())
{
auto newLabelValue = nextLabelVariant.value<LabelValueType>();
this->SetSelectedLabel(newLabelValue);
auto index = m_Model->indexOfLabel(newLabelValue); //we have to get index again, because it could have changed due to remove operation.
if (index.isValid())
{
m_Controls->view->expand(index.parent());
}
else
{
mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the model after adding it to the segmentation. Label value: " << newLabelValue;
}
}
else
{
this->SetSelectedLabels({});
}
emit ModelUpdated();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
mitk::Label* QmitkMultiLabelInspector::AddNewGroup()
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of AddNewLabel.";
if (m_Segmentation.IsNull())
{
return nullptr;
}
mitk::LabelSetImage::GroupIndexType groupID = 0;
mitk::Label* newLabel = nullptr;
m_ModelManipulationOngoing = true;
try
{
this->WaitCursorOn();
groupID = m_Segmentation->AddLayer();
this->WaitCursorOff();
newLabel = this->AddNewLabelInternal(groupID);
}
catch (mitk::Exception& e)
{
this->WaitCursorOff();
m_ModelManipulationOngoing = false;
MITK_ERROR << "Exception caught: " << e.GetDescription();
QMessageBox::information(this, "Add group", "Could not add a new group. See error log for details.");
}
m_ModelManipulationOngoing = false;
emit ModelUpdated();
return newLabel;
}
void QmitkMultiLabelInspector::RemoveGroupInternal(const mitk::LabelSetImage::GroupIndexType& groupID)
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
if (m_Segmentation.IsNull())
return;
if (m_Segmentation->GetNumberOfLayers() < 2)
return;
auto currentIndex = m_Model->indexOfGroup(groupID);
auto nextIndex = m_Model->ClosestLabelInstanceIndex(currentIndex);
auto labelVariant = nextIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
try
{
this->WaitCursorOn();
m_ModelManipulationOngoing = true;
m_Segmentation->RemoveGroup(groupID);
m_ModelManipulationOngoing = false;
this->WaitCursorOff();
}
catch (mitk::Exception& e)
{
m_ModelManipulationOngoing = false;
this->WaitCursorOff();
MITK_ERROR << "Exception caught: " << e.GetDescription();
QMessageBox::information(this, "Delete group", "Could not delete the currently active group. See error log for details.");
return;
}
if (labelVariant.isValid())
{
auto newLabelValue = labelVariant.value<LabelValueType>();
this->SetSelectedLabel(newLabelValue);
auto index = m_Model->indexOfLabel(newLabelValue); //we have to get index again, because it could have changed due to remove operation.
if (index.isValid())
{
m_Controls->view->expand(index.parent());
}
else
{
mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the model after adding it to the segmentation. Label value: " << newLabelValue;
}
}
emit ModelUpdated();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkMultiLabelInspector::RemoveGroup()
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
if (m_Segmentation.IsNull())
return;
if (m_Segmentation->GetNumberOfLayers() < 2)
{
QMessageBox::information(this, "Delete group", "Cannot delete last remaining group. A segmentation must contain at least a single group.");
return;
}
auto question = QStringLiteral("Do you really want to delete the group of the selected label with all labels?");
auto answer = QMessageBox::question(this, "Delete group", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answer != QMessageBox::Yes)
return;
auto selectedLabel = this->GetFirstSelectedLabelObject();
const auto group = m_Segmentation->GetGroupIndexOfLabel(selectedLabel->GetValue());
this->RemoveGroupInternal(group);
}
void QmitkMultiLabelInspector::OnDeleteGroup()
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
if (m_Segmentation.IsNull())
return;
auto currentIndex = this->m_Controls->view->currentIndex();
auto groupIDVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::GroupIDRole);
if (groupIDVariant.isValid())
{
auto groupID = groupIDVariant.value<mitk::LabelSetImage::GroupIndexType>();
auto question = QStringLiteral("Do you really want to delete the current group with all labels?");
auto answer = QMessageBox::question(this, QString("Delete group %1").arg(groupID), question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answer != QMessageBox::Yes)
return;
this->RemoveGroupInternal(groupID);
}
};
void QmitkMultiLabelInspector::OnContextMenuRequested(const QPoint& /*pos*/)
{
if (m_Segmentation.IsNull() || !this->isEnabled())
return;
const auto indexLevel = this->GetCurrentLevelType();
if (IndexLevelType::Group == indexLevel)
{
QMenu* menu = new QMenu(this);
if (m_AllowLabelModification)
{
QAction* addInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add.svg")), "&Add label", this);
QObject::connect(addInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnAddLabel);
menu->addAction(addInstanceAction);
if (m_Segmentation->GetNumberOfLayers() > 1)
{
QAction* removeAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_group_delete.svg")), "Delete group", this);
QObject::connect(removeAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnDeleteGroup);
menu->addAction(removeAction);
}
}
if (m_AllowLockModification)
{
menu->addSeparator();
QAction* lockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/lock.svg")), "Lock group", this);
QObject::connect(lockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnLockAffectedLabels);
menu->addAction(lockAllAction);
QAction* unlockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/unlock.svg")), "Unlock group", this);
QObject::connect(unlockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnUnlockAffectedLabels);
menu->addAction(unlockAllAction);
}
if (m_AllowVisibilityModification)
{
menu->addSeparator();
- QAction* viewAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "View group", this);
+ QAction* viewAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Show group", this);
QObject::connect(viewAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsVisible);
menu->addAction(viewAllAction);
QAction* hideAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/invisible.svg")), "Hide group", this);
QObject::connect(hideAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsInvisible);
menu->addAction(hideAllAction);
menu->addSeparator();
auto opacityAction = this->CreateOpacityAction();
if (nullptr != opacityAction)
menu->addAction(opacityAction);
}
menu->popup(QCursor::pos());
}
else if (IndexLevelType::LabelClass == indexLevel)
{
QMenu* menu = new QMenu(this);
if (m_AllowLabelModification)
{
QAction* addInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add_instance.svg")), "Add label instance", this);
QObject::connect(addInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnAddLabelInstance);
menu->addAction(addInstanceAction);
- QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename label class", this);
+ QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename label", this);
QObject::connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(OnRenameLabel(bool)));
menu->addAction(renameAction);
- QAction* removeAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete.svg")), "&Delete label class", this);
+ QAction* removeAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete.svg")), "&Delete label", this);
QObject::connect(removeAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnDeleteAffectedLabel);
menu->addAction(removeAction);
}
if (m_AllowLockModification)
{
menu->addSeparator();
QAction* lockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/lock.svg")), "Lock label instances", this);
QObject::connect(lockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnLockAffectedLabels);
menu->addAction(lockAllAction);
QAction* unlockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/unlock.svg")), "Unlock label instances", this);
QObject::connect(unlockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnUnlockAffectedLabels);
menu->addAction(unlockAllAction);
}
if (m_AllowVisibilityModification)
{
menu->addSeparator();
- QAction* viewAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "View label instances", this);
+ QAction* viewAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Show label instances", this);
QObject::connect(viewAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsVisible);
menu->addAction(viewAllAction);
QAction* hideAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/invisible.svg")), "Hide label instances", this);
QObject::connect(hideAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsInvisible);
menu->addAction(hideAllAction);
- QAction* viewOnlyAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "View only", this);
- QObject::connect(viewOnlyAction, SIGNAL(triggered(bool)), this, SLOT(OnSetOnlyActiveLabelVisible(bool)));
- menu->addAction(viewOnlyAction);
-
menu->addSeparator();
auto opacityAction = this->CreateOpacityAction();
if (nullptr!=opacityAction)
menu->addAction(opacityAction);
}
menu->popup(QCursor::pos());
}
else
{
auto selectedLabelValues = this->GetSelectedLabels();
if (selectedLabelValues.empty())
return;
QMenu* menu = new QMenu(this);
if (this->GetMultiSelectionMode() && selectedLabelValues.size() > 1)
{
QAction* mergeAction = new QAction(QIcon(":/Qmitk/MergeLabels.png"), "Merge selection on current label", this);
QObject::connect(mergeAction, SIGNAL(triggered(bool)), this, SLOT(OnMergeLabels(bool)));
menu->addAction(mergeAction);
QAction* removeLabelsAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete_instance.svg")), "&Delete selected labels", this);
QObject::connect(removeLabelsAction, SIGNAL(triggered(bool)), this, SLOT(OnDeleteLabels(bool)));
menu->addAction(removeLabelsAction);
QAction* clearLabelsAction = new QAction(QIcon(":/Qmitk/EraseLabel.png"), "&Clear selected labels", this);
QObject::connect(clearLabelsAction, SIGNAL(triggered(bool)), this, SLOT(OnClearLabels(bool)));
menu->addAction(clearLabelsAction);
}
else
{
if (m_AllowLabelModification)
{
- QAction* addInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add_instance.svg")), "&Add label instance...", this);
+ QAction* addInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add_instance.svg")), "&Add label instance", this);
QObject::connect(addInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnAddLabelInstance);
menu->addAction(addInstanceAction);
- QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename", this);
- QObject::connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(OnRenameLabel(bool)));
- menu->addAction(renameAction);
-
const auto selectedLabelIndex = m_Model->indexOfLabel(selectedLabelValues.front());
if (m_Model->GetLabelInstancesOfSameLabelClass(selectedLabelIndex).size() > 1) // Only labels that actually appear as instance (having additional instances)
{
+ QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename label instance", this);
+ QObject::connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(OnRenameLabel(bool)));
+ menu->addAction(renameAction);
+
QAction* removeInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete_instance.svg")), "&Delete label instance", this);
QObject::connect(removeInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::DeleteLabelInstance);
menu->addAction(removeInstanceAction);
}
+ else
+ {
+ QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename label", this);
+ QObject::connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(OnRenameLabel(bool)));
+ menu->addAction(renameAction);
+ }
- QAction* removeLabelAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete.svg")), "Delete &label class", this);
+ QAction* removeLabelAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete.svg")), "Delete &label", this);
QObject::connect(removeLabelAction, &QAction::triggered, this, &QmitkMultiLabelInspector::DeleteLabel);
menu->addAction(removeLabelAction);
QAction* clearAction = new QAction(QIcon(":/Qmitk/EraseLabel.png"), "&Clear content", this);
QObject::connect(clearAction, SIGNAL(triggered(bool)), this, SLOT(OnClearLabel(bool)));
menu->addAction(clearAction);
}
if (m_AllowVisibilityModification)
{
menu->addSeparator();
- QAction* viewOnlyAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Hide everything but this", this);
+ QAction* viewOnlyAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Hide everything in group but this", this);
QObject::connect(viewOnlyAction, SIGNAL(triggered(bool)), this, SLOT(OnSetOnlyActiveLabelVisible(bool)));
menu->addAction(viewOnlyAction);
menu->addSeparator();
auto opacityAction = this->CreateOpacityAction();
if (nullptr != opacityAction)
menu->addAction(opacityAction);
}
}
menu->popup(QCursor::pos());
}
}
QWidgetAction* QmitkMultiLabelInspector::CreateOpacityAction()
{
auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
std::vector<mitk::Label*> relevantLabels;
if (!relevantLabelValues.empty())
{
//we assume here that all affacted label belong to one group.
auto groupID = m_Segmentation->GetGroupIndexOfLabel(relevantLabelValues.front());
auto group = m_Segmentation->GetLabelSet(groupID);
for (auto value : relevantLabelValues)
{
auto label = this->m_Segmentation->GetLabel(value);
if (nullptr == label)
mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
relevantLabels.emplace_back(label);
}
auto* opacitySlider = new QSlider;
opacitySlider->setMinimum(0);
opacitySlider->setMaximum(100);
opacitySlider->setOrientation(Qt::Horizontal);
auto opacity = relevantLabels.front()->GetOpacity();
opacitySlider->setValue(static_cast<int>(opacity * 100));
auto segmentation = m_Segmentation;
QObject::connect(opacitySlider, &QSlider::valueChanged, this, [segmentation, relevantLabels, group](const int value)
{
auto opacity = static_cast<float>(value) / 100.0f;
for (auto label : relevantLabels)
{
label->SetOpacity(opacity);
group->UpdateLookupTable(label->GetValue());
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
);
QLabel* opacityLabel = new QLabel("Opacity: ");
QVBoxLayout* opacityWidgetLayout = new QVBoxLayout;
opacityWidgetLayout->setContentsMargins(4, 4, 4, 4);
opacityWidgetLayout->addWidget(opacityLabel);
opacityWidgetLayout->addWidget(opacitySlider);
QWidget* opacityWidget = new QWidget;
opacityWidget->setLayout(opacityWidgetLayout);
QWidgetAction* opacityAction = new QWidgetAction(this);
opacityAction->setDefaultWidget(opacityWidget);
return opacityAction;
}
return nullptr;
}
void QmitkMultiLabelInspector::OnClearLabels(bool /*value*/)
{
QString question = "Do you really want to clear the selected labels?";
QMessageBox::StandardButton answerButton = QMessageBox::question(
this, "Clear selected labels", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answerButton == QMessageBox::Yes)
{
this->WaitCursorOn();
m_Segmentation->EraseLabels(this->GetSelectedLabels());
this->WaitCursorOff();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkMultiLabelInspector::OnDeleteAffectedLabel()
{
if (!m_AllowLabelModification)
mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
if (m_Segmentation.IsNull())
{
return;
}
auto affectedLabels = GetCurrentlyAffactedLabelInstances();
auto currentLabel = m_Segmentation->GetLabel(affectedLabels.front());
- QString question = "Do you really want to delete all label instances of class \"" + QString::fromStdString(currentLabel->GetName()) + "\"?";
+ QString question = "Do you really want to delete all instances of label \"" + QString::fromStdString(currentLabel->GetName()) + "\"?";
QMessageBox::StandardButton answerButton =
- QMessageBox::question(this, "Delete label class", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
+ QMessageBox::question(this, "Delete label", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answerButton == QMessageBox::Yes)
{
this->DeleteLabelInternal(affectedLabels);
}
}
void QmitkMultiLabelInspector::OnDeleteLabels(bool /*value*/)
{
QString question = "Do you really want to remove the selected labels?";
QMessageBox::StandardButton answerButton = QMessageBox::question(
this, "Remove selected labels", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answerButton == QMessageBox::Yes)
{
this->WaitCursorOn();
m_Segmentation->RemoveLabels(this->GetSelectedLabels());
this->WaitCursorOff();
}
}
void QmitkMultiLabelInspector::OnMergeLabels(bool /*value*/)
{
auto currentLabel = GetCurrentLabel();
QString question = "Do you really want to merge selected labels into \"" + QString::fromStdString(currentLabel->GetName())+"\"?";
QMessageBox::StandardButton answerButton = QMessageBox::question(
this, "Merge selected label", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answerButton == QMessageBox::Yes)
{
this->WaitCursorOn();
m_Segmentation->MergeLabels(currentLabel->GetValue(), this->GetSelectedLabels(), m_Segmentation->GetActiveLayer());
this->WaitCursorOff();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkMultiLabelInspector::OnAddLabel()
{
auto currentIndex = this->m_Controls->view->currentIndex();
auto groupIDVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::GroupIDRole);
if (groupIDVariant.isValid())
{
auto groupID = groupIDVariant.value<mitk::LabelSetImage::GroupIndexType>();
this->AddNewLabelInternal(groupID);
}
}
void QmitkMultiLabelInspector::OnAddLabelInstance()
{
auto currentLabel = this->GetCurrentLabel();
if (nullptr == currentLabel)
return;
this->AddNewLabelInstanceInternal(currentLabel);
}
void QmitkMultiLabelInspector::OnClearLabel(bool /*value*/)
{
auto currentLabel = GetFirstSelectedLabelObject();
QString question = "Do you really want to clear the contents of label \"" + QString::fromStdString(currentLabel->GetName())+"\"?";
QMessageBox::StandardButton answerButton =
QMessageBox::question(this, "Clear label", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
if (answerButton == QMessageBox::Yes)
{
this->WaitCursorOn();
m_Segmentation->EraseLabel(currentLabel->GetValue());
this->WaitCursorOff();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkMultiLabelInspector::OnRenameLabel(bool /*value*/)
{
auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
auto currentLabel = this->GetCurrentLabel();
emit LabelRenameRequested(currentLabel, true);
//we assume here that all affacted label belong to one group.
auto groupID = m_Segmentation->GetGroupIndexOfLabel(currentLabel->GetValue());
auto group = m_Segmentation->GetLabelSet(groupID);
for (auto value : relevantLabelValues)
{
if (value != currentLabel->GetValue())
{
auto label = this->m_Segmentation->GetLabel(value);
if (nullptr == label)
mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
label->SetName(currentLabel->GetName());
label->SetColor(currentLabel->GetColor());
group->UpdateLookupTable(label->GetValue());
mitk::DICOMSegmentationPropertyHelper::SetDICOMSegmentProperties(label);
}
}
emit ModelUpdated();
}
void QmitkMultiLabelInspector::SetLockOfAffectedLabels(bool locked) const
{
auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
if (!relevantLabelValues.empty())
{
for (auto value : relevantLabelValues)
{
auto label = this->m_Segmentation->GetLabel(value);
if (nullptr == label)
mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
label->SetLocked(locked);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkMultiLabelInspector::OnUnlockAffectedLabels()
{
this->SetLockOfAffectedLabels(false);
}
void QmitkMultiLabelInspector::OnLockAffectedLabels()
{
this->SetLockOfAffectedLabels(true);
}
void QmitkMultiLabelInspector::SetVisibilityOfAffectedLabels(bool visible) const
{
auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
if (!relevantLabelValues.empty())
{
//we assume here that all affacted label belong to one group.
auto groupID = m_Segmentation->GetGroupIndexOfLabel(relevantLabelValues.front());
auto group = m_Segmentation->GetLabelSet(groupID);
for (auto value : relevantLabelValues)
{
auto label = this->m_Segmentation->GetLabel(value);
if (nullptr == label)
mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
label->SetVisible(visible);
group->UpdateLookupTable(label->GetValue());
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkMultiLabelInspector::OnSetAffectedLabelsVisible()
{
this->SetVisibilityOfAffectedLabels(true);
}
void QmitkMultiLabelInspector::OnSetAffectedLabelsInvisible()
{
this->SetVisibilityOfAffectedLabels(false);
}
void QmitkMultiLabelInspector::OnSetOnlyActiveLabelVisible(bool /*value*/)
{
auto currentLabel = GetFirstSelectedLabelObject();
const auto labelID = currentLabel->GetValue();
auto groupID = m_Segmentation->GetGroupIndexOfLabel(currentLabel->GetValue());
auto group = m_Segmentation->GetLabelSet(groupID);
group->SetAllLabelsVisible(false);
currentLabel->SetVisible(true);
group->UpdateLookupTable(labelID);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->PrepareGoToLabel(labelID);
}
void QmitkMultiLabelInspector::OnItemDoubleClicked(const QModelIndex& index)
{
if (!index.isValid()) return;
if (index.column() > 0) return;
auto labelVariant = index.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
if (!labelVariant.isValid()) return;
const auto labelID = labelVariant.value<mitk::Label::PixelType>();
if (QApplication::queryKeyboardModifiers().testFlag(Qt::AltModifier))
{
this->OnRenameLabel(false);
return;
}
this->PrepareGoToLabel(labelID);
}
void QmitkMultiLabelInspector::PrepareGoToLabel(mitk::Label::PixelType labelID) const
{
this->WaitCursorOn();
m_Segmentation->UpdateCenterOfMass(labelID);
const auto currentLabel = m_Segmentation->GetLabel(labelID);
const mitk::Point3D& pos = currentLabel->GetCenterOfMassCoordinates();
this->WaitCursorOff();
if (pos.GetVnlVector().max_value() > 0.0)
{
emit GoToLabel(currentLabel->GetValue(), pos);
}
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspectorControls.ui b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspectorControls.ui
index b408230b03..00fe89030a 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspectorControls.ui
+++ b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspectorControls.ui
@@ -1,98 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmitkMultiLabelInspector</class>
<widget class="QWidget" name="QmitkMultiLabelInspector">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
- <height>120</height>
+ <height>200</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
- <property name="spacing">
- <number>0</number>
- </property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QmitkMultiLabelTreeView" name="view">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
- <height>120</height>
+ <height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
- <height>120</height>
+ <height>200</height>
</size>
</property>
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerMinimumSectionSize">
<number>10</number>
</attribute>
<attribute name="headerDefaultSectionSize">
<number>50</number>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QmitkMultiLabelTreeView</class>
<extends>QTreeView</extends>
<header>QmitkMultiLabelTreeView.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
diff --git a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp
index 469020d982..315e7952fb 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp
@@ -1,997 +1,999 @@
/*============================================================================
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 "QmitkMultiLabelTreeModel.h"
#include "mitkRenderingManager.h"
#include "QmitkStyleManager.h"
class QmitkMultiLabelSegTreeItem
{
public:
enum class ItemType
{
Group,
Label,
Instance
};
QmitkMultiLabelSegTreeItem()
{
};
explicit QmitkMultiLabelSegTreeItem(ItemType type, QmitkMultiLabelSegTreeItem* parentItem,
mitk::Label* label = nullptr, std::string className = ""): m_parentItem(parentItem), m_ItemType(type), m_Label(label), m_ClassName(className)
{
};
~QmitkMultiLabelSegTreeItem()
{
for (auto item : m_childItems)
{
delete item;
}
};
void AppendChild(QmitkMultiLabelSegTreeItem* child)
{
m_childItems.push_back(child);
};
void RemoveChild(std::size_t row)
{
if (row < m_childItems.size())
{
delete m_childItems[row];
m_childItems.erase(m_childItems.begin() + row);
}
};
int Row() const
{
if (m_parentItem)
{
auto finding = std::find(m_parentItem->m_childItems.begin(), m_parentItem->m_childItems.end(), this);
if (finding != m_parentItem->m_childItems.end())
{
return std::distance(m_parentItem->m_childItems.begin(), finding);
}
}
return 0;
};
QmitkMultiLabelSegTreeItem* ParentItem()
{
return m_parentItem;
};
const QmitkMultiLabelSegTreeItem* ParentItem() const
{
return m_parentItem;
};
const QmitkMultiLabelSegTreeItem* NextSibblingItem() const
{
if (m_parentItem)
{
const std::vector<QmitkMultiLabelSegTreeItem*>::size_type row = this->Row();
if (row + 1 < m_parentItem->m_childItems.size())
return m_parentItem->m_childItems[row+1];
}
return nullptr;
};
const QmitkMultiLabelSegTreeItem* PrevSibblingItem() const
{
if (m_parentItem)
{
const std::vector<QmitkMultiLabelSegTreeItem*>::size_type row = this->Row();
if (row > 0)
return m_parentItem->m_childItems[row-1];
}
return nullptr;
};
const QmitkMultiLabelSegTreeItem* RootItem() const
{
auto item = this;
while (item->m_parentItem != nullptr)
{
item = item->m_parentItem;
}
return item;
};
std::size_t GetGroupID() const
{
auto root = this->RootItem();
auto item = this;
if (root == this) return 0;
while (root != item->m_parentItem)
{
item = item->m_parentItem;
}
auto iter = std::find(root->m_childItems.begin(), root->m_childItems.end(), item);
if (root->m_childItems.end() == iter) mitkThrow() << "Invalid internal state of QmitkMultiLabelTreeModel. Root does not have an currentItem as child that has root as parent.";
return std::distance(root->m_childItems.begin(), iter);
}
bool HandleAsInstance() const
{
return (ItemType::Instance == m_ItemType) || ((ItemType::Label == m_ItemType) && (m_childItems.size() == 1));
}
mitk::Label* GetLabel() const
{
if (ItemType::Instance == m_ItemType)
{
return m_Label;
}
if (ItemType::Label == m_ItemType)
{
if (m_childItems.empty()) mitkThrow() << "Invalid internal state of QmitkMultiLabelTreeModel. Internal label currentItem has no instance currentItem.";
return m_childItems[0]->GetLabel();
}
return nullptr;
};
mitk::LabelSetImage::LabelValueType GetLabelValue() const
{
auto label = this->GetLabel();
if (nullptr == label)
{
mitkThrow() << "Invalid internal state of QmitkMultiLabelTreeModel. Called GetLabelValue on an group currentItem.";
}
return label->GetValue();
};
/** returns a vector containing all label values of referenced by this item or its child items.*/
std::vector< mitk::LabelSetImage::LabelValueType> GetLabelsInSubTree() const
{
if (this->m_ItemType == ItemType::Instance)
{
return { this->GetLabelValue() };
}
std::vector< mitk::LabelSetImage::LabelValueType> result;
for (const auto child : this->m_childItems)
{
auto childresult = child->GetLabelsInSubTree();
result.reserve(result.size() + childresult.size());
result.insert(result.end(), childresult.begin(), childresult.end());
}
return result;
}
std::vector<QmitkMultiLabelSegTreeItem*> m_childItems;
QmitkMultiLabelSegTreeItem* m_parentItem = nullptr;
ItemType m_ItemType = ItemType::Group;
mitk::Label::Pointer m_Label;
std::string m_ClassName;
};
QModelIndex GetIndexByItem(const QmitkMultiLabelSegTreeItem* start, const QmitkMultiLabelTreeModel* model)
{
QModelIndex parentIndex = QModelIndex();
if (nullptr != start->m_parentItem)
{
parentIndex = GetIndexByItem(start->m_parentItem, model);
}
else
{
return parentIndex;
}
return model->index(start->Row(), 0, parentIndex);
}
QmitkMultiLabelSegTreeItem* GetGroupItem(QmitkMultiLabelTreeModel::GroupIndexType groupIndex, QmitkMultiLabelSegTreeItem* root)
{
if (nullptr != root && groupIndex < root->m_childItems.size())
{
return root->m_childItems[groupIndex];
}
return nullptr;
}
QmitkMultiLabelSegTreeItem* GetInstanceItem(QmitkMultiLabelTreeModel::LabelValueType labelValue, QmitkMultiLabelSegTreeItem* root)
{
QmitkMultiLabelSegTreeItem* result = nullptr;
for (auto item : root->m_childItems)
{
result = GetInstanceItem(labelValue, item);
if (nullptr != result) return result;
}
if (root->m_ItemType == QmitkMultiLabelSegTreeItem::ItemType::Instance && root->GetLabelValue() == labelValue)
{
return root;
}
return nullptr;
}
const QmitkMultiLabelSegTreeItem* GetFirstInstanceLikeItem(const QmitkMultiLabelSegTreeItem* startItem)
{
const QmitkMultiLabelSegTreeItem* result = nullptr;
if (nullptr != startItem)
{
if (startItem->HandleAsInstance())
{
result = startItem;
}
else if (!startItem->m_childItems.empty())
{
result = GetFirstInstanceLikeItem(startItem->m_childItems.front());
}
}
return result;
}
QmitkMultiLabelSegTreeItem* GetLabelItemInGroup(const std::string& labelName, QmitkMultiLabelSegTreeItem* group)
{
if (nullptr != group)
{
auto predicate = [labelName](const QmitkMultiLabelSegTreeItem* item) { return labelName == item->m_ClassName; };
auto finding = std::find_if(group->m_childItems.begin(), group->m_childItems.end(), predicate);
if (group->m_childItems.end() != finding)
{
return *finding;
}
}
return nullptr;
}
QmitkMultiLabelTreeModel::QmitkMultiLabelTreeModel(QObject *parent) : QAbstractItemModel(parent)
, m_Observed(false)
{
m_RootItem = std::make_unique<QmitkMultiLabelSegTreeItem>();
}
QmitkMultiLabelTreeModel ::~QmitkMultiLabelTreeModel()
{
this->SetSegmentation(nullptr);
};
int QmitkMultiLabelTreeModel::columnCount(const QModelIndex& /*parent*/) const
{
return 4;
}
int QmitkMultiLabelTreeModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
if (m_Segmentation.IsNull())
return 0;
QmitkMultiLabelSegTreeItem* parentItem = m_RootItem.get();
if (parent.isValid())
parentItem = static_cast<QmitkMultiLabelSegTreeItem *>(parent.internalPointer());
if (parentItem->HandleAsInstance())
{
return 0;
}
return parentItem->m_childItems.size();
}
QVariant QmitkMultiLabelTreeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
auto item = static_cast<QmitkMultiLabelSegTreeItem*>(index.internalPointer());
if (!item)
return QVariant();
if (role == Qt::DisplayRole||role == Qt::EditRole)
{
if (TableColumns::NAME_COL == index.column())
{
switch (item->m_ItemType)
{
case QmitkMultiLabelSegTreeItem::ItemType::Group:
return QVariant(QString("Group %1").arg(item->GetGroupID()));
case QmitkMultiLabelSegTreeItem::ItemType::Label:
{
auto label = item->GetLabel();
if (nullptr == label)
mitkThrow() << "Invalid internal state. QmitkMultiLabelTreeModel currentItem is refering to a label that does not exist.";
QString name = QString::fromStdString(label->GetName());
if (!item->HandleAsInstance())
name = name + QString(" (%1 instances)").arg(item->m_childItems.size());
return QVariant(name);
}
case QmitkMultiLabelSegTreeItem::ItemType::Instance:
{
auto label = item->GetLabel();
if (nullptr == label)
mitkThrow() << "Invalid internal state. QmitkMultiLabelTreeModel currentItem is refering to a label that does not exist.";
return QVariant(QString::fromStdString(label->GetName()) + QString(" [%1]").arg(item->GetLabelValue()));
}
}
}
else
{
if (item->HandleAsInstance())
{
auto label = item->GetLabel();
if (TableColumns::LOCKED_COL == index.column())
{
return QVariant(label->GetLocked());
}
else if (TableColumns::COLOR_COL == index.column())
{
return QVariant(QColor(label->GetColor().GetRed() * 255, label->GetColor().GetGreen() * 255, label->GetColor().GetBlue() * 255));
}
else if (TableColumns::VISIBLE_COL == index.column())
{
return QVariant(label->GetVisible());
}
}
}
}
else if (role == ItemModelRole::LabelDataRole)
{
auto label = item->GetLabel();
if (nullptr!=label) return QVariant::fromValue<void*>(label);
}
else if (role == ItemModelRole::LabelValueRole)
{
auto label = item->GetLabel();
if (nullptr != label) return QVariant(label->GetValue());
}
else if (role == ItemModelRole::LabelInstanceDataRole)
{
if (item->HandleAsInstance())
{
auto label = item->GetLabel();
return QVariant::fromValue<void*>(label);
}
}
else if (role == ItemModelRole::LabelInstanceValueRole)
{
if (item->HandleAsInstance())
{
auto label = item->GetLabel();
return QVariant(label->GetValue());
}
}
else if (role == ItemModelRole::GroupIDRole)
{
QVariant v;
v.setValue(item->GetGroupID());
return v;
}
return QVariant();
}
mitk::Color QtToMitk(const QColor& color)
{
mitk::Color mitkColor;
mitkColor.SetRed(color.red() / 255.0f);
mitkColor.SetGreen(color.green() / 255.0f);
mitkColor.SetBlue(color.blue() / 255.0f);
return mitkColor;
}
bool QmitkMultiLabelTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid())
return false;
auto item = static_cast<QmitkMultiLabelSegTreeItem*>(index.internalPointer());
if (!item)
return false;
if (role == Qt::EditRole)
{
if (TableColumns::NAME_COL != index.column())
{
if (item->HandleAsInstance())
{
auto label = item->GetLabel();
if (TableColumns::LOCKED_COL == index.column())
{
label->SetLocked(value.toBool());
}
else if (TableColumns::COLOR_COL == index.column())
{
label->SetColor(QtToMitk(value.value<QColor>()));
}
else if (TableColumns::VISIBLE_COL == index.column())
{
label->SetVisible(value.toBool());
}
auto groupID = m_Segmentation->GetGroupIndexOfLabel(label->GetValue());
m_Segmentation->GetLabelSet(groupID)->UpdateLookupTable(label->GetValue());
m_Segmentation->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else
{
}
return true;
}
}
return false;
}
QModelIndex QmitkMultiLabelTreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
auto parentItem = m_RootItem.get();
if (parent.isValid())
parentItem = static_cast<QmitkMultiLabelSegTreeItem *>(parent.internalPointer());
QmitkMultiLabelSegTreeItem *childItem = parentItem->m_childItems[row];
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex QmitkMultiLabelTreeModel::indexOfLabel(mitk::Label::PixelType labelValue) const
{
if (labelValue == mitk::LabelSetImage::UnlabeledValue) return QModelIndex();
auto relevantItem = GetInstanceItem(labelValue, this->m_RootItem.get());
if (nullptr == relevantItem)
return QModelIndex();
auto labelItem = relevantItem->ParentItem();
if (labelItem->m_childItems.size() == 1)
{ //was the only instance of the label, therefor return the label item instat.
relevantItem = labelItem;
}
return GetIndexByItem(relevantItem, this);
}
QModelIndex QmitkMultiLabelTreeModel::indexOfGroup(mitk::LabelSetImage::GroupIndexType groupIndex) const
{
auto relevantItem = GetGroupItem(groupIndex, this->m_RootItem.get());
if (nullptr == relevantItem) QModelIndex();
return GetIndexByItem(relevantItem, this);
}
QModelIndex QmitkMultiLabelTreeModel::parent(const QModelIndex &child) const
{
if (!child.isValid())
return QModelIndex();
QmitkMultiLabelSegTreeItem *childItem = static_cast<QmitkMultiLabelSegTreeItem *>(child.internalPointer());
QmitkMultiLabelSegTreeItem *parentItem = childItem->ParentItem();
if (parentItem == m_RootItem.get())
return QModelIndex();
return createIndex(parentItem->Row(), 0, parentItem);
}
QModelIndex QmitkMultiLabelTreeModel::ClosestLabelInstanceIndex(const QModelIndex& currentIndex) const
{
if (!currentIndex.isValid()) return QModelIndex();
auto currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
if (!currentItem) return QModelIndex();
if (currentItem->RootItem() != this->m_RootItem.get()) mitkThrow() << "Invalid call. Passed currentIndex does not seem to be a valid index of this model. It is either outdated or from another model.";
const QmitkMultiLabelSegTreeItem* resultItem = nullptr;
auto searchItem = currentItem;
const auto rootItem = currentItem->RootItem();
while (searchItem != rootItem)
{
resultItem = GetFirstInstanceLikeItem(searchItem->NextSibblingItem());
if (nullptr != resultItem) break;
//no next closest label instance on this level -> check for closest before
resultItem = GetFirstInstanceLikeItem(searchItem->PrevSibblingItem());
if (nullptr != resultItem) break;
//no closest label instance before current on this level -> moeve one level up
searchItem = searchItem->ParentItem();
}
if (nullptr == resultItem)
return QModelIndex();
return GetIndexByItem(resultItem, this);
}
QModelIndex QmitkMultiLabelTreeModel::FirstLabelInstanceIndex(const QModelIndex& currentIndex) const
{
const QmitkMultiLabelSegTreeItem* currentItem = nullptr;
if (!currentIndex.isValid())
{
currentItem = this->m_RootItem.get();
}
else
{
currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
}
if (!currentItem) return QModelIndex();
if (currentItem->RootItem() != this->m_RootItem.get()) mitkThrow() << "Invalid call. Passed currentIndex does not seem to be a valid index of this model. It is either outdated or from another model.";
const QmitkMultiLabelSegTreeItem* resultItem = nullptr;
resultItem = GetFirstInstanceLikeItem(currentItem);
if (nullptr == resultItem)
return QModelIndex();
return GetIndexByItem(resultItem, this);
}
///** Returns the index to the next node in the tree that behaves like an instance (label node with only one instance
//or instance node). If current index is at the end, an invalid index is returned.*/
//QModelIndex QmitkMultiLabelTreeModel::PrevLabelInstanceIndex(const QModelIndex& currentIndex) const;
std::vector <QmitkMultiLabelTreeModel::LabelValueType> QmitkMultiLabelTreeModel::GetLabelsInSubTree(const QModelIndex& currentIndex) const
{
const QmitkMultiLabelSegTreeItem* currentItem = nullptr;
if (!currentIndex.isValid())
{
currentItem = this->m_RootItem.get();
}
else
{
currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
}
if (!currentItem) return {};
return currentItem->GetLabelsInSubTree();
}
std::vector <QmitkMultiLabelTreeModel::LabelValueType> QmitkMultiLabelTreeModel::GetLabelInstancesOfSameLabelClass(const QModelIndex& currentIndex) const
{
const QmitkMultiLabelSegTreeItem* currentItem = nullptr;
if (currentIndex.isValid())
{
currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
}
if (!currentItem)
return {};
if (QmitkMultiLabelSegTreeItem::ItemType::Group == currentItem->m_ItemType)
return {};
if (QmitkMultiLabelSegTreeItem::ItemType::Instance == currentItem->m_ItemType)
currentItem = currentItem->ParentItem();
return currentItem->GetLabelsInSubTree();
}
Qt::ItemFlags QmitkMultiLabelTreeModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
if (!index.isValid())
return Qt::NoItemFlags;
auto item = static_cast<QmitkMultiLabelSegTreeItem*>(index.internalPointer());
if (!item)
return Qt::NoItemFlags;
if (TableColumns::NAME_COL != index.column())
{
if (item->HandleAsInstance() &&
((TableColumns::VISIBLE_COL == index.column() && m_AllowVisibilityModification) ||
(TableColumns::COLOR_COL == index.column() && m_AllowVisibilityModification) || //m_AllowVisibilityModification controls visibility and color
(TableColumns::LOCKED_COL == index.column() && m_AllowLockModification)))
{
return Qt::ItemIsEnabled | Qt::ItemIsEditable;
}
else
{
return Qt::ItemIsEnabled;
}
}
else
{
if (item->HandleAsInstance())
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
else
{
return Qt::ItemIsEnabled;
}
}
return Qt::NoItemFlags;
}
QVariant QmitkMultiLabelTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if ((Qt::DisplayRole == role) && (Qt::Horizontal == orientation))
{
if (TableColumns::NAME_COL == section)
{
return "Name";
}
else if (TableColumns::LOCKED_COL == section)
{
return "Locked";
}
else if (TableColumns::COLOR_COL == section)
{
return "Color";
}
else if (TableColumns::VISIBLE_COL == section)
{
return "Visibility";
}
}
return QVariant();
}
const mitk::LabelSetImage* QmitkMultiLabelTreeModel::GetSegmentation() const
{
return m_Segmentation;
}
void QmitkMultiLabelTreeModel::SetSegmentation(mitk::LabelSetImage* segmentation)
{
if (m_Segmentation != segmentation)
{
this->RemoveObserver();
this->m_Segmentation = segmentation;
this->AddObserver();
this->UpdateInternalTree();
}
}
/**Helper function that adds a labek into the item tree. Passes back the new created instance iten*/
QmitkMultiLabelSegTreeItem* AddLabelToGroupTree(mitk::Label* label, QmitkMultiLabelSegTreeItem* groupItem, bool& newLabelItemCreated)
{
if (nullptr == groupItem) return nullptr;
if (nullptr == label) return nullptr;
newLabelItemCreated = false;
std::set<std::string> labelNames;
for (auto labelItem : groupItem->m_childItems)
{
labelNames.emplace(labelItem->GetLabel()->GetName());
}
QmitkMultiLabelSegTreeItem* labelItem = nullptr;
auto finding = labelNames.find(label->GetName());
if (finding != labelNames.end())
{ //other label with same name exists
labelItem = groupItem->m_childItems[std::distance(labelNames.begin(), finding)];
}
else
{
newLabelItemCreated = true;
labelItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Label, groupItem, nullptr, label->GetName());
auto predicate = [label](const std::string& name) { return name > label->GetName(); };
auto insertFinding = std::find_if(labelNames.begin(), labelNames.end(), predicate);
groupItem->m_childItems.insert(groupItem->m_childItems.begin() + std::distance(labelNames.begin(), insertFinding), labelItem);
}
auto instanceItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Instance, labelItem, label);
auto predicate = [label](const QmitkMultiLabelSegTreeItem* item) { return item->GetLabelValue() > label->GetValue(); };
auto insertFinding = std::find_if(labelItem->m_childItems.begin(), labelItem->m_childItems.end(), predicate);
labelItem->m_childItems.insert(labelItem->m_childItems.begin() + std::distance(labelItem->m_childItems.begin(), insertFinding), instanceItem);
return instanceItem;
}
void QmitkMultiLabelTreeModel::GenerateInternalGroupTree(unsigned int groupID, QmitkMultiLabelSegTreeItem* groupItem)
{
auto labelSet = m_Segmentation->GetLabelSet(groupID);
for (auto lIter = labelSet->IteratorConstBegin(); lIter != labelSet->IteratorConstEnd(); lIter++)
{
if (lIter->first== mitk::LabelSetImage::UnlabeledValue) continue;
bool newItemCreated = false;
AddLabelToGroupTree(lIter->second, groupItem, newItemCreated);
}
}
QmitkMultiLabelSegTreeItem* QmitkMultiLabelTreeModel::GenerateInternalTree()
{
auto rootItem = new QmitkMultiLabelSegTreeItem();
if (m_Segmentation.IsNotNull())
{
for (unsigned int groupID = 0; groupID < m_Segmentation->GetNumberOfLayers(); ++groupID)
{
auto groupItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Group, rootItem);
rootItem->AppendChild(groupItem);
GenerateInternalGroupTree(groupID, groupItem);
}
}
return rootItem;
}
void QmitkMultiLabelTreeModel::UpdateInternalTree()
{
emit beginResetModel();
auto newTree = this->GenerateInternalTree();
this->m_RootItem.reset(newTree);
emit endResetModel();
emit modelChanged();
}
void QmitkMultiLabelTreeModel::AddObserver()
{
if (this->m_Segmentation.IsNotNull())
{
if (m_Observed)
{
MITK_DEBUG << "Invalid observer state in QmitkMultiLabelTreeModel. There is already a registered observer. Internal logic is not correct. May be an old observer was not removed.";
}
this->m_Segmentation->AddLabelAddedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, LabelValueType>(
this, &QmitkMultiLabelTreeModel::OnLabelAdded));
this->m_Segmentation->AddLabelModifiedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, LabelValueType>(
this, &QmitkMultiLabelTreeModel::OnLabelModified));
this->m_Segmentation->AddLabelRemovedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, LabelValueType>(
this, &QmitkMultiLabelTreeModel::OnLabelRemoved));
this->m_Segmentation->AddGroupAddedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, GroupIndexType>(
this, &QmitkMultiLabelTreeModel::OnGroupAdded));
this->m_Segmentation->AddGroupModifiedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, GroupIndexType>(
this, &QmitkMultiLabelTreeModel::OnGroupModified));
this->m_Segmentation->AddGroupRemovedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, GroupIndexType>(
this, &QmitkMultiLabelTreeModel::OnGroupRemoved));
m_Observed = true;
}
}
void QmitkMultiLabelTreeModel::RemoveObserver()
{
if (this->m_Segmentation.IsNotNull())
{
this->m_Segmentation->RemoveLabelAddedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, LabelValueType>(
this, &QmitkMultiLabelTreeModel::OnLabelAdded));
this->m_Segmentation->RemoveLabelModifiedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, LabelValueType>(
this, &QmitkMultiLabelTreeModel::OnLabelModified));
this->m_Segmentation->RemoveLabelRemovedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, LabelValueType>(
this, &QmitkMultiLabelTreeModel::OnLabelRemoved));
this->m_Segmentation->RemoveGroupAddedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, GroupIndexType>(
this, &QmitkMultiLabelTreeModel::OnGroupAdded));
this->m_Segmentation->RemoveGroupModifiedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, GroupIndexType>(
this, &QmitkMultiLabelTreeModel::OnGroupModified));
this->m_Segmentation->RemoveGroupRemovedListener(mitk::MessageDelegate1<QmitkMultiLabelTreeModel, GroupIndexType>(
this, &QmitkMultiLabelTreeModel::OnGroupRemoved));
}
m_Observed = false;
}
void QmitkMultiLabelTreeModel::OnLabelAdded(LabelValueType labelValue)
{
GroupIndexType groupIndex = 0;
if (m_Segmentation->IsLabelInGroup(labelValue, groupIndex))
{
auto label = m_Segmentation->GetLabel(labelValue);
if (nullptr == label) mitkThrow() << "Invalid internal state. Segmentation signaled the addition of an label that does not exist in the segmentation. Invalid label value:" << labelValue;
if (labelValue == mitk::LabelSetImage::UnlabeledValue) return;
auto groupItem = GetGroupItem(groupIndex, this->m_RootItem.get());
bool newLabelCreated = false;
auto instanceItem = AddLabelToGroupTree(label, groupItem, newLabelCreated);
if (newLabelCreated)
{
if (groupItem->m_childItems.size() == 1)
{ //first label added
auto groupIndex = GetIndexByItem(groupItem, this);
emit dataChanged(groupIndex, groupIndex);
+ this->beginInsertRows(groupIndex, instanceItem->ParentItem()->Row(), instanceItem->ParentItem()->Row());
+ this->endInsertRows();
}
else
{ //whole new label level added to group item
auto groupIndex = GetIndexByItem(groupItem, this);
this->beginInsertRows(groupIndex, instanceItem->ParentItem()->Row(), instanceItem->ParentItem()->Row());
this->endInsertRows();
}
}
else
{
if (instanceItem->ParentItem()->m_childItems.size() < 3)
{ //second instance item was added, so label item will now able to colapse
// -> the whole label node has to be updated.
auto labelIndex = GetIndexByItem(instanceItem->ParentItem(), this);
emit dataChanged(labelIndex, labelIndex);
this->beginInsertRows(labelIndex, 0, instanceItem->ParentItem()->m_childItems.size()-1);
this->endInsertRows();
}
else
{
// instance item was added to existing label item with multiple instances
//-> just notify the row insertion
auto labelIndex = GetIndexByItem(instanceItem->ParentItem(), this);
this->beginInsertRows(labelIndex, instanceItem->Row(), instanceItem->Row());
this->endInsertRows();
}
}
}
else
{
mitkThrow() << "Group less labels are not supported in the current implementation.";
}
}
void QmitkMultiLabelTreeModel::OnLabelModified(LabelValueType labelValue)
{
if (labelValue == mitk::LabelSetImage::UnlabeledValue) return;
auto instanceItem = GetInstanceItem(labelValue, this->m_RootItem.get());
if (nullptr == instanceItem)
{
mitkThrow() << "Internal invalid state. QmitkMultiLabelTreeModel recieved a LabelModified signal for a label that is not represented in the model. Invalid label: " << labelValue;
}
auto labelItem = instanceItem->ParentItem();
if (labelItem->m_ClassName == instanceItem->GetLabel()->GetName())
{ //only the state of the label changed, but not its position in the model tree.
auto index = GetIndexByItem(labelItem, this);
emit dataChanged(index, index);
}
else
{ //the name of the label changed and thus its place in the model tree, delete the current item and add a new one
this->OnLabelRemoved(labelValue);
this->OnLabelAdded(labelValue);
}
}
void QmitkMultiLabelTreeModel::OnLabelRemoved(LabelValueType labelValue)
{
if (labelValue == mitk::LabelSetImage::UnlabeledValue) return;
auto instanceItem = GetInstanceItem(labelValue, this->m_RootItem.get());
if (nullptr == instanceItem) mitkThrow() << "Internal invalid state. QmitkMultiLabelTreeModel recieved a LabelRemoved signal for a label that is not represented in the model. Invalid label: " << labelValue;
auto labelItem = instanceItem->ParentItem();
if (labelItem->m_childItems.size() > 2)
{
auto labelIndex = GetIndexByItem(labelItem, this);
this->beginRemoveRows(labelIndex, instanceItem->Row(), instanceItem->Row());
labelItem->RemoveChild(instanceItem->Row());
this->endRemoveRows();
}
else if (labelItem->m_childItems.size() == 2)
{ //After removal only one label is left -> the whole label node is about to be changed (no instances are shown any more).
auto labelIndex = GetIndexByItem(labelItem, this);
this->beginRemoveRows(labelIndex, instanceItem->Row(), instanceItem->Row());
labelItem->RemoveChild(instanceItem->Row());
this->endRemoveRows();
emit dataChanged(labelIndex, labelIndex);
}
else
{ //was the only instance of the label, therefor also remove the label node from the tree.
auto groupItem = labelItem->ParentItem();
auto groupIndex = GetIndexByItem(groupItem, this);
this->beginRemoveRows(groupIndex, labelItem->Row(), labelItem->Row());
groupItem->RemoveChild(labelItem->Row());
this->endRemoveRows();
}
}
void QmitkMultiLabelTreeModel::OnGroupAdded(GroupIndexType groupIndex)
{
if (m_ShowGroups)
{
this->beginInsertRows(QModelIndex(), groupIndex, groupIndex);
auto rootItem = m_RootItem.get();
auto groupItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Group, rootItem);
rootItem->AppendChild(groupItem);
this->GenerateInternalGroupTree(groupIndex, groupItem);
this->endInsertRows();
}
}
void QmitkMultiLabelTreeModel::OnGroupModified(GroupIndexType /*groupIndex*/)
{
//currently not needed
}
void QmitkMultiLabelTreeModel::OnGroupRemoved(GroupIndexType groupIndex)
{
if (m_ShowGroups)
{
this->beginRemoveRows(QModelIndex(), groupIndex, groupIndex);
auto root = m_RootItem.get();
root->RemoveChild(groupIndex);
this->endRemoveRows();
}
}
void QmitkMultiLabelTreeModel::SetAllowVisibilityModification(bool vmod)
{
m_AllowVisibilityModification = vmod;
}
bool QmitkMultiLabelTreeModel::GetAllowVisibilityModification() const
{
return m_AllowVisibilityModification;
}
void QmitkMultiLabelTreeModel::SetAllowLockModification(bool lmod)
{
m_AllowLockModification = lmod;
}
bool QmitkMultiLabelTreeModel::GetAllowLockModification() const
{
return m_AllowLockModification;
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.cpp b/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.cpp
index 37ea6adefc..d3e04175c0 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.cpp
@@ -1,981 +1,1012 @@
/*============================================================================
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 "QmitkSegmentationTaskListWidget.h"
#include <mitkCoreServices.h>
#include <mitkIPreferencesService.h>
#include <mitkIPreferences.h>
#include <mitkDICOMQIPropertyHelper.h>
#include <mitkIOUtil.h>
#include <mitkMultiLabelIOHelper.h>
#include <mitkLabelSetImageHelper.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateFunction.h>
#include <mitkRenderingManager.h>
#include <mitkSegmentationHelper.h>
#include <mitkToolManagerProvider.h>
+#include <QmitkFindSegmentationTaskDialog.h>
#include <QmitkStaticDynamicSegmentationDialog.h>
#include <QmitkStyleManager.h>
-#include <QmitkStyleManager.h>
-
#include <ui_QmitkSegmentationTaskListWidget.h>
#include <QFileSystemWatcher>
#include <QMessageBox>
#include <QShortcut>
#include <filesystem>
namespace
{
mitk::IPreferences* GetSegmentationPreferences()
{
return mitk::CoreServices::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.views.segmentation");
}
std::filesystem::path GetInputLocation(const mitk::BaseData* data)
{
std::string result;
if (data != nullptr)
data->GetPropertyList()->GetStringProperty("MITK.IO.reader.inputlocation", result);
return result;
}
QString ColorString(const QString& string, const QColor& color, const QColor& backgroundColor = QColor::Invalid)
{
if (!color.isValid() && !backgroundColor.isValid())
return string;
auto result = QStringLiteral("<span style=\"");
QStringList strings;
if (color.isValid())
strings << QString("color: %1;").arg(color.name());
if (backgroundColor.isValid())
strings << QString("background-color: %1;").arg(backgroundColor.name());
result += strings.join(' ') + QString("\">%1</span>").arg(string);
return result;
}
mitk::DataStorage::SetOfObjects::ConstPointer GetSubset(const mitk::DataStorage* dataStorage, const mitk::NodePredicateBase* condition, const mitk::DataNode* removedDataNode)
{
auto subset = dataStorage->GetSubset(condition);
if (nullptr != removedDataNode)
{
auto actualSubset = mitk::DataStorage::SetOfObjects::New();
for (auto node : *subset)
{
if (node != removedDataNode)
actualSubset->push_back(node);
}
return actualSubset;
}
return subset;
}
}
/* This constructor has three objectives:
* 1. Do widget initialization that cannot be done in the .ui file
* 2. Connect signals and slots
* 3. Explicitly trigger a reset to a valid initial widget state
*/
QmitkSegmentationTaskListWidget::QmitkSegmentationTaskListWidget(QWidget* parent)
: QWidget(parent),
m_Ui(new Ui::QmitkSegmentationTaskListWidget),
m_FileSystemWatcher(new QFileSystemWatcher(this)),
m_DataStorage(nullptr),
m_UnsavedChanges(false)
{
m_Ui->setupUi(this);
m_Ui->selectionWidget->SetNodePredicate(mitk::TNodePredicateDataType<mitk::SegmentationTaskList>::New());
m_Ui->progressBar->setStyleSheet(QString("QProgressBar::chunk { background-color: %1; }").arg(QmitkStyleManager::GetIconAccentColor()));
+ m_Ui->findButton->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_find.svg")));
m_Ui->storeButton->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/document-save.svg")));
using Self = QmitkSegmentationTaskListWidget;
connect(m_Ui->selectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &Self::OnSelectionChanged);
connect(m_Ui->previousButton, &QToolButton::clicked, this, &Self::OnPreviousButtonClicked);
connect(m_Ui->nextButton, &QToolButton::clicked, this, &Self::OnNextButtonClicked);
+ connect(m_Ui->findButton, &QToolButton::clicked, this, &Self::OnFindButtonClicked);
connect(m_Ui->loadButton, &QPushButton::clicked, this, &Self::OnLoadButtonClicked);
connect(m_Ui->storeButton, &QPushButton::clicked, this, &Self::OnStoreButtonClicked);
connect(m_Ui->acceptButton, &QPushButton::clicked, this, &Self::OnAcceptButtonClicked);
connect(m_FileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, &Self::OnResultDirectoryChanged);
auto* prevShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key::Key_P), this);
connect(prevShortcut, &QShortcut::activated, this, &Self::OnPreviousTaskShortcutActivated);
auto* prevUndoneShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key::Key_P), this);
connect(prevUndoneShortcut, &QShortcut::activated, this, &Self::OnPreviousTaskShortcutActivated);
auto* nextShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key::Key_N), this);
connect(nextShortcut, &QShortcut::activated, this, &Self::OnNextTaskShortcutActivated);
auto* nextUndoneShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key::Key_N), this);
connect(nextUndoneShortcut, &QShortcut::activated, this, &Self::OnNextTaskShortcutActivated);
+ auto *findTaskShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key::Key_F), this);
+ connect(findTaskShortcut, &QShortcut::activated, this, &Self::OnFindTaskShortcutActivated);
+
auto* loadShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key::Key_L), this);
connect(loadShortcut, &QShortcut::activated, this, &Self::OnLoadTaskShortcutActivated);
auto* storeShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key::Key_S), parent);
connect(storeShortcut, &QShortcut::activated, this, &Self::OnStoreInterimResultShortcutActivated);
auto* acceptShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key::Key_A), parent);
connect(acceptShortcut, &QShortcut::activated, this, &Self::OnAcceptSegmentationShortcutActivated);
this->ResetControls();
this->CheckDataStorage();
}
QmitkSegmentationTaskListWidget::~QmitkSegmentationTaskListWidget()
{
}
void QmitkSegmentationTaskListWidget::SetDataStorage(mitk::DataStorage* dataStorage)
{
m_DataStorage = dataStorage;
m_Ui->selectionWidget->SetDataStorage(dataStorage); // Triggers OnSelectionChanged()
m_Ui->selectionWidget->SetAutoSelectNewNodes(true);
this->CheckDataStorage();
}
void QmitkSegmentationTaskListWidget::CheckDataStorage(const mitk::DataNode* removedNode)
{
QString warning;
if (nullptr == m_DataStorage)
{
warning = QStringLiteral(
"<h3>Developer warning</h3><p>Call <code>SetDataStorage()</code> to fully initialize "
"this instance of <code>QmitkSegmentationTaskListWidget</code>.</p>");
}
else
{
auto isTaskList = mitk::TNodePredicateDataType<mitk::SegmentationTaskList>::New();
auto taskListNodes = GetSubset(m_DataStorage, isTaskList, removedNode);
if (taskListNodes->empty())
{
warning = QStringLiteral(
"<h3>No segmentation task list found</h3><p>Load a segmentation task list to use "
"this plugin.</p>");
}
else if (taskListNodes->Size() > 1)
{
warning = QStringLiteral(
"<h3>More than one segmentation task list found</h3><p>Unload everything but a "
"single segmentation task list to use this plugin.</p>");
}
else
{
const auto* taskListNode = (*taskListNodes)[0].GetPointer();
auto isTaskListNode = mitk::NodePredicateFunction::New([taskListNode](const mitk::DataNode* node) {
return node == taskListNode;
});
auto isChildOfTaskListNode = mitk::NodePredicateFunction::New([this, isTaskListNode](const mitk::DataNode* node) {
return !m_DataStorage->GetSources(node, isTaskListNode, false)->empty();
});
auto isHelperObject = mitk::NodePredicateProperty::New("helper object");
auto isUndesiredNode = mitk::NodePredicateNot::New(mitk::NodePredicateOr::New(
isTaskListNode,
isChildOfTaskListNode,
isHelperObject));
if (!GetSubset(m_DataStorage, isUndesiredNode, removedNode)->empty())
{
warning = QStringLiteral(
"<h3>Unrelated data found</h3><p>Unload everything but a single segmentation task "
"list to use this plugin.</p>");
}
}
}
m_Ui->label->setText("<span style=\"color: " + QmitkStyleManager::GetIconAccentColor() + "\">" + warning + "</span>");
m_Ui->label->setVisible(!warning.isEmpty());
m_Ui->widget->setVisible(warning.isEmpty());
}
void QmitkSegmentationTaskListWidget::OnUnsavedChangesSaved()
{
if (m_UnsavedChanges)
{
m_UnsavedChanges = false;
if (this->ActiveTaskIsShown())
this->UpdateDetailsLabel();
}
}
/* Make sure that the widget transitions into a valid state whenever the
* selection changes.
*/
void QmitkSegmentationTaskListWidget::OnSelectionChanged(const QmitkSingleNodeSelectionWidget::NodeList& nodes)
{
this->UnloadTasks();
this->ResetControls();
if (!nodes.empty())
{
m_TaskListNode = nodes.front();
auto taskList = dynamic_cast<mitk::SegmentationTaskList*>(m_TaskListNode->GetData());
if (taskList != nullptr)
{
this->OnTaskListChanged(taskList);
return;
}
}
this->SetTaskList(nullptr);
m_TaskListNode = nullptr;
}
/* Reset all controls to a default state as a common basis for further
* adjustments.
*/
void QmitkSegmentationTaskListWidget::ResetControls()
{
m_Ui->progressBar->setEnabled(false);
m_Ui->progressBar->setFormat("");
m_Ui->progressBar->setValue(0);
m_Ui->progressBar->setMaximum(1);
m_Ui->previousButton->setEnabled(false);
m_Ui->nextButton->setEnabled(false);
this->UpdateLoadButton();
this->UpdateDetailsLabel();
this->UpdateStoreAndAcceptButtons();
}
/* If the segmentation task changed, reset all member variables to expected
* default values and reset the file system watcher.
*/
void QmitkSegmentationTaskListWidget::SetTaskList(mitk::SegmentationTaskList* taskList)
{
if (m_TaskList != taskList)
{
m_TaskList = taskList;
if (taskList != nullptr)
{
this->SetCurrentTaskIndex(0);
}
else
{
this->SetCurrentTaskIndex(std::nullopt);
}
this->ResetFileSystemWatcher();
}
}
void QmitkSegmentationTaskListWidget::ResetFileSystemWatcher()
{
auto paths = m_FileSystemWatcher->directories();
if (!paths.empty())
m_FileSystemWatcher->removePaths(paths);
if (m_TaskList.IsNotNull())
{
for (const auto& task : *m_TaskList)
{
auto resultPath = m_TaskList->GetAbsolutePath(task.GetResult()).remove_filename();
if (!std::filesystem::exists(resultPath))
{
try
{
std::filesystem::create_directories(resultPath);
}
catch (const std::filesystem::filesystem_error& e)
{
MITK_ERROR << e.what();
}
}
if (std::filesystem::exists(resultPath))
m_FileSystemWatcher->addPath(QString::fromStdString(resultPath.string()));
}
}
}
void QmitkSegmentationTaskListWidget::OnResultDirectoryChanged(const QString&)
{
// TODO: If a segmentation was modified ("Unsaved changes"), saved ("Done"), and then the file is deleted, the status should be "Unsaved changes" instead of "Not done".
this->UpdateProgressBar();
this->UpdateDetailsLabel();
}
void QmitkSegmentationTaskListWidget::UpdateProgressBar()
{
int progress = 0;
for (size_t i = 0; i < m_TaskList->GetNumberOfTasks(); ++i)
{
if (m_TaskList->IsDone(i))
++progress;
}
m_Ui->progressBar->setValue(progress);
}
/* Provided that a valid segmentation task list is currently selected and the
* widget is in its default state, update all controls accordingly.
* TODO: Then, load the first unfinished task, if any.
*/
void QmitkSegmentationTaskListWidget::OnTaskListChanged(mitk::SegmentationTaskList* taskList)
{
this->SetTaskList(taskList);
const auto numTasks = taskList->GetNumberOfTasks();
m_Ui->progressBar->setMaximum(numTasks);
m_Ui->progressBar->setFormat(QStringLiteral("%v/%m Task(s) done"));
m_Ui->progressBar->setEnabled(true);
this->UpdateProgressBar();
m_Ui->loadButton->setEnabled(true);
if (numTasks > 1)
m_Ui->nextButton->setEnabled(true);
// TODO: This line should be enough but it is happening too early even before
// the RenderingManager has any registered render windows, resulting in mismatching
// renderer and data geometries.
// this->LoadNextUnfinishedTask();
}
/* If possible, change the currently displayed task to the previous task.
* Enable/disable navigation buttons according to the task's position.
*/
void QmitkSegmentationTaskListWidget::OnPreviousButtonClicked()
{
auto current = m_CurrentTaskIndex.value();
// If the shift modifier key is pressed, look for the previous undone task.
if (QApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier))
{
if (current > 0)
{
for (decltype(current) i = current; i > 0; --i)
{
if (!m_TaskList->IsDone(i - 1))
{
this->SetCurrentTaskIndex(i - 1);
break;
}
}
}
}
else
{
if (current != 0)
this->SetCurrentTaskIndex(current - 1);
}
this->UpdateNavigationButtons();
}
/* If possible, change the currently displayed task to the next task.
* Enable/disable navigation buttons according to the task's position.
*/
void QmitkSegmentationTaskListWidget::OnNextButtonClicked()
{
const auto numTasks = m_TaskList->GetNumberOfTasks();
auto current = m_CurrentTaskIndex.value();
// If the shift modifier key is pressed, look for the next undone task.
if (QApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier))
{
for (std::remove_const_t<decltype(numTasks)> i = current + 1; i < numTasks; ++i)
{
if (!m_TaskList->IsDone(i))
{
this->SetCurrentTaskIndex(i);
break;
}
}
}
else
{
if (current < numTasks - 1)
this->SetCurrentTaskIndex(current + 1);
}
this->UpdateNavigationButtons();
}
+void QmitkSegmentationTaskListWidget::OnFindButtonClicked()
+{
+ if (m_TaskList.IsNull())
+ return;
+
+ QmitkFindSegmentationTaskDialog dialog;
+ dialog.SetTaskList(m_TaskList);
+
+ if (dialog.exec() != QDialog::Accepted)
+ return;
+
+ if (!dialog.GetSelectedTask().has_value())
+ return;
+
+ this->SetCurrentTaskIndex(dialog.GetSelectedTask());
+
+ if (dialog.LoadSelectedTask())
+ {
+ if (!m_ActiveTaskIndex.has_value() || m_ActiveTaskIndex.value() != dialog.GetSelectedTask().value())
+ this->OnLoadButtonClicked();
+ }
+}
+
void QmitkSegmentationTaskListWidget::UpdateNavigationButtons()
{
if (m_TaskList.IsNull() || m_TaskList->GetNumberOfTasks() == 0)
{
m_Ui->previousButton->setEnabled(false);
m_Ui->nextButton->setEnabled(false);
return;
}
const auto maxIndex = m_TaskList->GetNumberOfTasks() - 1;
const auto current = m_CurrentTaskIndex.value();
m_Ui->previousButton->setEnabled(current != 0);
m_Ui->nextButton->setEnabled(current != maxIndex);
}
/* Update affected controls when the currently displayed task changed.
*/
void QmitkSegmentationTaskListWidget::OnCurrentTaskChanged()
{
this->UpdateLoadButton();
this->UpdateNavigationButtons();
this->UpdateDetailsLabel();
this->UpdateStoreAndAcceptButtons();
}
/* Update the load button according to the currently displayed task.
*/
void QmitkSegmentationTaskListWidget::UpdateLoadButton()
{
auto text = !this->ActiveTaskIsShown()
? QStringLiteral("Load task")
: QStringLiteral("Task");
if (m_CurrentTaskIndex.has_value())
{
const auto current = m_CurrentTaskIndex.value();
if (m_TaskList.IsNotNull())
{
text += QString(" %1/%2").arg(current + 1).arg(m_TaskList->GetNumberOfTasks());
if (m_TaskList->HasName(current))
text += QStringLiteral(":\n") + QString::fromStdString(m_TaskList->GetName(current));
}
m_Ui->loadButton->setDisabled(this->ActiveTaskIsShown());
}
else
{
m_Ui->loadButton->setEnabled(false);
}
m_Ui->loadButton->setText(text);
}
/* Update the details label according to the currently display task.
* The text is composed of the status of the task and a variable number
* of text blocks according to the optional values provided by the task.
*/
void QmitkSegmentationTaskListWidget::UpdateDetailsLabel()
{
if (!m_CurrentTaskIndex.has_value())
{
m_Ui->detailsLabel->clear();
return;
}
const auto current = m_CurrentTaskIndex.value();
bool isDone = m_TaskList->IsDone(current);
auto details = QString("<p><b>Status: %1</b> / <b>").arg(this->ActiveTaskIsShown()
? ColorString("Active", Qt::white, QColor(Qt::green).darker())
: ColorString("Inactive", Qt::white, QColor(Qt::red).darker()));
if (m_UnsavedChanges && this->ActiveTaskIsShown())
{
details += QString("%1</b></p>").arg(ColorString("Unsaved changes", Qt::white, QColor(Qt::red).darker()));
}
else
{
details += QString("%1</b></p>").arg(isDone
? ColorString("Done", Qt::white, QColor(Qt::green).darker())
: ColorString("Not done", Qt::white, QColor(Qt::red).darker()));
}
if (m_TaskList->HasDescription(current))
details += QString("<p><b>Description:</b> %1</p>").arg(QString::fromStdString(m_TaskList->GetDescription(current)));
QStringList stringList;
if (m_TaskList->HasImage(current))
stringList << QString::fromStdString("<b>Image:</b> " + m_TaskList->GetImage(current).string());
if (m_TaskList->HasSegmentation(current))
stringList << QString::fromStdString("<b>Segmentation:</b> " + m_TaskList->GetSegmentation(current).string());
if (m_TaskList->HasLabelName(current))
stringList << QString::fromStdString("<b>Label name:</b> " + m_TaskList->GetLabelName(current));
if (m_TaskList->HasLabelNameSuggestions(current))
stringList << QString::fromStdString("<b>Label name suggestions:</b> " + m_TaskList->GetLabelNameSuggestions(current).string());
if (m_TaskList->HasPreset(current))
stringList << QString::fromStdString("<b>Label set preset:</b> " + m_TaskList->GetPreset(current).string());
if (m_TaskList->HasDynamic(current))
stringList << QString("<b>Segmentation type:</b> %1").arg(m_TaskList->GetDynamic(current) ? "Dynamic" : "Static");
if (!stringList.empty())
details += QString("<p>%1</p>").arg(stringList.join(QStringLiteral("<br>")));
m_Ui->detailsLabel->setText(details);
}
void QmitkSegmentationTaskListWidget::UpdateStoreAndAcceptButtons()
{
auto activeTaskIsShown = this->ActiveTaskIsShown();
m_Ui->storeButton->setVisible(activeTaskIsShown);
m_Ui->acceptButton->setEnabled(activeTaskIsShown);
}
/* Load/activate the currently displayed task. Unload all data nodes from
* previously active tasks first, but spare and reuse the image if possible.
*/
void QmitkSegmentationTaskListWidget::OnLoadButtonClicked()
{
if (!this->HandleUnsavedChanges() || m_UnsavedChanges)
return;
m_Ui->loadButton->setEnabled(false);
QApplication::setOverrideCursor(Qt::BusyCursor);
this->LoadTask(this->GetImageDataNode(m_CurrentTaskIndex.value()));
QApplication::restoreOverrideCursor();
}
/* If present, return the image data node for the task with the specified
* index. Otherwise, return nullptr.
*/
mitk::DataNode* QmitkSegmentationTaskListWidget::GetImageDataNode(size_t index) const
{
const auto imagePath = m_TaskList->GetAbsolutePath(m_TaskList->GetImage(index));
auto imageNodes = m_DataStorage->GetDerivations(m_TaskListNode, mitk::NodePredicateFunction::New([imagePath](const mitk::DataNode* node) {
return imagePath == GetInputLocation(node->GetData());
}));
return !imageNodes->empty()
? imageNodes->front()
: nullptr;
}
/* If present, return the segmentation data node for the task with the
* specified index. Otherwise, return nullptr.
*/
mitk::DataNode* QmitkSegmentationTaskListWidget::GetSegmentationDataNode(size_t index) const
{
const auto* imageNode = this->GetImageDataNode(index);
if (imageNode != nullptr)
{
auto segmentations = m_DataStorage->GetDerivations(imageNode, mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
if (!segmentations->empty())
return segmentations->front();
}
return nullptr;
}
/* Unload all task data nodes but spare the passed image data node.
*/
void QmitkSegmentationTaskListWidget::UnloadTasks(const mitk::DataNode* skip)
{
this->UnsubscribeFromActiveSegmentation();
if (m_TaskListNode.IsNotNull())
{
auto imageNodes = m_DataStorage->GetDerivations(m_TaskListNode, mitk::TNodePredicateDataType<mitk::Image>::New());
for (auto imageNode : *imageNodes)
{
m_DataStorage->Remove(m_DataStorage->GetDerivations(imageNode, nullptr, false));
if (imageNode != skip)
m_DataStorage->Remove(imageNode);
}
}
this->SetActiveTaskIndex(std::nullopt);
}
void QmitkSegmentationTaskListWidget::LoadNextUnfinishedTask()
{
const auto current = m_CurrentTaskIndex.value();
const auto numTasks = m_TaskList->GetNumberOfTasks();
for (size_t unboundNext = current; unboundNext < current + numTasks; ++unboundNext)
{
auto next = unboundNext % numTasks;
if (!m_TaskList->IsDone(next))
{
this->SetCurrentTaskIndex(next);
this->OnLoadButtonClicked();
break;
}
}
}
/* Load/activate the currently displayed task. The task must specify
* an image. The segmentation is either created from scratch with an optional
* name for the first label, possibly based on a label set preset specified by
* the task, or loaded as specified by the task. If a result file does
* exist, it is chosen as segmentation instead.
*/
void QmitkSegmentationTaskListWidget::LoadTask(mitk::DataNode::Pointer imageNode)
{
this->UnloadTasks(imageNode);
const auto current = m_CurrentTaskIndex.value();
mitk::Image::Pointer image;
mitk::LabelSetImage::Pointer segmentation;
try
{
if (imageNode.IsNull())
{
const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetImage(current));
image = mitk::IOUtil::Load<mitk::Image>(path.string());
}
const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetResult(current));
const auto interimPath = m_TaskList->GetInterimPath(path);
if (std::filesystem::exists(path))
{
segmentation = mitk::IOUtil::Load<mitk::LabelSetImage>(path.string());
}
else if (std::filesystem::exists(interimPath))
{
segmentation = mitk::IOUtil::Load<mitk::LabelSetImage>(interimPath.string());
}
else if (m_TaskList->HasSegmentation(current))
{
const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetSegmentation(current));
segmentation = mitk::IOUtil::Load<mitk::LabelSetImage>(path.string());
}
}
catch (const mitk::Exception&)
{
return;
}
if (imageNode.IsNull())
{
imageNode = mitk::DataNode::New();
imageNode->SetData(image);
m_DataStorage->Add(imageNode, m_TaskListNode);
mitk::RenderingManager::GetInstance()->InitializeViews(image->GetTimeGeometry());
}
else
{
image = static_cast<mitk::Image*>(imageNode->GetData());
}
auto name = "Task " + std::to_string(current + 1);
imageNode->SetName(name);
if (segmentation.IsNull())
{
mitk::Image::ConstPointer templateImage = image;
if (templateImage->GetDimension() > 3)
{
if (m_TaskList->HasDynamic(current))
{
if (!m_TaskList->GetDynamic(current))
templateImage = mitk::SegmentationHelper::GetStaticSegmentationTemplate(image);
}
else
{
QmitkStaticDynamicSegmentationDialog dialog(this);
dialog.SetReferenceImage(templateImage);
dialog.exec();
templateImage = dialog.GetSegmentationTemplate();
}
}
auto segmentationNode = mitk::LabelSetImageHelper::CreateNewSegmentationNode(imageNode, templateImage, name);
segmentation = static_cast<mitk::LabelSetImage*>(segmentationNode->GetData());
if (m_TaskList->HasPreset(current))
{
const auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetPreset(current));
mitk::MultiLabelIOHelper::LoadLabelSetImagePreset(path.string(), segmentation);
}
else
{
auto label = mitk::LabelSetImageHelper::CreateNewLabel(segmentation);
if (m_TaskList->HasLabelName(current))
label->SetName(m_TaskList->GetLabelName(current));
segmentation->GetActiveLabelSet()->AddLabel(label);
}
m_DataStorage->Add(segmentationNode, imageNode);
}
else
{
auto segmentationNode = mitk::DataNode::New();
segmentationNode->SetName(name);
segmentationNode->SetData(segmentation);
m_DataStorage->Add(segmentationNode, imageNode);
}
// Workaround for T29431. Remove when T26953 is fixed.
mitk::DICOMQIPropertyHelper::DeriveDICOMSourceProperties(image, segmentation);
auto prefs = GetSegmentationPreferences();
if (prefs != nullptr)
{
if (m_TaskList->HasLabelNameSuggestions(current))
{
auto path = m_TaskList->GetAbsolutePath(m_TaskList->GetLabelNameSuggestions(current));
prefs->PutBool("default label naming", false);
prefs->Put("label suggestions", path.string());
prefs->PutBool("replace standard suggestions", true);
prefs->PutBool("suggest once", true);
}
else
{
prefs->PutBool("default label naming", true);
prefs->Put("label suggestions", "");
}
}
m_UnsavedChanges = false;
this->SetActiveTaskIndex(current);
this->SubscribeToActiveSegmentation();
this->OnCurrentTaskChanged();
}
void QmitkSegmentationTaskListWidget::SubscribeToActiveSegmentation()
{
if (m_ActiveTaskIndex.has_value())
{
auto segmentationNode = this->GetSegmentationDataNode(m_ActiveTaskIndex.value());
if (segmentationNode != nullptr)
{
auto segmentation = static_cast<mitk::LabelSetImage*>(segmentationNode->GetData());
auto command = itk::SimpleMemberCommand<QmitkSegmentationTaskListWidget>::New();
command->SetCallbackFunction(this, &QmitkSegmentationTaskListWidget::OnSegmentationModified);
m_SegmentationModifiedObserverTag = segmentation->AddObserver(itk::ModifiedEvent(), command);
}
}
}
void QmitkSegmentationTaskListWidget::UnsubscribeFromActiveSegmentation()
{
if (m_ActiveTaskIndex.has_value() && m_SegmentationModifiedObserverTag.has_value())
{
auto segmentationNode = this->GetSegmentationDataNode(m_ActiveTaskIndex.value());
if (segmentationNode != nullptr)
{
auto segmentation = static_cast<mitk::LabelSetImage*>(segmentationNode->GetData());
segmentation->RemoveObserver(m_SegmentationModifiedObserverTag.value());
}
m_SegmentationModifiedObserverTag.reset();
}
}
void QmitkSegmentationTaskListWidget::OnSegmentationModified()
{
if (!m_UnsavedChanges)
{
m_UnsavedChanges = true;
if (m_ActiveTaskIndex.value() == m_CurrentTaskIndex)
this->UpdateDetailsLabel();
}
}
void QmitkSegmentationTaskListWidget::SetActiveTaskIndex(const std::optional<size_t>& index)
{
if (m_ActiveTaskIndex != index)
{
m_ActiveTaskIndex = index;
this->UpdateStoreAndAcceptButtons();
}
}
void QmitkSegmentationTaskListWidget::SetCurrentTaskIndex(const std::optional<size_t>& index)
{
if (m_CurrentTaskIndex != index)
{
m_CurrentTaskIndex = index;
this->OnCurrentTaskChanged();
-
}
}
bool QmitkSegmentationTaskListWidget::ActiveTaskIsShown() const
{
return m_ActiveTaskIndex.has_value() && m_CurrentTaskIndex.has_value() && m_ActiveTaskIndex == m_CurrentTaskIndex;
}
bool QmitkSegmentationTaskListWidget::HandleUnsavedChanges(const QString& alternativeTitle)
{
if (m_UnsavedChanges)
{
const auto active = m_ActiveTaskIndex.value();
const auto current = m_CurrentTaskIndex.value();
QString title;
if (alternativeTitle.isEmpty())
{
title = QString("Load task %1").arg(current + 1);
if (m_TaskList->HasName(current))
title += ": " + QString::fromStdString(m_TaskList->GetName(current));
}
else
{
title = alternativeTitle;
}
auto text = QString("The currently active task %1 ").arg(active + 1);
if (m_TaskList->HasName(active))
text += "(" + QString::fromStdString(m_TaskList->GetName(active)) + ") ";
text += "has unsaved changes.";
auto reply = QMessageBox::question(this, title, text, QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel);
switch (reply)
{
case QMessageBox::Save:
this->SaveActiveTask(!std::filesystem::exists(m_TaskList->GetResult(active)));
break;
case QMessageBox::Discard:
m_UnsavedChanges = false;
break;
default:
return false;
}
}
return true;
}
void QmitkSegmentationTaskListWidget::SaveActiveTask(bool saveAsIntermediateResult)
{
if (!m_ActiveTaskIndex.has_value())
return;
QApplication::setOverrideCursor(Qt::BusyCursor);
try
{
const auto active = m_ActiveTaskIndex.value();
m_TaskList->SaveTask(active, this->GetSegmentationDataNode(active)->GetData(), saveAsIntermediateResult);
this->OnUnsavedChangesSaved();
}
catch (const mitk::Exception& e)
{
MITK_ERROR << e;
}
QApplication::restoreOverrideCursor();
}
bool QmitkSegmentationTaskListWidget::OnPreShutdown()
{
return this->HandleUnsavedChanges(QStringLiteral("Application shutdown"));
}
void QmitkSegmentationTaskListWidget::OnPreviousTaskShortcutActivated()
{
m_Ui->previousButton->click();
}
void QmitkSegmentationTaskListWidget::OnNextTaskShortcutActivated()
{
m_Ui->nextButton->click();
}
+void QmitkSegmentationTaskListWidget::OnFindTaskShortcutActivated()
+{
+ m_Ui->findButton->click();
+}
+
void QmitkSegmentationTaskListWidget::OnLoadTaskShortcutActivated()
{
m_Ui->loadButton->click();
}
void QmitkSegmentationTaskListWidget::OnStoreInterimResultShortcutActivated()
{
m_Ui->storeButton->click();
}
void QmitkSegmentationTaskListWidget::OnAcceptSegmentationShortcutActivated()
{
m_Ui->acceptButton->click();
}
void QmitkSegmentationTaskListWidget::OnStoreButtonClicked()
{
this->SaveActiveTask(true);
}
void QmitkSegmentationTaskListWidget::OnAcceptButtonClicked()
{
auto* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
int activeToolId = -1;
if (toolManager != nullptr)
activeToolId = toolManager->GetActiveToolID();
this->SaveActiveTask();
this->LoadNextUnfinishedTask();
if (toolManager != nullptr)
toolManager->ActivateTool(activeToolId);
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.h b/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.h
index 33813a7722..ca90c1b26a 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.h
+++ b/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.h
@@ -1,99 +1,101 @@
/*============================================================================
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 QmitkSegmentationTaskListWidget_h
#define QmitkSegmentationTaskListWidget_h
#include <mitkSegmentationTaskList.h>
#include <MitkSegmentationUIExports.h>
#include <QmitkSingleNodeSelectionWidget.h>
#include <QWidget>
#include <optional>
class QFileSystemWatcher;
namespace Ui
{
class QmitkSegmentationTaskListWidget;
}
class MITKSEGMENTATIONUI_EXPORT QmitkSegmentationTaskListWidget : public QWidget
{
Q_OBJECT
public:
explicit QmitkSegmentationTaskListWidget(QWidget* parent = nullptr);
~QmitkSegmentationTaskListWidget() override;
void SetDataStorage(mitk::DataStorage* dataStorage);
void CheckDataStorage(const mitk::DataNode* removedNode = nullptr);
bool ActiveTaskIsShown() const;
void LoadNextUnfinishedTask();
void SaveActiveTask(bool saveAsIntermediateResult = false);
bool OnPreShutdown();
signals:
void ActiveTaskChanged(const std::optional<size_t>& index);
void CurrentTaskChanged(const std::optional<size_t>& index);
private:
void OnSelectionChanged(const QmitkSingleNodeSelectionWidget::NodeList& nodes);
void ResetControls();
void SetTaskList(mitk::SegmentationTaskList* task);
void ResetFileSystemWatcher();
void OnResultDirectoryChanged(const QString&);
void UpdateProgressBar();
void OnTaskListChanged(mitk::SegmentationTaskList* task);
void OnPreviousButtonClicked();
void OnNextButtonClicked();
+ void OnFindButtonClicked();
void OnCurrentTaskChanged();
void UpdateLoadButton();
void UpdateNavigationButtons();
void UpdateDetailsLabel();
void UpdateStoreAndAcceptButtons();
void OnLoadButtonClicked();
mitk::DataNode* GetImageDataNode(size_t index) const;
void UnloadTasks(const mitk::DataNode* skip = nullptr);
void LoadTask(mitk::DataNode::Pointer imageNode = nullptr);
void SubscribeToActiveSegmentation();
void UnsubscribeFromActiveSegmentation();
void OnSegmentationModified();
void SetActiveTaskIndex(const std::optional<size_t>& index);
void SetCurrentTaskIndex(const std::optional<size_t>& index);
bool HandleUnsavedChanges(const QString& alternativeTitle = QString());
mitk::DataNode* GetSegmentationDataNode(size_t index) const;
void OnUnsavedChangesSaved();
void OnPreviousTaskShortcutActivated();
void OnNextTaskShortcutActivated();
+ void OnFindTaskShortcutActivated();
void OnLoadTaskShortcutActivated();
void OnStoreInterimResultShortcutActivated();
void OnAcceptSegmentationShortcutActivated();
void OnStoreButtonClicked();
void OnAcceptButtonClicked();
Ui::QmitkSegmentationTaskListWidget* m_Ui;
QFileSystemWatcher* m_FileSystemWatcher;
mitk::DataStorage* m_DataStorage;
mitk::SegmentationTaskList::Pointer m_TaskList;
mitk::DataNode::Pointer m_TaskListNode;
std::optional<size_t> m_CurrentTaskIndex;
std::optional<size_t> m_ActiveTaskIndex;
std::optional<unsigned long> m_SegmentationModifiedObserverTag;
bool m_UnsavedChanges;
};
#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.ui b/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.ui
index 9fa63f8100..43beb9b1a7 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.ui
+++ b/Modules/SegmentationUI/Qmitk/QmitkSegmentationTaskListWidget.ui
@@ -1,240 +1,259 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmitkSegmentationTaskListWidget</class>
<widget class="QWidget" name="QmitkSegmentationTaskListWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>288</width>
<height>478</height>
</rect>
</property>
<property name="title" stdset="0">
<string>Segmentation Task List</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QmitkSingleNodeSelectionWidget" name="selectionWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="value">
<number>0</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="format">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="previousButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="toolTip">
<string>Previous subtask</string>
</property>
<property name="arrowType">
<enum>Qt::LeftArrow</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="loadButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="text">
<string>Load subtask</string>
</property>
</widget>
</item>
+ <item>
+ <widget class="QToolButton" name="findButton">
+ <property name="minimumSize">
+ <size>
+ <width>40</width>
+ <height>40</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Find task...</string>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QToolButton" name="nextButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="toolTip">
<string>Next subtask</string>
</property>
<property name="arrowType">
<enum>Qt::RightArrow</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="detailsLabel">
<property name="text">
<string/>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="storeButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="toolTip">
<string>Save interim segmentation</string>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="acceptButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
<property name="toolTip">
<string>Save and accept segmentation</string>
</property>
<property name="text">
<string>Accept segmentation</string>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QmitkSingleNodeSelectionWidget</class>
<extends>QWidget</extends>
<header location="global">QmitkSingleNodeSelectionWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.cpp b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.cpp
index 8cc7ecb0e2..50c6fe88f9 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.cpp
@@ -1,182 +1,182 @@
/*============================================================================
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.s
============================================================================*/
#include "QmitkSetupVirtualEnvUtil.h"
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <QStandardPaths>
#include <itkCommand.h>
QmitkSetupVirtualEnvUtil::QmitkSetupVirtualEnvUtil()
{
m_BaseDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() +
qApp->organizationName() + QDir::separator();
}
QmitkSetupVirtualEnvUtil::QmitkSetupVirtualEnvUtil(const QString &baseDir)
{
m_BaseDir = baseDir;
}
QString& QmitkSetupVirtualEnvUtil::GetBaseDir()
{
return m_BaseDir;
}
QString QmitkSetupVirtualEnvUtil::GetVirtualEnvPath()
{
return m_venvPath;
}
QString& QmitkSetupVirtualEnvUtil::GetSystemPythonPath()
{
return m_SysPythonPath;
}
QString& QmitkSetupVirtualEnvUtil::GetPythonPath()
{
return m_PythonPath;
}
QString& QmitkSetupVirtualEnvUtil::GetPipPath()
{
return m_PipPath;
}
void QmitkSetupVirtualEnvUtil::SetVirtualEnvPath(const QString &path)
{
m_venvPath = path;
}
void QmitkSetupVirtualEnvUtil::SetPipPath(const QString &path)
{
m_PipPath = path;
}
void QmitkSetupVirtualEnvUtil::SetPythonPath(const QString &path)
{
if (this->IsPythonPath(path))
{
m_PythonPath = path;
}
else
{
MITK_INFO << "Python was not detected in " + path.toStdString();
}
}
void QmitkSetupVirtualEnvUtil::SetSystemPythonPath(const QString &path)
{
if (this->IsPythonPath(path))
{
m_SysPythonPath = path;
}
else
{
MITK_INFO << "Python was not detected in " + path.toStdString();
}
}
void QmitkSetupVirtualEnvUtil::PrintProcessEvent(itk::Object * /*pCaller*/, const itk::EventObject &e, void *)
{
std::string testCOUT;
std::string testCERR;
const auto *pEvent = dynamic_cast<const mitk::ExternalProcessStdOutEvent *>(&e);
if (pEvent)
{
testCOUT = testCOUT + pEvent->GetOutput();
MITK_INFO << testCOUT;
}
const auto *pErrEvent = dynamic_cast<const mitk::ExternalProcessStdErrEvent *>(&e);
if (pErrEvent)
{
testCERR = testCERR + pErrEvent->GetOutput();
MITK_ERROR << testCERR;
}
}
void QmitkSetupVirtualEnvUtil::InstallPytorch(const std::string &workingDir,
void (*callback)(itk::Object *, const itk::EventObject &, void *))
{
mitk::ProcessExecutor::ArgumentListType args;
auto spExec = mitk::ProcessExecutor::New();
auto spCommand = itk::CStyleCommand::New();
spCommand->SetCallback(callback);
spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand);
args.push_back("-m");
args.push_back("pip");
args.push_back("install");
args.push_back("light-the-torch");
spExec->Execute(workingDir, "python", args);
PipInstall("torch", workingDir, callback, "ltt");
}
void QmitkSetupVirtualEnvUtil::InstallPytorch()
{
this->InstallPytorch(GetPythonPath().toStdString(), &PrintProcessEvent);
}
void QmitkSetupVirtualEnvUtil::PipInstall(const std::string &library,
const std::string &workingDir,
void (*callback)(itk::Object *, const itk::EventObject &, void *),
const std::string &command)
{
mitk::ProcessExecutor::ArgumentListType args;
auto spExec = mitk::ProcessExecutor::New();
auto spCommand = itk::CStyleCommand::New();
spCommand->SetCallback(callback);
spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand);
args.push_back("install");
args.push_back(library);
spExec->Execute(workingDir, command, args);
}
void QmitkSetupVirtualEnvUtil::PipInstall(const std::string &library,
void (*callback)(itk::Object*, const itk::EventObject&, void*),
const std::string& command)
{
this->PipInstall(library, this->GetPipPath().toStdString(), callback, command);
}
void QmitkSetupVirtualEnvUtil::ExecutePython(const std::string &pythonCode,
const std::string &workingDir,
void (*callback)(itk::Object *, const itk::EventObject &, void *),
const std::string &command)
{
mitk::ProcessExecutor::ArgumentListType args;
auto spExec = mitk::ProcessExecutor::New();
auto spCommand = itk::CStyleCommand::New();
spCommand->SetCallback(callback);
spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand);
args.push_back("-c");
args.push_back(pythonCode);
spExec->Execute(workingDir, command, args);
}
void QmitkSetupVirtualEnvUtil::ExecutePython(const std::string &args,
void (*callback)(itk::Object *, const itk::EventObject &, void *),
const std::string &command)
{
this->ExecutePython(args, this->GetPythonPath().toStdString(), callback, command);
}
bool QmitkSetupVirtualEnvUtil::IsPythonPath(const QString &pythonPath)
{
QString fullPath = pythonPath;
bool isExists =
#ifdef _WIN32
QFile::exists(fullPath + QDir::separator() + QString("python.exe"));
#else
QFile::exists(fullPath + QDir::separator() + QString("python3"));
#endif
return isExists;
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h
index 748334bc45..3f822b66dc 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h
+++ b/Modules/SegmentationUI/Qmitk/QmitkSetupVirtualEnvUtil.h
@@ -1,195 +1,195 @@
/*============================================================================
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.s
============================================================================*/
#ifndef QmitkSetupVirtualEnvUtil_h_Included
#define QmitkSetupVirtualEnvUtil_h_Included
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include "mitkProcessExecutor.h"
#include <MitkSegmentationUIExports.h>
#include <QString>
#include <QDir>
#include <QApplication>
/**
* @brief Abstract Class to Setup a python virtual environment and pip install required packages.
* Derive this class for creating installer for the respective tool.
*/
class MITKSEGMENTATIONUI_EXPORT QmitkSetupVirtualEnvUtil
{
public:
QmitkSetupVirtualEnvUtil(const QString& baseDir);
QmitkSetupVirtualEnvUtil();
/**
* @brief Implement the method in child class
* to setup the virtual environment.
*/
virtual bool SetupVirtualEnv(const QString& venvName) = 0;
/**
* @brief Get the Virtual Env Path object. Override this method in the respective
* tool installer class.
*
* @return QString
*/
virtual QString GetVirtualEnvPath();
/**
* @brief Function to Pip install a library package given the location of
* pip3 executable.
* Any callback function can be passed to process the output.
*
* @param library
* @param workingDir
* @param callback
* @param command
*/
void PipInstall(const std::string &library,
const std::string &workingDir,
void (*callback)(itk::Object *, const itk::EventObject &, void *),
const std::string &command = "pip3");
/**
* @brief Overloaded function to Pip install a library function.
*
* @param library
* @param callback
* @param command
*/
void PipInstall(const std::string &library,
void (*callback)(itk::Object *, const itk::EventObject &, void *),
const std::string &command = "pip3");
/**
* @brief Function to execute any python code given a python path.
* Any callback function can be passed to process the output.
*
* @param args
* @param pythonPath
* @param callback
* @param command
*/
void ExecutePython(const std::string &args,
const std::string &pythonPath,
void (*callback)(itk::Object *, const itk::EventObject &, void *),
const std::string &command = "python");
/**
* @brief Overloaded function to Execute Python code.
* Any callback function can be passed to process the output.
*
* @param args
* @param callback
* @param command
*/
void ExecutePython(const std::string &args,
void (*callback)(itk::Object *, const itk::EventObject &, void *),
const std::string &command = "python");
/**
* @brief Installs pytorch using light-the-torch package, correctly identifying cuda version.
* Requires location of pip3 executable.
* Any callback function can be passed to process the output.
*
* @param workingDir
* @param callback
*/
void InstallPytorch(const std::string &workingDir, void (*callback)(itk::Object *, const itk::EventObject &, void *));
/**
* @brief Overloaded function to install pytorch using light-the-torch package, correctly
* identifying cuda version.
*/
void InstallPytorch();
/**
* @brief Get the Base Dir object
*
* @return QString&
*/
QString& GetBaseDir();
/**
* @brief Get the System Python Path object
*
* @return QString&
*/
QString& GetSystemPythonPath();
/**
* @brief Get the Python Path object
*
* @return QString&
*/
QString& GetPythonPath();
/**
* @brief Get the Pip Path object
*
* @return QString&
*/
QString& GetPipPath();
/**
* @brief Set the System Python Path object
*
* @param path
*/
void SetSystemPythonPath(const QString& path);
/**
* @brief Set the Python Path object
*
* @param path
*/
void SetPythonPath(const QString& path);
/**
* @brief Set the Pip Path object
*
* @param path
*/
void SetPipPath(const QString& path);
/**
* @brief Set the Virtual Env Path object
*
* @param path
*/
void SetVirtualEnvPath(const QString &path);
/**
* @brief Check if the path provide has python executable or not.
*
* @param pythonPath
* @return true
* @return false
*/
bool IsPythonPath(const QString &pythonPath);
/**
* @brief Function can be used as callback to simply print out all the process execution output
* parsed out from itk::EventObject.
*
*/
static void PrintProcessEvent(itk::Object *, const itk::EventObject &e, void *);
private:
QString m_PythonPath;
QString m_PipPath;
QString m_BaseDir;
QString m_venvPath;
QString m_SysPythonPath;
};
#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
index 86f1b19d0c..912b186306 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
@@ -1,1999 +1,2039 @@
/*============================================================================
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 "QmitkSlicesInterpolator.h"
#include "QmitkRenderWindow.h"
#include "QmitkRenderWindowWidget.h"
#include "mitkApplyDiffImageOperation.h"
#include "mitkColorProperty.h"
#include "mitkCoreObjectFactory.h"
#include "mitkDiffImageApplier.h"
#include "mitkInteractionConst.h"
#include "mitkLevelWindowProperty.h"
#include "mitkOperationEvent.h"
#include "mitkProgressBar.h"
#include "mitkProperties.h"
#include "mitkRenderingManager.h"
#include "mitkSegTool2D.h"
#include "mitkSliceNavigationController.h"
#include "mitkSurfaceToImageFilter.h"
+#include <mitkTimeNavigationController.h>
#include "mitkToolManager.h"
#include "mitkUndoController.h"
#include <mitkExtractSliceFilter.h>
#include <mitkPlanarCircle.h>
#include <mitkImageReadAccessor.h>
#include <mitkImageTimeSelector.h>
#include <mitkImageWriteAccessor.h>
#include <mitkPlaneProposer.h>
#include <mitkUnstructuredGridClusteringFilter.h>
#include <mitkVtkImageOverwrite.h>
#include <mitkShapeBasedInterpolationAlgorithm.h>
#include <itkCommand.h>
#include <mitkImageToContourFilter.h>
#include <mitkImagePixelReadAccessor.h>
// Includes for the merge operation
#include "mitkImageToContourFilter.h"
#include <mitkLabelSetImage.h>
#include <QCheckBox>
#include <QCursor>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QVBoxLayout>
#include <vtkDoubleArray.h>
#include <vtkFieldData.h>
#include <vtkPolyVertex.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>
#include <array>
#include <atomic>
#include <thread>
#include <vector>
namespace
{
template <typename T = mitk::BaseData>
itk::SmartPointer<T> GetData(const mitk::DataNode* dataNode)
{
return nullptr != dataNode
? dynamic_cast<T*>(dataNode->GetData())
: nullptr;
}
}
float SURFACE_COLOR_RGB[3] = {0.49f, 1.0f, 0.16f};
-const std::map<QAction *, mitk::SliceNavigationController *> QmitkSlicesInterpolator::createActionToSlicer(const QList<QmitkRenderWindow*>& windows)
+const QmitkSlicesInterpolator::ActionToSliceDimensionMapType QmitkSlicesInterpolator::CreateActionToSlicer(const QList<QmitkRenderWindow*>& windows)
{
std::map<QAction *, mitk::SliceNavigationController *> actionToSliceDimension;
for (auto* window : windows)
{
std::string windowName;
auto renderWindowWidget = dynamic_cast<QmitkRenderWindowWidget*>(window->parentWidget());
if (renderWindowWidget)
{
windowName = renderWindowWidget->GetCornerAnnotationText();
}
else
{
windowName = window->GetRenderer()->GetName();
}
auto slicer = window->GetSliceNavigationController();
actionToSliceDimension[new QAction(QString::fromStdString(windowName), nullptr)] = slicer;
}
return actionToSliceDimension;
}
// Check whether the given contours are coplanar
bool AreContoursCoplanar(mitk::SurfaceInterpolationController::ContourPositionInformation leftHandSide,
mitk::SurfaceInterpolationController::ContourPositionInformation rightHandSide)
{
// Here we check two things:
// 1. Whether the normals of both contours are at least parallel
// 2. Whether both contours lie in the same plane
// Check for coplanarity:
// a. Span a vector between two points one from each contour
// b. Calculate dot product for the vector and one of the normals
// c. If the dot is zero the two vectors are orthogonal and the contours are coplanar
double vec[3];
vec[0] = leftHandSide.ContourPoint[0] - rightHandSide.ContourPoint[0];
vec[1] = leftHandSide.ContourPoint[1] - rightHandSide.ContourPoint[1];
vec[2] = leftHandSide.ContourPoint[2] - rightHandSide.ContourPoint[2];
double n[3];
n[0] = rightHandSide.ContourNormal[0];
n[1] = rightHandSide.ContourNormal[1];
n[2] = rightHandSide.ContourNormal[2];
double dot = vtkMath::Dot(n, vec);
double n2[3];
n2[0] = leftHandSide.ContourNormal[0];
n2[1] = leftHandSide.ContourNormal[1];
n2[2] = leftHandSide.ContourNormal[2];
// The normals of both contours have to be parallel but not of the same orientation
double lengthLHS = leftHandSide.ContourNormal.GetNorm();
double lengthRHS = rightHandSide.ContourNormal.GetNorm();
double dot2 = vtkMath::Dot(n, n2);
bool contoursParallel = mitk::Equal(fabs(lengthLHS * lengthRHS), fabs(dot2), 0.001);
if (mitk::Equal(dot, 0.0, 0.001) && contoursParallel)
return true;
else
return false;
}
mitk::Image::Pointer ExtractSliceFromImage(mitk::Image* image,
const mitk::PlaneGeometry * contourPlane,
unsigned int timeStep)
{
vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
// set to false to extract a slice
reslice->SetOverwriteMode(false);
reslice->Modified();
mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
extractor->SetInput(image);
extractor->SetTimeStep(timeStep);
extractor->SetWorldGeometry(contourPlane);
extractor->SetVtkOutputRequest(false);
extractor->SetResliceTransformByGeometry(image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
extractor->Update();
mitk::Image::Pointer slice = extractor->GetOutput();
return slice;
}
template <unsigned int VImageDimension = 3>
std::vector<mitk::Label::PixelType> GetPixelValuesPresentInImage(mitk::LabelSetImage* labelSetImage)
{
std::vector<mitk::Label::PixelType> pixelsPresent;
mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage);
std::size_t numberOfPixels = 1;
for (size_t dim = 0; dim < VImageDimension; ++dim)
numberOfPixels *= static_cast<std::size_t>(readAccessor.GetDimension(dim));
auto src = readAccessor.GetData();
for (std::size_t i = 0; i < numberOfPixels; ++i)
{
mitk::Label::PixelType pixelVal = *(src + i);
if ( (std::find(pixelsPresent.begin(), pixelsPresent.end(), pixelVal) == pixelsPresent.end()) && (pixelVal != mitk::LabelSetImage::UnlabeledValue) )
pixelsPresent.push_back(pixelVal);
}
return pixelsPresent;
}
template <unsigned int VImageDimension = 3>
ModifyLabelActionTrigerred ModifyLabelProcessing(mitk::LabelSetImage* labelSetImage,
mitk::SurfaceInterpolationController::Pointer surfaceInterpolator,
unsigned int timePoint)
{
auto currentLayerID = labelSetImage->GetActiveLayer();
auto numTimeSteps = labelSetImage->GetTimeSteps();
ModifyLabelActionTrigerred actionTriggered = ModifyLabelActionTrigerred::Null;
- mitk::SurfaceInterpolationController::ContourPositionInformationList &currentContourList =
- surfaceInterpolator->GetContours(timePoint, currentLayerID);
+ auto* currentContourList = surfaceInterpolator->GetContours(timePoint, currentLayerID);
+
+ while (nullptr == currentContourList)
+ {
+ surfaceInterpolator->OnAddLayer();
+ currentContourList = surfaceInterpolator->GetContours(timePoint, currentLayerID);
+ }
mitk::LabelSetImage::Pointer labelSetImage2 = labelSetImage->Clone();
mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage2.GetPointer());
- for (auto& contour : currentContourList)
+ for (auto& contour : *currentContourList)
{
mitk::Label::PixelType contourPixelValue;
itk::Index<3> itkIndex;
labelSetImage2->GetGeometry()->WorldToIndex(contour.ContourPoint, itkIndex);
if (VImageDimension == 4)
{
itk::Index<VImageDimension> time3DIndex;
for (size_t i = 0; i < itkIndex.size(); ++i)
time3DIndex[i] = itkIndex[i];
time3DIndex[3] = timePoint;
contourPixelValue = readAccessor.GetPixelByIndexSafe(time3DIndex);
}
else if (VImageDimension == 3)
{
itk::Index<VImageDimension> geomIndex;
for (size_t i = 0; i < itkIndex.size(); ++i)
geomIndex[i] = itkIndex[i];
contourPixelValue = readAccessor.GetPixelByIndexSafe(geomIndex);
}
if (contour.LabelValue != contourPixelValue)
{
if (contourPixelValue == 0) // Erase label
{
for (size_t t = 0; t < numTimeSteps; ++t)
surfaceInterpolator->RemoveContours(contour.LabelValue, t, currentLayerID);
actionTriggered = ModifyLabelActionTrigerred::Erase;
}
else
{
contour.LabelValue = contourPixelValue;
actionTriggered = ModifyLabelActionTrigerred::Merge;
}
}
}
return actionTriggered;
}
QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget *parent, const char * /*name*/)
: QWidget(parent),
m_Interpolator(mitk::SegmentationInterpolationController::New()),
m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()),
m_ToolManager(nullptr),
m_Initialized(false),
m_LastSNC(nullptr),
m_LastSliceIndex(0),
m_2DInterpolationEnabled(false),
m_3DInterpolationEnabled(false),
m_PreviousActiveLabelValue(0),
m_CurrentActiveLabelValue(0),
m_PreviousLayerIndex(0),
m_CurrentLayerIndex(0),
m_FirstRun(true)
{
m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this);
QVBoxLayout *vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode);
m_EdgeDetector = mitk::FeatureBasedEdgeDetectionFilter::New();
m_PointScorer = mitk::PointCloudScoringFilter::New();
m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode);
m_CmbInterpolation->addItem("Disabled");
m_CmbInterpolation->addItem("2-Dimensional");
m_CmbInterpolation->addItem("3-Dimensional");
vboxLayout->addWidget(m_CmbInterpolation);
m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_BtnApply2D);
m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_BtnApplyForAllSlices2D);
m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_BtnApply3D);
// T28261
// m_BtnSuggestPlane = new QPushButton("Suggest a plane", m_GroupBoxEnableExclusiveInterpolationMode);
// vboxLayout->addWidget(m_BtnSuggestPlane);
m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_BtnReinit3DInterpolation);
m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode);
vboxLayout->addWidget(m_ChkShowPositionNodes);
this->HideAllInterpolationControls();
connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int)));
connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()));
connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked()));
connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked()));
connect(m_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation()));
connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool)));
connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool)));
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode);
this->setLayout(layout);
itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command =
itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
command->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged);
InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver(itk::ModifiedEvent(), command);
itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command2 =
itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged);
SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver(itk::ModifiedEvent(), command2);
auto command3 = itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
command3->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationAborted);
InterpolationAbortedObserverTag = m_Interpolator->AddObserver(itk::AbortEvent(), command3);
// feedback node and its visualization properties
m_FeedbackNode = mitk::DataNode::New();
mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties(m_FeedbackNode);
m_FeedbackNode->SetProperty("binary", mitk::BoolProperty::New(true));
m_FeedbackNode->SetProperty("outline binary", mitk::BoolProperty::New(true));
m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0));
m_FeedbackNode->SetProperty("texture interpolation", mitk::BoolProperty::New(false));
m_FeedbackNode->SetProperty("layer", mitk::IntProperty::New(20));
m_FeedbackNode->SetProperty("levelwindow", mitk::LevelWindowProperty::New(mitk::LevelWindow(0, 1)));
m_FeedbackNode->SetProperty("name", mitk::StringProperty::New("Interpolation feedback"));
m_FeedbackNode->SetProperty("opacity", mitk::FloatProperty::New(0.8));
m_FeedbackNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_InterpolatedSurfaceNode = mitk::DataNode::New();
m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
m_InterpolatedSurfaceNode->SetProperty("name", mitk::StringProperty::New("Surface Interpolation feedback"));
m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5));
m_InterpolatedSurfaceNode->SetProperty("line width", mitk::FloatProperty::New(4.0f));
m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_InterpolatedSurfaceNode->SetVisibility(false);
m_3DContourNode = mitk::DataNode::New();
m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(0.0, 0.0, 0.0));
m_3DContourNode->SetProperty("hidden object", mitk::BoolProperty::New(true));
m_3DContourNode->SetProperty("name", mitk::StringProperty::New("Drawn Contours"));
m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME));
m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f));
m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true));
m_3DContourNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
m_3DContourNode->SetVisibility(false);
QWidget::setContentsMargins(0, 0, 0, 0);
if (QWidget::layout() != nullptr)
{
QWidget::layout()->setContentsMargins(0, 0, 0, 0);
}
// For running 3D Interpolation in background
// create a QFuture and a QFutureWatcher
connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer()));
connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished()));
connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer()));
m_Timer = new QTimer(this);
connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor()));
}
void QmitkSlicesInterpolator::SetDataStorage(mitk::DataStorage::Pointer storage)
{
if (m_DataStorage == storage)
{
return;
}
if (m_DataStorage.IsNotNull())
{
m_DataStorage->RemoveNodeEvent.RemoveListener(
mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
);
}
m_DataStorage = storage;
m_SurfaceInterpolator->SetDataStorage(storage);
if (m_DataStorage.IsNotNull())
{
m_DataStorage->RemoveNodeEvent.AddListener(
mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
);
}
}
mitk::DataStorage *QmitkSlicesInterpolator::GetDataStorage()
{
if (m_DataStorage.IsNotNull())
{
return m_DataStorage;
}
else
{
return nullptr;
}
}
void QmitkSlicesInterpolator::InitializeWindow(QmitkRenderWindow* window)
{
auto slicer = window->GetSliceNavigationController();
if (slicer == nullptr)
{
MITK_WARN << "Tried setting up interpolation for a render window that does not have a slice navigation controller set";
return;
}
// Has to be initialized
m_LastSNC = slicer;
- m_TimePoints.insert(slicer, slicer->GetSelectedTimePoint());
itk::MemberCommand<QmitkSlicesInterpolator>::Pointer deleteCommand =
itk::MemberCommand<QmitkSlicesInterpolator>::New();
deleteCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted);
m_ControllerToDeleteObserverTag[slicer] = slicer->AddObserver(itk::DeleteEvent(), deleteCommand);
- itk::MemberCommand<QmitkSlicesInterpolator>::Pointer timeChangedCommand =
- itk::MemberCommand<QmitkSlicesInterpolator>::New();
- timeChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnTimeChanged);
- m_ControllerToTimeObserverTag[slicer] = slicer->AddObserver(mitk::SliceNavigationController::TimeGeometryEvent(nullptr, 0), timeChangedCommand);
-
itk::MemberCommand<QmitkSlicesInterpolator>::Pointer sliceChangedCommand =
itk::MemberCommand<QmitkSlicesInterpolator>::New();
sliceChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceChanged);
m_ControllerToSliceObserverTag[slicer] = slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), sliceChangedCommand);
}
void QmitkSlicesInterpolator::Initialize(mitk::ToolManager *toolManager,
const QList<QmitkRenderWindow*>& windows)
{
Q_ASSERT(!windows.empty());
if (m_Initialized)
{
// remove old observers
this->Uninitialize();
}
m_ToolManager = toolManager;
if (m_ToolManager)
{
// set enabled only if a segmentation is selected
mitk::DataNode *node = m_ToolManager->GetWorkingData(0);
QWidget::setEnabled(node != nullptr);
// react whenever the set of selected segmentation changes
m_ToolManager->WorkingDataChanged +=
mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate<QmitkSlicesInterpolator>(
this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ itk::MemberCommand<QmitkSlicesInterpolator>::Pointer timeChangedCommand =
+ itk::MemberCommand<QmitkSlicesInterpolator>::New();
+ timeChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnTimeChanged);
+ m_ControllerToTimeObserverTag =
+ timeNavigationController->AddObserver(mitk::TimeNavigationController::TimeEvent(0), timeChangedCommand);
+
+ m_TimePoint = timeNavigationController->GetSelectedTimePoint();
+
// connect to the slice navigation controller. after each change, call the interpolator
for (auto* window : windows)
{
this->InitializeWindow(window);
}
- m_ActionToSlicer = createActionToSlicer(windows);
+ m_ActionToSlicerMap = CreateActionToSlicer(windows);
}
m_Initialized = true;
}
void QmitkSlicesInterpolator::Uninitialize()
{
if (m_ToolManager.IsNotNull())
{
m_ToolManager->WorkingDataChanged -=
mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
}
- for (auto* slicer : m_ControllerToTimeObserverTag.keys())
+
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ timeNavigationController->RemoveObserver(m_ControllerToTimeObserverTag);
+
+for (auto* slicer : m_ControllerToSliceObserverTag.keys())
{
slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer));
- slicer->RemoveObserver(m_ControllerToTimeObserverTag.take(slicer));
slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer));
}
this->ClearSegmentationObservers();
-
- m_ActionToSlicer.clear();
+ m_ActionToSlicerMap.clear();
m_ToolManager = nullptr;
m_Initialized = false;
}
QmitkSlicesInterpolator::~QmitkSlicesInterpolator()
{
if (m_Initialized)
{
// remove old observers
this->Uninitialize();
}
WaitForFutures();
if (m_DataStorage.IsNotNull())
{
m_DataStorage->RemoveNodeEvent.RemoveListener(
mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
);
if (m_DataStorage->Exists(m_3DContourNode))
m_DataStorage->Remove(m_3DContourNode);
if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
m_DataStorage->Remove(m_InterpolatedSurfaceNode);
}
// remove observer
m_Interpolator->RemoveObserver(InterpolationAbortedObserverTag);
m_Interpolator->RemoveObserver(InterpolationInfoChangedObserverTag);
m_SurfaceInterpolator->RemoveObserver(SurfaceInterpolationInfoChangedObserverTag);
m_SurfaceInterpolator->UnsetSelectedImage();
delete m_Timer;
}
/**
External enableization...
*/
void QmitkSlicesInterpolator::setEnabled(bool enable)
{
QWidget::setEnabled(enable);
// Set the gui elements of the different interpolation modi enabled
if (enable)
{
if (m_2DInterpolationEnabled)
{
this->Show2DInterpolationControls(true);
m_Interpolator->Activate2DInterpolation(true);
}
else if (m_3DInterpolationEnabled)
{
this->Show3DInterpolationControls(true);
this->Show3DInterpolationResult(true);
}
}
// Set all gui elements of the interpolation disabled
else
{
this->HideAllInterpolationControls();
this->Show3DInterpolationResult(false);
}
}
void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status)
{
OnInterpolationActivated(status);
m_Interpolator->Activate2DInterpolation(status);
}
void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status)
{
On3DInterpolationActivated(status);
}
void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status)
{
if (status)
{
OnInterpolationActivated(!status);
On3DInterpolationActivated(!status);
this->Show3DInterpolationResult(false);
}
}
void QmitkSlicesInterpolator::HideAllInterpolationControls()
{
this->Show2DInterpolationControls(false);
this->Show3DInterpolationControls(false);
}
void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show)
{
m_BtnApply2D->setVisible(show);
m_BtnApplyForAllSlices2D->setVisible(show);
}
void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show)
{
m_BtnApply3D->setVisible(show);
// T28261
// m_BtnSuggestPlane->setVisible(show);
m_ChkShowPositionNodes->setVisible(show);
m_BtnReinit3DInterpolation->setVisible(show);
}
void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index)
{
switch (index)
{
case 0: // Disabled
m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation");
this->HideAllInterpolationControls();
this->OnInterpolationActivated(false);
this->On3DInterpolationActivated(false);
this->Show3DInterpolationResult(false);
m_Interpolator->Activate2DInterpolation(false);
break;
case 1: // 2D
m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
this->HideAllInterpolationControls();
this->Show2DInterpolationControls(true);
this->OnInterpolationActivated(true);
this->On3DInterpolationActivated(false);
+ this->Show3DInterpolationResult(false);
m_Interpolator->Activate2DInterpolation(true);
break;
case 2: // 3D
m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
this->HideAllInterpolationControls();
this->Show3DInterpolationControls(true);
this->OnInterpolationActivated(false);
this->On3DInterpolationActivated(true);
m_Interpolator->Activate2DInterpolation(false);
break;
default:
MITK_ERROR << "Unknown interpolation method!";
m_CmbInterpolation->setCurrentIndex(0);
break;
}
}
void QmitkSlicesInterpolator::OnShowMarkers(bool state)
{
mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers =
m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)));
for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End();
++it)
{
it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state));
}
}
void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified()
{
this->ClearSegmentationObservers();
if (m_ToolManager->GetWorkingData(0) != nullptr)
{
m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
m_BtnReinit3DInterpolation->setEnabled(true);
try {
if (m_SegmentationObserverTags.find(labelSetImage) == m_SegmentationObserverTags.end())
{
auto command2 = itk::MemberCommand<QmitkSlicesInterpolator>::New();
command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnModifyLabelChanged);
auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
m_SegmentationObserverTags[workingImage] = workingImage->AddObserver(itk::ModifiedEvent(), command2);
}
}
catch (const std::exception& e)
{
MITK_ERROR << "Error casting node data to LabelSetImage\n";
}
}
else
{
// If no workingdata is set, remove the interpolation feedback
this->GetDataStorage()->Remove(m_FeedbackNode);
m_FeedbackNode->SetData(nullptr);
this->GetDataStorage()->Remove(m_3DContourNode);
m_3DContourNode->SetData(nullptr);
this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode);
m_InterpolatedSurfaceNode->SetData(nullptr);
m_BtnReinit3DInterpolation->setEnabled(false);
m_CmbInterpolation->setCurrentIndex(0);
return;
}
// Updating the current selected segmentation for the 3D interpolation
this->SetCurrentContourListID();
if (m_2DInterpolationEnabled)
{
OnInterpolationActivated(true); // re-initialize if needed
}
}
void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified()
{
}
void QmitkSlicesInterpolator::OnTimeChanged(itk::Object *sender, const itk::EventObject &e)
{
- // Check if we really have a GeometryTimeEvent
- if (!dynamic_cast<const mitk::SliceNavigationController::GeometryTimeEvent *>(&e))
+ if (!dynamic_cast<const mitk::TimeNavigationController::TimeEvent*>(&e))
+ {
return;
+ }
- mitk::SliceNavigationController *slicer = dynamic_cast<mitk::SliceNavigationController *>(sender);
- Q_ASSERT(slicer);
+ const auto* timeNavigationController = dynamic_cast<mitk::TimeNavigationController*>(sender);
+ if (nullptr == timeNavigationController)
+ {
+ return;
+ }
- const auto timePoint = slicer->GetSelectedTimePoint();
- m_TimePoints[slicer] = timePoint;
+ m_TimePoint = timeNavigationController->GetSelectedTimePoint();
if (m_Watcher.isRunning())
m_Watcher.waitForFinished();
- if (timePoint != m_SurfaceInterpolator->GetCurrentTimePoint())
+ if (m_TimePoint != m_SurfaceInterpolator->GetCurrentTimePoint())
{
- m_SurfaceInterpolator->SetCurrentTimePoint(timePoint);
+ m_SurfaceInterpolator->SetCurrentTimePoint(m_TimePoint);
if (m_3DInterpolationEnabled)
{
m_3DContourNode->SetData(nullptr);
m_InterpolatedSurfaceNode->SetData(nullptr);
}
m_SurfaceInterpolator->Modified();
}
- if (m_LastSNC == slicer)
+ if (nullptr == m_LastSNC)
{
- slicer->SendSlice(); // will trigger a new interpolation
+ return;
+ }
+
+ if (TranslateAndInterpolateChangedSlice(m_LastSNC->GetCreatedWorldGeometry()))
+ {
+ m_LastSNC->GetRenderer()->RequestUpdate();
}
}
void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e)
{
- // Check whether we really have a GeometrySliceEvent
- if (!dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent *>(&e))
+ if (!dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e))
+ {
return;
+ }
- mitk::SliceNavigationController *slicer = dynamic_cast<mitk::SliceNavigationController *>(sender);
+ auto sliceNavigationController = dynamic_cast<mitk::SliceNavigationController*>(sender);
+ if (nullptr == sliceNavigationController)
+ {
+ return;
+ }
if(m_2DInterpolationEnabled)
{
this->On2DInterpolationEnabled(m_2DInterpolationEnabled);
- }
- if (TranslateAndInterpolateChangedSlice(e, slicer))
+ }
+
+ if (TranslateAndInterpolateChangedSlice(e, sliceNavigationController))
{
- slicer->GetRenderer()->RequestUpdate();
+ sliceNavigationController->GetRenderer()->RequestUpdate();
}
}
-bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject &e,
- mitk::SliceNavigationController *slicer)
+bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e,
+ mitk::SliceNavigationController* sliceNavigationController)
+{
+ const mitk::SliceNavigationController::GeometrySliceEvent* event =
+ dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e);
+
+ mitk::TimeGeometry* timeGeometry = event->GetTimeGeometry();
+ m_LastSNC = sliceNavigationController;
+
+ return this->TranslateAndInterpolateChangedSlice(timeGeometry);
+}
+
+bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const mitk::TimeGeometry* timeGeometry)
{
if (!m_2DInterpolationEnabled)
+ {
return false;
+ }
- try
+ if (nullptr == timeGeometry)
{
- const mitk::SliceNavigationController::GeometrySliceEvent &event =
- dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent &>(e);
+ return false;
+ }
- mitk::TimeGeometry *tsg = event.GetTimeGeometry();
- if (tsg && m_TimePoints.contains(slicer) && tsg->IsValidTimePoint(m_TimePoints[slicer]))
- {
- mitk::SlicedGeometry3D *slicedGeometry =
- dynamic_cast<mitk::SlicedGeometry3D *>(tsg->GetGeometryForTimePoint(m_TimePoints[slicer]).GetPointer());
+ if (!timeGeometry->IsValidTimePoint(m_TimePoint))
+ {
+ return false;
+ }
- if (slicedGeometry)
- {
- m_LastSNC = slicer;
- mitk::PlaneGeometry *plane =
- dynamic_cast<mitk::PlaneGeometry *>(slicedGeometry->GetPlaneGeometry(event.GetPos()));
- if (plane)
- {
- Interpolate(plane, m_TimePoints[slicer], slicer);
- }
- return true;
- }
- }
+ mitk::SlicedGeometry3D* slicedGeometry =
+ dynamic_cast<mitk::SlicedGeometry3D*>(timeGeometry->GetGeometryForTimePoint(m_TimePoint).GetPointer());
+ if (nullptr == slicedGeometry)
+ {
+ return false;
}
- catch (const std::bad_cast &)
+
+ mitk::PlaneGeometry* plane = dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry->GetPlaneGeometry(m_LastSNC->GetStepper()->GetPos()));
+ if (nullptr == plane)
{
- return false; // so what
+ return false;
}
- return false;
+ this->Interpolate(plane);
+ return true;
}
void QmitkSlicesInterpolator::OnLayerChanged()
{
auto* workingNode = m_ToolManager->GetWorkingData(0);
if (workingNode != nullptr)
{
m_3DContourNode->SetData(nullptr);
this->Show3DInterpolationResult(false);
}
if (m_3DInterpolationEnabled)
{
m_SurfaceInterpolator->Modified();
}
if (m_2DInterpolationEnabled)
{
m_FeedbackNode->SetData(nullptr);
this->OnInterpolationActivated(true);
m_LastSNC->SendSlice();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->UpdateVisibleSuggestion();
}
-void QmitkSlicesInterpolator::Interpolate(mitk::PlaneGeometry *plane,
- mitk::TimePointType timePoint,
- mitk::SliceNavigationController *slicer)
+void QmitkSlicesInterpolator::Interpolate(mitk::PlaneGeometry *plane)
{
- if (m_ToolManager)
+ if (nullptr == m_ToolManager)
{
- mitk::DataNode *node = m_ToolManager->GetWorkingData(0);
- if (node)
- {
- m_Segmentation = dynamic_cast<mitk::Image *>(node->GetData());
+ return;
+ }
- if (m_Segmentation)
- {
- if (!m_Segmentation->GetTimeGeometry()->IsValidTimePoint(timePoint))
- {
- MITK_WARN << "Cannot interpolate segmentation. Passed time point is not within the time bounds of WorkingImage. Time point: " << timePoint;
- return;
- }
- const auto timeStep = m_Segmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint);
+ mitk::DataNode* node = m_ToolManager->GetWorkingData(0);
+ if (nullptr == node)
+ {
+ return;
+ }
- int clickedSliceDimension = -1;
- int clickedSliceIndex = -1;
+ m_Segmentation = dynamic_cast<mitk::Image*>(node->GetData());
+ if (nullptr == m_Segmentation)
+ {
+ return;
+ }
- // calculate real slice position, i.e. slice of the image
- mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex);
+ if (!m_Segmentation->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
+ {
+ MITK_WARN << "Cannot interpolate WorkingImage. Passed time point is not within the time bounds of WorkingImage. "
+ "Time point: "
+ << m_TimePoint;
+ return;
+ }
- mitk::Image::Pointer interpolation =
- m_Interpolator->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep);
- m_FeedbackNode->SetData(interpolation);
+ const auto timeStep = m_Segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
- // maybe just have a variable that stores the active label color.
- if (m_ToolManager)
- {
- auto* workingNode = m_ToolManager->GetWorkingData(0);
- if (workingNode != nullptr)
- {
- auto* activeLabel = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabelSet()->GetActiveLabel();
- if (nullptr != activeLabel)
- {
- auto activeColor = activeLabel->GetColor();
- m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
- }
- }
- }
+ int clickedSliceDimension = -1;
+ int clickedSliceIndex = -1;
+
+ // calculate real slice position, i.e. slice of the image
+ mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex);
- m_LastSNC = slicer;
- m_LastSliceIndex = clickedSliceIndex;
+ mitk::Image::Pointer interpolation =
+ m_Interpolator->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep);
+ m_FeedbackNode->SetData(interpolation);
+
+ // maybe just have a variable that stores the active label color.
+ if (m_ToolManager)
+ {
+ auto* workingNode = m_ToolManager->GetWorkingData(0);
+ if (workingNode != nullptr)
+ {
+ auto* activeLabel = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabelSet()->GetActiveLabel();
+ if (nullptr != activeLabel)
+ {
+ auto activeColor = activeLabel->GetColor();
+ m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
}
}
}
+
+ m_LastSliceIndex = clickedSliceIndex;
}
void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished()
{
mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult();
mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
mitk::PlaneGeometry::Pointer slicingPlane = mitk::PlaneGeometry::New();
mitk::Vector3D slicingPlaneNormalVector;
FillVector3D(slicingPlaneNormalVector,0.0,1.0,0.0);
mitk::Point3D origin;
FillVector3D(origin, 0.0, 0.0, 0.0);
slicingPlane->InitializePlane(origin, slicingPlaneNormalVector);
if (interpolatedSurface.IsNotNull() && workingNode)
{
m_BtnApply3D->setEnabled(true);
// T28261
// m_BtnSuggestPlane->setEnabled(true);
m_InterpolatedSurfaceNode->SetData(interpolatedSurface);
m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface());
this->Show3DInterpolationResult(true);
if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode))
{
m_DataStorage->Add(m_InterpolatedSurfaceNode);
}
}
else if (interpolatedSurface.IsNull())
{
m_BtnApply3D->setEnabled(false);
// T28261
// m_BtnSuggestPlane->setEnabled(false);
if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
{
this->Show3DInterpolationResult(false);
}
}
m_BtnReinit3DInterpolation->setEnabled(true);
- for (auto* slicer : m_ControllerToTimeObserverTag.keys())
+ for (auto* slicer : m_ControllerToSliceObserverTag.keys())
{
slicer->GetRenderer()->RequestUpdate();
}
m_SurfaceInterpolator->ReinitializeInterpolation();
}
void QmitkSlicesInterpolator::OnAcceptInterpolationClicked()
{
auto* workingNode = m_ToolManager->GetWorkingData(0);
auto* planeGeometry = m_LastSNC->GetCurrentPlaneGeometry();
auto* interpolatedPreview = dynamic_cast<mitk::Image*>(m_FeedbackNode->GetData());
if (nullptr == workingNode || nullptr == interpolatedPreview)
return;
auto* segmentationImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
if (nullptr == segmentationImage)
return;
- const auto timePoint = m_LastSNC->GetSelectedTimePoint();
- if (!segmentationImage->GetTimeGeometry()->IsValidTimePoint(timePoint))
+ if (!segmentationImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
{
- MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the time bounds of segmentation. Time point: " << timePoint;
+ MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the "
+ "time bounds of segmentation. Time point: "
+ << m_TimePoint;
return;
}
- const auto timeStep = segmentationImage->GetTimeGeometry()->TimePointToTimeStep(timePoint);
+
+ const auto timeStep = segmentationImage->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
auto interpolatedSlice = mitk::SegTool2D::GetAffectedImageSliceAs2DImage(planeGeometry, segmentationImage, timeStep)->Clone();
auto labelSet = segmentationImage->GetActiveLabelSet();
auto activeValue = labelSet->GetActiveLabel()->GetValue();
mitk::TransferLabelContentAtTimeStep(
interpolatedPreview,
interpolatedSlice,
labelSet,
timeStep,
0,
mitk::LabelSetImage::UnlabeledValue,
false,
{ {0, mitk::LabelSetImage::UnlabeledValue}, {1, activeValue} }
);
mitk::SegTool2D::WriteBackSegmentationResult(workingNode, planeGeometry, interpolatedSlice, timeStep);
m_FeedbackNode->SetData(nullptr);
}
void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController *slicer)
{
/*
* What exactly is done here:
* 1. We create an empty diff image for the current segmentation
* 2. All interpolated slices are written into the diff image
* 3. Then the diffimage is applied to the original segmentation
*/
if (m_Segmentation)
{
mitk::Image::Pointer segmentation3D = m_Segmentation;
unsigned int timeStep = 0;
- const auto timePoint = slicer->GetSelectedTimePoint();
if (4 == m_Segmentation->GetDimension())
{
const auto* geometry = m_Segmentation->GetTimeGeometry();
- if (!geometry->IsValidTimePoint(timePoint))
+ if (!geometry->IsValidTimePoint(m_TimePoint))
{
- MITK_WARN << "Cannot accept all interpolations. Time point selected by passed SliceNavigationController is not within the time bounds of segmentation. Time point: " << timePoint;
+ MITK_WARN << "Cannot accept all interpolations. Time point selected by passed SliceNavigationController is not "
+ "within the time bounds of segmentation. Time point: "
+ << m_TimePoint;
return;
}
mitk::Image::Pointer activeLabelImage;
try
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation);
activeLabelImage = labelSetImage->CreateLabelMask(labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetValue(), true, 0);
}
catch (const std::exception& e)
{
MITK_ERROR << e.what() << " | NO LABELSETIMAGE IN WORKING NODE\n";
}
m_Interpolator->SetSegmentationVolume(activeLabelImage);
- timeStep = geometry->TimePointToTimeStep(timePoint);
+ timeStep = geometry->TimePointToTimeStep(m_TimePoint);
auto timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(m_Segmentation);
timeSelector->SetTimeNr(timeStep);
timeSelector->Update();
segmentation3D = timeSelector->GetOutput();
}
// Create an empty diff image for the undo operation
auto diffImage = mitk::Image::New();
diffImage->Initialize(segmentation3D);
// Create scope for ImageWriteAccessor so that the accessor is destroyed right after use
{
mitk::ImageWriteAccessor accessor(diffImage);
// Set all pixels to zero
auto pixelType = mitk::MakeScalarPixelType<mitk::Tool::DefaultSegmentationDataType>();
// For legacy purpose support former pixel type of segmentations (before multilabel)
if (itk::IOComponentEnum::UCHAR == m_Segmentation->GetImageDescriptor()->GetChannelDescriptor().GetPixelType().GetComponentType())
pixelType = mitk::MakeScalarPixelType<unsigned char>();
memset(accessor.GetData(), 0, pixelType.GetSize() * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2));
}
// Since we need to shift the plane it must be clone so that the original plane isn't altered
auto slicedGeometry = m_Segmentation->GetSlicedGeometry();
auto planeGeometry = slicer->GetCurrentPlaneGeometry()->Clone();
int sliceDimension = -1;
int sliceIndex = -1;
mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, planeGeometry, sliceDimension, sliceIndex);
const auto numSlices = m_Segmentation->GetDimension(sliceDimension);
mitk::ProgressBar::GetInstance()->AddStepsToDo(numSlices);
std::atomic_uint totalChangedSlices;
// Reuse interpolation algorithm instance for each slice to cache boundary calculations
auto algorithm = mitk::ShapeBasedInterpolationAlgorithm::New();
// Distribute slice interpolations to multiple threads
const auto numThreads = std::min(std::thread::hardware_concurrency(), numSlices);
// const auto numThreads = 1;
std::vector<std::vector<unsigned int>> sliceIndices(numThreads);
for (std::remove_const_t<decltype(numSlices)> sliceIndex = 0; sliceIndex < numSlices; ++sliceIndex)
sliceIndices[sliceIndex % numThreads].push_back(sliceIndex);
std::vector<std::thread> threads;
threads.reserve(numThreads);
// This lambda will be executed by the threads
auto interpolate = [=, &interpolator = m_Interpolator, &totalChangedSlices](unsigned int threadIndex)
{
auto clonedPlaneGeometry = planeGeometry->Clone();
auto origin = clonedPlaneGeometry->GetOrigin();
// Go through the sliced indices
for (auto sliceIndex : sliceIndices[threadIndex])
{
slicedGeometry->WorldToIndex(origin, origin);
origin[sliceDimension] = sliceIndex;
slicedGeometry->IndexToWorld(origin, origin);
clonedPlaneGeometry->SetOrigin(origin);
auto interpolation = interpolator->Interpolate(sliceDimension, sliceIndex, clonedPlaneGeometry, timeStep, algorithm);
if (interpolation.IsNotNull())
{
// Setting up the reslicing pipeline which allows us to write the interpolation results back into the image volume
auto reslicer = vtkSmartPointer<mitkVtkImageOverwrite>::New();
// Set overwrite mode to true to write back to the image volume
reslicer->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData());
reslicer->SetOverwriteMode(true);
reslicer->Modified();
auto diffSliceWriter = mitk::ExtractSliceFilter::New(reslicer);
diffSliceWriter->SetInput(diffImage);
diffSliceWriter->SetTimeStep(0);
diffSliceWriter->SetWorldGeometry(clonedPlaneGeometry);
diffSliceWriter->SetVtkOutputRequest(true);
diffSliceWriter->SetResliceTransformByGeometry(diffImage->GetTimeGeometry()->GetGeometryForTimeStep(0));
diffSliceWriter->Modified();
diffSliceWriter->Update();
++totalChangedSlices;
}
mitk::ProgressBar::GetInstance()->Progress();
}
};
m_Interpolator->EnableSliceImageCache();
// Do the interpolation here.
for (size_t threadIndex = 0; threadIndex < numThreads; ++threadIndex)
{
interpolate(threadIndex);
}
m_Interpolator->DisableSliceImageCache();
const mitk::Label::PixelType newDestinationLabel = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation)->GetActiveLabelSet()->GetActiveLabel()->GetValue();
// Do and Undo Operations
if (totalChangedSlices > 0)
{
// Create do/undo operations
auto* doOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
auto* undoOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
undoOp->SetFactor(-1.0);
auto comment = "Confirm all interpolations (" + std::to_string(totalChangedSlices) + ")";
auto* undoStackItem = new mitk::OperationEvent(mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment);
mitk::OperationEvent::IncCurrGroupEventId();
mitk::OperationEvent::IncCurrObjectEventId();
mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(undoStackItem);
mitk::DiffImageApplier::GetInstanceForUndo()->SetDestinationLabel(newDestinationLabel);
// Apply the changes to the original image
mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation(doOp);
}
m_FeedbackNode->SetData(nullptr);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController *slicer)
{
// this redirect is for calling from outside
if (slicer == nullptr)
OnAcceptAllInterpolationsClicked();
else
AcceptAllInterpolations(slicer);
}
void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked()
{
QMenu orientationPopup(this);
- for (auto it = m_ActionToSlicer.begin(); it != m_ActionToSlicer.end(); ++it)
+ for (auto it = m_ActionToSlicerMap.begin(); it != m_ActionToSlicerMap.end(); ++it)
+ {
orientationPopup.addAction(it->first);
+ }
connect(&orientationPopup, SIGNAL(triggered(QAction *)), this, SLOT(OnAcceptAllPopupActivated(QAction *)));
orientationPopup.exec(QCursor::pos());
}
void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked()
{
auto referenceImage = GetData<mitk::Image>(m_ToolManager->GetReferenceData(0));
auto* segmentationDataNode = m_ToolManager->GetWorkingData(0);
auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(segmentationDataNode->GetData());
auto activeLabelColor = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetColor();
std::string activeLabelName = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetName();
auto segmentation = GetData<mitk::Image>(segmentationDataNode);
if (referenceImage.IsNull() || segmentation.IsNull())
return;
const auto* segmentationGeometry = segmentation->GetTimeGeometry();
- const auto timePoint = m_LastSNC->GetSelectedTimePoint();
- if (!referenceImage->GetTimeGeometry()->IsValidTimePoint(timePoint) ||
- !segmentationGeometry->IsValidTimePoint(timePoint))
+ if (!referenceImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint) ||
+ !segmentationGeometry->IsValidTimePoint(m_TimePoint))
{
MITK_WARN << "Cannot accept interpolation. Current time point is not within the time bounds of the patient image and segmentation.";
return;
}
auto interpolatedSurface = GetData<mitk::Surface>(m_InterpolatedSurfaceNode);
if (interpolatedSurface.IsNull())
return;
auto surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
surfaceToImageFilter->SetImage(referenceImage);
surfaceToImageFilter->SetMakeOutputBinary(true);
surfaceToImageFilter->SetUShortBinaryPixelType(itk::IOComponentEnum::USHORT == segmentation->GetPixelType().GetComponentType());
surfaceToImageFilter->SetInput(interpolatedSurface);
surfaceToImageFilter->Update();
mitk::Image::Pointer interpolatedSegmentation = surfaceToImageFilter->GetOutput();
- auto timeStep = segmentationGeometry->TimePointToTimeStep(timePoint);
+ auto timeStep = segmentationGeometry->TimePointToTimeStep(m_TimePoint);
const mitk::Label::PixelType newDestinationLabel = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetValue();
TransferLabelContentAtTimeStep(
interpolatedSegmentation,
labelSetImage,
labelSetImage->GetActiveLabelSet(),
timeStep,
0,
0,
false,
{{1, newDestinationLabel}},
mitk::MultiLabelSegmentation::MergeStyle::Merge,
mitk::MultiLabelSegmentation::OverwriteStyle::RegardLocks);
- // m_CmbInterpolation->setCurrentIndex(0);
this->Show3DInterpolationResult(false);
std::string name = segmentationDataNode->GetName() + " 3D-interpolation - " + activeLabelName;
mitk::TimeBounds timeBounds;
if (1 < interpolatedSurface->GetTimeSteps())
{
name += "_t" + std::to_string(timeStep);
auto* polyData = vtkPolyData::New();
polyData->DeepCopy(interpolatedSurface->GetVtkPolyData(timeStep));
auto surface = mitk::Surface::New();
surface->SetVtkPolyData(polyData);
interpolatedSurface = surface;
timeBounds = segmentationGeometry->GetTimeBounds(timeStep);
}
else
{
timeBounds = segmentationGeometry->GetTimeBounds(0);
}
auto* surfaceGeometry = static_cast<mitk::ProportionalTimeGeometry*>(interpolatedSurface->GetTimeGeometry());
surfaceGeometry->SetFirstTimePoint(timeBounds[0]);
surfaceGeometry->SetStepDuration(timeBounds[1] - timeBounds[0]);
// Typical file formats for surfaces do not save any time-related information. As a workaround at least for MITK scene files, we have the
// possibility to seralize this information as properties.
interpolatedSurface->SetProperty("ProportionalTimeGeometry.FirstTimePoint", mitk::FloatProperty::New(surfaceGeometry->GetFirstTimePoint()));
interpolatedSurface->SetProperty("ProportionalTimeGeometry.StepDuration", mitk::FloatProperty::New(surfaceGeometry->GetStepDuration()));
auto interpolatedSurfaceDataNode = mitk::DataNode::New();
interpolatedSurfaceDataNode->SetData(interpolatedSurface);
interpolatedSurfaceDataNode->SetName(name);
interpolatedSurfaceDataNode->SetOpacity(0.7f);
interpolatedSurfaceDataNode->SetColor(activeLabelColor);
m_DataStorage->Add(interpolatedSurfaceDataNode, segmentationDataNode);
}
-
void QmitkSlicesInterpolator::OnReinit3DInterpolation()
{
// Step 1. Load from the isContourPlaneGeometry nodes the contourNodes.
mitk::NodePredicateProperty::Pointer pred =
mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
m_DataStorage->GetDerivations(m_ToolManager->GetWorkingData(0), pred);
if (contourNodes->Size() != 0)
{
std::vector<const mitk::PlaneGeometry*> contourPlanes;
std::vector<mitk::Surface::Pointer> contourList;
if (m_ToolManager->GetWorkingData(0) != nullptr)
{
try
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
auto activeLayerID = labelSetImage->GetActiveLayer();
- const auto timePoint = m_LastSNC->GetSelectedTimePoint();
- if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(timePoint))
+ if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
{
MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
return;
}
// Adding layer, label and timeStep information for the contourNodes.
for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
{
auto contourNode = it->Value();
auto layerID = dynamic_cast<mitk::UIntProperty *>(contourNode->GetProperty("layerID"))->GetValue();
auto labelID = dynamic_cast<mitk::UShortProperty *>(contourNode->GetProperty("labelID"))->GetValue();
auto timeStep = dynamic_cast<mitk::IntProperty *>(contourNode->GetProperty("timeStep"))->GetValue();
auto px = dynamic_cast<mitk::DoubleProperty *>(contourNode->GetProperty("px"))->GetValue();
auto py = dynamic_cast<mitk::DoubleProperty *>(contourNode->GetProperty("py"))->GetValue();
auto pz = dynamic_cast<mitk::DoubleProperty *>(contourNode->GetProperty("pz"))->GetValue();
// auto layerImage = labelSetImage->GetLayerImage(layerID);
auto planeGeometry = dynamic_cast<mitk::PlanarFigure *>(contourNode->GetData())->GetPlaneGeometry();
labelSetImage->SetActiveLayer(layerID);
auto sliceImage = ExtractSliceFromImage(labelSetImage, planeGeometry, timeStep);
labelSetImage->SetActiveLayer(activeLayerID);
mitk::ImageToContourFilter::Pointer contourExtractor = mitk::ImageToContourFilter::New();
contourExtractor->SetInput(sliceImage);
contourExtractor->SetContourValue(labelID);
contourExtractor->Update();
mitk::Surface::Pointer contour = contourExtractor->GetOutput();
if (contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
continue;
vtkSmartPointer<vtkIntArray> intArray = vtkSmartPointer<vtkIntArray>::New();
intArray->InsertNextValue(labelID);
intArray->InsertNextValue(layerID);
intArray->InsertNextValue(timeStep);
contour->GetVtkPolyData()->GetFieldData()->AddArray(intArray);
vtkSmartPointer<vtkDoubleArray> doubleArray = vtkSmartPointer<vtkDoubleArray>::New();
doubleArray->InsertNextValue(px);
doubleArray->InsertNextValue(py);
doubleArray->InsertNextValue(pz);
contour->GetVtkPolyData()->GetFieldData()->AddArray(doubleArray);
contour->DisconnectPipeline();
contourList.push_back(contour);
contourPlanes.push_back(planeGeometry);
}
labelSetImage->SetActiveLayer(activeLayerID);
// size_t activeLayer = labelSetImage->GetActiveLayer();
for (size_t l = 0; l < labelSetImage->GetNumberOfLayers(); ++l)
{
this->OnAddLabelSetConnection(l);
}
// labelSetImage->SetActiveLayer(activeLayer);
m_SurfaceInterpolator->CompleteReinitialization(contourList, contourPlanes);
}
catch(const std::exception& e)
{
MITK_ERROR << "Exception thrown casting toolmanager working data to labelsetImage";
}
}
}
else
{
m_BtnApply3D->setEnabled(false);
QMessageBox errorInfo;
errorInfo.setWindowTitle("Reinitialize surface interpolation");
errorInfo.setIcon(QMessageBox::Information);
errorInfo.setText("No contours available for the selected segmentation!");
errorInfo.exec();
}
}
void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction *action)
{
try
{
- auto iter = m_ActionToSlicer.find(action);
- if (iter != m_ActionToSlicer.end())
+ auto iter = m_ActionToSlicerMap.find(action);
+ if (iter != m_ActionToSlicerMap.end())
{
mitk::SliceNavigationController *slicer = iter->second;
- AcceptAllInterpolations(slicer);
+ this->AcceptAllInterpolations(slicer);
}
}
catch (...)
{
/* Showing message box with possible memory error */
QMessageBox errorInfo;
errorInfo.setWindowTitle("Interpolation Process");
errorInfo.setIcon(QMessageBox::Critical);
errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!");
errorInfo.exec();
// additional error message on std::cerr
std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl;
}
}
void QmitkSlicesInterpolator::OnInterpolationActivated(bool on)
{
m_2DInterpolationEnabled = on;
try
{
if (m_DataStorage.IsNotNull())
{
if (on && !m_DataStorage->Exists(m_FeedbackNode))
{
m_DataStorage->Add(m_FeedbackNode);
}
}
}
catch (...)
{
// don't care (double add/remove)
}
if (m_ToolManager)
{
mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
mitk::DataNode *referenceNode = m_ToolManager->GetReferenceData(0);
QWidget::setEnabled(workingNode != nullptr);
m_BtnApply2D->setEnabled(on);
m_FeedbackNode->SetVisibility(on);
if (!on)
{
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
return;
}
if (workingNode)
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
if (nullptr == labelSetImage)
{
MITK_ERROR << "NO LABELSETIMAGE IN WORKING NODE\n";
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
return;
}
auto* activeLabel = labelSetImage->GetActiveLabelSet()->GetActiveLabel();
auto* segmentation = dynamic_cast<mitk::Image*>(workingNode->GetData());
if (nullptr != activeLabel && nullptr != segmentation)
{
auto activeLabelImage = labelSetImage->CreateLabelMask(activeLabel->GetValue(), true, 0);
m_Interpolator->SetSegmentationVolume(activeLabelImage);
if (referenceNode)
{
mitk::Image *referenceImage = dynamic_cast<mitk::Image *>(referenceNode->GetData());
m_Interpolator->SetReferenceVolume(referenceImage); // may be nullptr
}
}
}
}
this->UpdateVisibleSuggestion();
}
void QmitkSlicesInterpolator::Run3DInterpolation()
{
m_SurfaceInterpolator->Interpolate();
}
void QmitkSlicesInterpolator::StartUpdateInterpolationTimer()
{
m_Timer->start(500);
}
void QmitkSlicesInterpolator::StopUpdateInterpolationTimer()
{
if(m_ToolManager)
{
auto* workingNode = m_ToolManager->GetWorkingData(0);
auto activeColor = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabelSet()->GetActiveLabel()->GetColor();
m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
}
m_Timer->stop();
}
void QmitkSlicesInterpolator::ChangeSurfaceColor()
{
float currentColor[3];
m_InterpolatedSurfaceNode->GetColor(currentColor);
m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
m_InterpolatedSurfaceNode->Update();
mitk::RenderingManager::GetInstance()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS);
}
void QmitkSlicesInterpolator::PrepareInputsFor3DInterpolation()
{
if (m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled)
{
auto *workingNode = m_ToolManager->GetWorkingData(0);
if (workingNode != nullptr)
{
int ret = QMessageBox::Yes;
if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5)
{
QMessageBox msgBox;
msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!");
msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?");
msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
ret = msgBox.exec();
}
auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
auto activeLabel = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetValue();
m_SurfaceInterpolator->AddActiveLabelContoursForInterpolation(activeLabel);
if (m_Watcher.isRunning())
m_Watcher.waitForFinished();
if (ret == QMessageBox::Yes)
{
// Maybe set the segmentation node here
m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
m_Watcher.setFuture(m_Future);
}
else
{
m_CmbInterpolation->setCurrentIndex(0);
}
}
else
{
QWidget::setEnabled(false);
m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled);
}
}
if (!m_3DInterpolationEnabled)
{
this->Show3DInterpolationResult(false);
m_BtnApply3D->setEnabled(m_3DInterpolationEnabled);
// T28261
// m_BtnSuggestPlane->setEnabled(m_3DInterpolationEnabled);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on)
{
m_3DInterpolationEnabled = on;
try
{
// this->PrepareInputsFor3DInterpolation();
m_SurfaceInterpolator->Modified();
}
catch (...)
{
MITK_ERROR << "Error with 3D surface interpolation!";
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::EnableInterpolation(bool on)
{
// only to be called from the outside world
// just a redirection to OnInterpolationActivated
OnInterpolationActivated(on);
}
void QmitkSlicesInterpolator::Enable3DInterpolation(bool on)
{
// only to be called from the outside world
// just a redirection to OnInterpolationActivated
this->On3DInterpolationActivated(on);
}
void QmitkSlicesInterpolator::UpdateVisibleSuggestion()
{
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject & /*e*/)
{
// something (e.g. undo) changed the interpolation info, we should refresh our display
this->UpdateVisibleSuggestion();
}
void QmitkSlicesInterpolator::OnInterpolationAborted(const itk::EventObject& /*e*/)
{
m_CmbInterpolation->setCurrentIndex(0);
m_FeedbackNode->SetData(nullptr);
}
void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject & /*e*/)
{
if (m_Watcher.isRunning())
m_Watcher.waitForFinished();
if (m_3DInterpolationEnabled)
{
m_3DContourNode->SetData(nullptr);
m_InterpolatedSurfaceNode->SetData(nullptr);
auto* workingNode = m_ToolManager->GetWorkingData(0);
if (workingNode == nullptr)
return;
auto* labelSetImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
auto* label = labelSetImage->GetActiveLabelSet()->GetActiveLabel();
if (label == nullptr)
return;
m_SurfaceInterpolator->AddActiveLabelContoursForInterpolation(label->GetValue());
m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
m_Watcher.setFuture(m_Future);
}
}
void QmitkSlicesInterpolator::SetCurrentContourListID()
{
// New ContourList = hide current interpolation
Show3DInterpolationResult(false);
if (m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC)
{
mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
try{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
for (size_t layerID = 0; layerID < labelSetImage->GetNumberOfLayers(); ++layerID)
{
this->OnAddLabelSetConnection(layerID);
}
}
catch (std::exception &e)
{
MITK_ERROR << e.what() << "\n";
}
if (workingNode)
{
QWidget::setEnabled(true);
- const auto timePoint = m_LastSNC->GetSelectedTimePoint();
// In case the time is not valid use 0 to access the time geometry of the working node
unsigned int time_position = 0;
- if (!workingNode->GetData()->GetTimeGeometry()->IsValidTimePoint(timePoint))
+ if (!workingNode->GetData()->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
{
- MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << timePoint;
+ MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << m_TimePoint;
return;
}
// Sets up the surface interpolator to accept
- time_position = workingNode->GetData()->GetTimeGeometry()->TimePointToTimeStep(timePoint);
+ time_position = workingNode->GetData()->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
mitk::Vector3D spacing = workingNode->GetData()->GetGeometry(time_position)->GetSpacing();
double minSpacing = 100;
double maxSpacing = 0;
for (int i = 0; i < 3; i++)
{
if (spacing[i] < minSpacing)
{
minSpacing = spacing[i];
}
if (spacing[i] > maxSpacing)
{
maxSpacing = spacing[i];
}
}
m_SurfaceInterpolator->SetMaxSpacing(maxSpacing);
m_SurfaceInterpolator->SetMinSpacing(minSpacing);
m_SurfaceInterpolator->SetDistanceImageVolume(50000);
mitk::Image::Pointer segmentationImage;
segmentationImage = dynamic_cast<mitk::Image *>(workingNode->GetData());
m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage);
- m_SurfaceInterpolator->SetCurrentTimePoint(timePoint);
+ m_SurfaceInterpolator->SetCurrentTimePoint(m_TimePoint);
}
else
{
QWidget::setEnabled(false);
}
}
}
void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status)
{
if (m_InterpolatedSurfaceNode.IsNotNull())
m_InterpolatedSurfaceNode->SetVisibility(status);
if (m_3DContourNode.IsNotNull())
{
auto allRenderWindows = mitk::BaseRenderer::GetAll3DRenderWindows();
for (auto mapit = allRenderWindows.begin(); mapit != allRenderWindows.end(); ++mapit)
{
m_3DContourNode->SetVisibility(status, mapit->second);
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSlicesInterpolator::OnActiveLabelChanged(mitk::Label::PixelType)
{
m_3DContourNode->SetData(nullptr);
m_FeedbackNode->SetData(nullptr);
m_InterpolatedSurfaceNode->SetData(nullptr);
if (m_Watcher.isRunning())
m_Watcher.waitForFinished();
if (m_3DInterpolationEnabled)
{
m_SurfaceInterpolator->Modified();
}
if (m_2DInterpolationEnabled)
{
m_FeedbackNode->SetData(nullptr);
this->OnInterpolationActivated(true);
m_LastSNC->SendSlice();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->UpdateVisibleSuggestion();
}
void QmitkSlicesInterpolator::CheckSupportedImageDimension()
{
if (m_ToolManager->GetWorkingData(0))
{
m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
if (m_3DInterpolationEnabled && m_Segmentation && ((m_Segmentation->GetDimension() != 3) || (m_Segmentation->GetDimension() != 4)) )
{
QMessageBox info;
info.setWindowTitle("3D Interpolation Process");
info.setIcon(QMessageBox::Information);
info.setText("3D Interpolation is only supported for 3D/4D images at the moment!");
info.exec();
m_CmbInterpolation->setCurrentIndex(0);
}
}
}
void QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted(const itk::Object *sender,
const itk::EventObject & /*e*/)
{
// Don't know how to avoid const_cast here?!
mitk::SliceNavigationController *slicer =
dynamic_cast<mitk::SliceNavigationController *>(const_cast<itk::Object *>(sender));
if (slicer)
{
- m_ControllerToTimeObserverTag.remove(slicer);
m_ControllerToSliceObserverTag.remove(slicer);
m_ControllerToDeleteObserverTag.remove(slicer);
}
}
void QmitkSlicesInterpolator::WaitForFutures()
{
if (m_Watcher.isRunning())
{
m_Watcher.waitForFinished();
}
if (m_PlaneWatcher.isRunning())
{
m_PlaneWatcher.waitForFinished();
}
}
void QmitkSlicesInterpolator::NodeRemoved(const mitk::DataNode* node)
{
if ((m_ToolManager && m_ToolManager->GetWorkingData(0) == node) ||
node == m_3DContourNode ||
node == m_FeedbackNode ||
node == m_InterpolatedSurfaceNode)
{
WaitForFutures();
}
}
void QmitkSlicesInterpolator::OnAddLabelSetConnection(unsigned int layerID)
{
if (m_ToolManager->GetWorkingData(0) != nullptr)
{
try
{
auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
auto labelSet = workingImage->GetLabelSet(layerID);
labelSet->RemoveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnRemoveLabel);
labelSet->ActiveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<QmitkSlicesInterpolator>(
this, &QmitkSlicesInterpolator::OnLayerChanged);
m_SurfaceInterpolator->AddLabelSetConnection(layerID);
}
catch(const std::exception& e)
{
MITK_ERROR << e.what() << '\n';
}
}
}
void QmitkSlicesInterpolator::OnAddLabelSetConnection()
{
if (m_ToolManager->GetWorkingData(0) != nullptr)
{
try
{
auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
workingImage->GetActiveLabelSet()->RemoveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnRemoveLabel);
workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<QmitkSlicesInterpolator>(
this, &QmitkSlicesInterpolator::OnLayerChanged);
m_SurfaceInterpolator->AddLabelSetConnection();
}
catch(const std::exception& e)
{
MITK_ERROR << e.what() << '\n';
}
}
}
void QmitkSlicesInterpolator::OnRemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID)
{
size_t previousLayerID = labelSetImage->GetActiveLayer();
labelSetImage->SetActiveLayer(layerID);
labelSetImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnRemoveLabel);
labelSetImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
labelSetImage->AfterChangeLayerEvent -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
this, &QmitkSlicesInterpolator::OnLayerChanged);
m_SurfaceInterpolator->RemoveLabelSetConnection(labelSetImage, layerID);
labelSetImage->SetActiveLayer(previousLayerID);
}
void QmitkSlicesInterpolator::OnRemoveLabelSetConnection()
{
if (m_ToolManager->GetWorkingData(0) != nullptr)
{
try
{
auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_ToolManager->GetWorkingData(0)->GetData());
workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnRemoveLabel);
workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
workingImage->AfterChangeLayerEvent -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
this, &QmitkSlicesInterpolator::OnLayerChanged);
}
catch(const std::exception& e)
{
MITK_ERROR << e.what() << '\n';
}
}
}
void QmitkSlicesInterpolator::OnRemoveLabel(mitk::Label::PixelType /*removedLabelValue*/)
{
if (m_ToolManager->GetWorkingData(0) != nullptr)
{
try
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
auto currentLayerID = labelSetImage->GetActiveLayer();
auto numTimeSteps = labelSetImage->GetTimeGeometry()->CountTimeSteps();
for (size_t t = 0; t < numTimeSteps; ++t)
{
m_SurfaceInterpolator->RemoveContours(m_PreviousActiveLabelValue,t,currentLayerID);
}
}
catch(const std::exception& e)
{
MITK_ERROR << "Bad cast error for labelSetImage";
}
}
}
void QmitkSlicesInterpolator::OnModifyLabelChanged(const itk::Object *caller,
const itk::EventObject & /*event*/)
{
auto *tempImage = dynamic_cast<mitk::LabelSetImage *>(const_cast<itk::Object *>(caller) ) ;
if( tempImage == nullptr)
{
MITK_ERROR << "Unable to cast caller to LabelSetImage.";
return;
}
ModifyLabelActionTrigerred actionTriggered = ModifyLabelActionTrigerred::Null;
if(m_ToolManager->GetWorkingData(0) != nullptr)
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
if (labelSetImage == tempImage)
{
- const auto timePoint = m_LastSNC->GetSelectedTimePoint();
- if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(timePoint))
+ if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
{
MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
return;
}
- auto timeStep = labelSetImage->GetTimeGeometry()->TimePointToTimeStep(timePoint);
+ auto timeStep = labelSetImage->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
auto numLayersInCurrentSegmentation = m_SurfaceInterpolator->GetNumberOfLayersInCurrentSegmentation();
// This handles the add layer or remove layer operation.
if (labelSetImage->GetNumberOfLayers() != numLayersInCurrentSegmentation)
{
bool addLayer = (labelSetImage->GetNumberOfLayers() == (numLayersInCurrentSegmentation +1) );
bool removeLayer = (labelSetImage->GetNumberOfLayers() == (numLayersInCurrentSegmentation - 1) );
m_SurfaceInterpolator->SetNumberOfLayersInCurrentSegmentation(labelSetImage->GetNumberOfLayers());
if (addLayer)
{
m_SurfaceInterpolator->OnAddLayer();
this->OnAddLabelSetConnection();
}
if (removeLayer)
{
m_SurfaceInterpolator->OnRemoveLayer();
}
return;
}
// Get the pixels present in the image.
// This portion of the code deals with the merge and erase labels operations.
auto imageDimension = labelSetImage->GetDimension();
if (imageDimension == 4)
{
actionTriggered = ModifyLabelProcessing<4>(labelSetImage, m_SurfaceInterpolator, timeStep);
}
else
{
actionTriggered = ModifyLabelProcessing<3>(labelSetImage, m_SurfaceInterpolator, timeStep);
}
if (actionTriggered == ModifyLabelActionTrigerred::Erase)
{
m_InterpolatedSurfaceNode->SetData(nullptr);
}
auto currentLayerID = labelSetImage->GetActiveLayer();
if (actionTriggered == ModifyLabelActionTrigerred::Merge)
{
this->MergeContours(timeStep, currentLayerID);
m_SurfaceInterpolator->Modified();
}
}
}
}
void QmitkSlicesInterpolator::MergeContours(unsigned int timeStep,
unsigned int layerID)
{
- std::vector<mitk::SurfaceInterpolationController::ContourPositionInformation>& contours =
- m_SurfaceInterpolator->GetContours(timeStep,layerID);
+ auto* contours = m_SurfaceInterpolator->GetContours(timeStep, layerID);
+
+ if (nullptr == contours)
+ return;
+
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
- for (size_t i = 0; i < contours.size(); ++i)
+ for (size_t i = 0; i < contours->size(); ++i)
{
- for (size_t j = i+1; j < contours.size(); ++j)
+ for (size_t j = i+1; j < contours->size(); ++j)
{
// And Labels are the same and Layers are the same.
- bool areContoursCoplanar = AreContoursCoplanar(contours[i],contours[j]);
+ bool areContoursCoplanar = AreContoursCoplanar((*contours)[i], (*contours)[j]);
- if ( areContoursCoplanar && (contours[i].LabelValue == contours[j].LabelValue) )
+ if ( areContoursCoplanar && ((*contours)[i].LabelValue == (*contours)[j].LabelValue) )
{
// Update the contour by re-extracting the slice from the corresponding plane.
- mitk::Image::Pointer slice = ExtractSliceFromImage(m_Segmentation, contours[i].Plane, timeStep);
+ mitk::Image::Pointer slice = ExtractSliceFromImage(m_Segmentation, (*contours)[i].Plane, timeStep);
mitk::ImageToContourFilter::Pointer contourExtractor = mitk::ImageToContourFilter::New();
contourExtractor->SetInput(slice);
- contourExtractor->SetContourValue(contours[i].LabelValue);
+ contourExtractor->SetContourValue((*contours)[i].LabelValue);
contourExtractor->Update();
mitk::Surface::Pointer contour = contourExtractor->GetOutput();
- contours[i].Contour = contour;
+ (*contours)[i].Contour = contour;
// Update the interior point of the contour
- contours[i].ContourPoint = m_SurfaceInterpolator->ComputeInteriorPointOfContour(contours[i],dynamic_cast<mitk::LabelSetImage *>(m_Segmentation));
+ (*contours)[i].ContourPoint = m_SurfaceInterpolator->ComputeInteriorPointOfContour((*contours)[i],dynamic_cast<mitk::LabelSetImage *>(m_Segmentation));
// Setting the contour polygon data to an empty vtkPolyData,
// as source label is empty after merge operation.
- contours[j].Contour->SetVtkPolyData(vtkSmartPointer<vtkPolyData>::New());
+ (*contours)[j].Contour->SetVtkPolyData(vtkSmartPointer<vtkPolyData>::New());
}
}
}
auto segmentationNode = m_SurfaceInterpolator->GetSegmentationImageNode();
if (segmentationNode == nullptr)
{
MITK_ERROR << "segmentation Image Node not found\n";
}
auto isContourPlaneGeometry = mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
m_DataStorage->GetDerivations(segmentationNode, isContourPlaneGeometry);
// Remove empty contour nodes.
auto isContourEmpty = [] (const mitk::SurfaceInterpolationController::ContourPositionInformation& contour)
{
return (contour.Contour->GetVtkPolyData()->GetNumberOfPoints() == 0);
};
- auto it = std::remove_if(contours.begin(), contours.end(), isContourEmpty);
- contours.erase(it, contours.end());
+ auto it = std::remove_if((*contours).begin(), (*contours).end(), isContourEmpty);
+ (*contours).erase(it, (*contours).end());
}
void QmitkSlicesInterpolator::ClearSegmentationObservers()
{
auto dataIter = m_SegmentationObserverTags.begin();
while (dataIter != m_SegmentationObserverTags.end())
{
auto labelSetImage = (*dataIter).first;
labelSetImage->RemoveObserver((*dataIter).second);
for (size_t layerID = 0; layerID < labelSetImage->GetNumberOfLayers(); ++layerID)
{
this->OnRemoveLabelSetConnection(labelSetImage, layerID);
}
++dataIter;
}
m_SegmentationObserverTags.clear();
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h
index 9ab6eec6d3..5344f253a6 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h
+++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h
@@ -1,426 +1,428 @@
/*============================================================================
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 QmitkSlicesInterpolator_h
#define QmitkSlicesInterpolator_h
#include "mitkDataNode.h"
#include "mitkDataStorage.h"
#include "mitkSegmentationInterpolationController.h"
-#include "mitkSliceNavigationController.h"
#include "mitkSurfaceInterpolationController.h"
#include "mitkToolManager.h"
#include <MitkSegmentationUIExports.h>
#include "mitkFeatureBasedEdgeDetectionFilter.h"
#include "mitkPointCloudScoringFilter.h"
#include <QWidget>
#include <map>
#include <QCheckBox>
#include <QComboBox>
#include <QFrame>
#include <QGroupBox>
#include <QRadioButton>
#include "mitkVtkRepresentationProperty.h"
#include "vtkProperty.h"
// For running 3D interpolation in background
#include <QFuture>
#include <QFutureWatcher>
#include <QTimer>
#include <QtConcurrentRun>
namespace mitk
{
class PlaneGeometry;
class SliceNavigationController;
+ class TimeNavigationController;
}
class QPushButton;
class QmitkRenderWindow;
enum ModifyLabelActionTrigerred
{
Null,
Erase,
Merge
};
/**
\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,
QmitkSlicesInterpolator 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.
\todo show/hide feedback on demand
Last contributor: $Author: maleike $
*/
class MITKSEGMENTATIONUI_EXPORT QmitkSlicesInterpolator : public QWidget
{
Q_OBJECT
public:
QmitkSlicesInterpolator(QWidget *parent = nullptr, const char *name = nullptr);
/**
To be called once before real use.
*/
void Initialize(mitk::ToolManager *toolManager, const QList<QmitkRenderWindow*>& windows);
/**
* @brief
*
*/
void Uninitialize();
~QmitkSlicesInterpolator() override;
/**
* @brief Set the Data Storage object
*
* @param storage
*/
void SetDataStorage(mitk::DataStorage::Pointer storage);
/**
* @brief Get the Data Storage object
*
* @return mitk::DataStorage*
*/
mitk::DataStorage *GetDataStorage();
/**
Just public because it is called by itk::Commands. You should not need to call this.
*/
void OnToolManagerWorkingDataModified();
/**
Just public because it is called by itk::Commands. You should not need to call this.
*/
void OnToolManagerReferenceDataModified();
/**
* @brief Reacts to the time changed event.
*
* @param sender
*/
void OnTimeChanged(itk::Object *sender, const itk::EventObject &);
/**
* @brief Reacts to the slice changed event
*
* @param sender
*/
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 OnInterpolationInfoChanged(const itk::EventObject &);
/**
Just public because it is called by itk::Commands. You should not need to call this.
*/
void OnInterpolationAborted(const itk::EventObject &);
/**
Just public because it is called by itk::Commands. You should not need to call this.
*/
void OnSurfaceInterpolationInfoChanged(const itk::EventObject &);
private:
/**
* @brief Set the visibility of the 3d interpolation
*/
void Show3DInterpolationResult(bool);
/**
* @brief Function that reacts to a change in the activeLabel of the working segmentation image.
*
*/
void OnActiveLabelChanged(mitk::Label::PixelType);
/**
* @brief Function that reacts to a change in the layer.
*
*/
void OnLayerChanged();
/**
* @brief Function that handles label removal from the segmentation image.
*
*/
void OnRemoveLabel(mitk::Label::PixelType removedLabelValue);
/**
* @brief Function that to changes in the segmentation image. It handles the layer removal, addition, label erasure,
*
*/
void OnModifyLabelChanged(const itk::Object *caller,
const itk::EventObject & /*event*/);
/**
* @brief Add the necessary subscribers to the label set image, for UI responsiveness.
* It deals with remove label, change active label, layer changes and change in the label.
*
*/
void OnAddLabelSetConnection();
/**
* @brief Add the necessary subscribers to the current LabelSetImage at the layer input, for UI responsiveness.
* It deals with remove label, change active label, layer changes and change in the label.
*
* @param layerID
*/
void OnAddLabelSetConnection(unsigned int layerID);
/**
* @brief Remove the subscribers for the different events to the segmentation image.
*
*/
void OnRemoveLabelSetConnection();
/**
* @brief Merge contours for the current layerID and current timeStep.
*
* @param timeStep
* @param layerID
*/
void MergeContours(unsigned int timeStep, unsigned int layerID);
/**
* @brief Prepare Inputs for 3D Interpolation.
*
*/
void PrepareInputsFor3DInterpolation();
signals:
void SignalRememberContourPositions(bool);
void SignalShowMarkerNodes(bool);
public slots:
virtual void setEnabled(bool);
/**
Call this from the outside to enable/disable interpolation
*/
void EnableInterpolation(bool);
void Enable3DInterpolation(bool);
/**
Call this from the outside to accept all interpolations
*/
void FinishInterpolation(mitk::SliceNavigationController *slicer = nullptr);
protected slots:
/**
Reaction to button clicks.
*/
void OnAcceptInterpolationClicked();
/*
Opens popup to ask about which orientation should be interpolated
*/
void OnAcceptAllInterpolationsClicked();
/*
Reaction to button clicks
*/
void OnAccept3DInterpolationClicked();
/**
* @brief Reaction to reinit 3D Interpolation. Re-reads the plane geometries of the image
* that should have generated the
*
*/
void OnReinit3DInterpolation();
/*
* Will trigger interpolation for all slices in given orientation (called from popup menu of
* OnAcceptAllInterpolationsClicked)
*/
void OnAcceptAllPopupActivated(QAction *action);
/**
Called on activation/deactivation
*/
void OnInterpolationActivated(bool);
void On3DInterpolationActivated(bool);
void OnInterpolationMethodChanged(int index);
// Enhancement for 3D interpolation
void On2DInterpolationEnabled(bool);
void On3DInterpolationEnabled(bool);
void OnInterpolationDisabled(bool);
void OnShowMarkers(bool);
void Run3DInterpolation();
/**
* @brief Function triggers when the surface interpolation thread completes running.
* It is responsible for retrieving the data, rendering it in the active color label,
* storing the surface information in the feedback node.
*
*/
void OnSurfaceInterpolationFinished();
void StartUpdateInterpolationTimer();
void StopUpdateInterpolationTimer();
void ChangeSurfaceColor();
/**
* @brief Removes all observers to the labelSetImage at the layerID specified.
* Is used when changing the segmentation image.
*
* @param labelSetImage
* @param layerID
*/
void OnRemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID);
protected:
- const std::map<QAction *, mitk::SliceNavigationController *> createActionToSlicer(const QList<QmitkRenderWindow*>& windows);
- std::map<QAction *, mitk::SliceNavigationController *> m_ActionToSlicer;
+
+ typedef std::map<QAction*, mitk::SliceNavigationController*> ActionToSliceDimensionMapType;
+ const ActionToSliceDimensionMapType CreateActionToSlicer(const QList<QmitkRenderWindow*>& windows);
+ ActionToSliceDimensionMapType m_ActionToSlicerMap;
void AcceptAllInterpolations(mitk::SliceNavigationController *slicer);
/**
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 slicer the SliceNavigationController
*/
- bool TranslateAndInterpolateChangedSlice(const itk::EventObject &e, mitk::SliceNavigationController *slicer);
+ bool TranslateAndInterpolateChangedSlice(const itk::EventObject &e,
+ mitk::SliceNavigationController *sliceNavigationController);
+ bool TranslateAndInterpolateChangedSlice(const mitk::TimeGeometry* timeGeometry);
/**
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);
-
- // void InterpolateSurface();
+ void Interpolate(mitk::PlaneGeometry *plane);
/**
Called internally to update the interpolation suggestion. Finds out about the focused render window and requests an
interpolation.
*/
void UpdateVisibleSuggestion();
void SetCurrentContourListID();
private:
void InitializeWindow(QmitkRenderWindow* window);
void HideAllInterpolationControls();
void Show2DInterpolationControls(bool show);
void Show3DInterpolationControls(bool show);
void CheckSupportedImageDimension();
void WaitForFutures();
void NodeRemoved(const mitk::DataNode* node);
void ClearSegmentationObservers();
mitk::SegmentationInterpolationController::Pointer m_Interpolator;
mitk::SurfaceInterpolationController::Pointer m_SurfaceInterpolator;
mitk::FeatureBasedEdgeDetectionFilter::Pointer m_EdgeDetector;
mitk::PointCloudScoringFilter::Pointer m_PointScorer;
mitk::ToolManager::Pointer m_ToolManager;
bool m_Initialized;
- QHash<mitk::SliceNavigationController *, int> m_ControllerToTimeObserverTag;
+ unsigned int m_ControllerToTimeObserverTag;
QHash<mitk::SliceNavigationController *, int> m_ControllerToSliceObserverTag;
QHash<mitk::SliceNavigationController *, int> m_ControllerToDeleteObserverTag;
std::map<mitk::LabelSetImage *, unsigned long> m_SegmentationObserverTags;
unsigned int InterpolationInfoChangedObserverTag;
unsigned int SurfaceInterpolationInfoChangedObserverTag;
unsigned int InterpolationAbortedObserverTag;
QGroupBox *m_GroupBoxEnableExclusiveInterpolationMode;
QComboBox *m_CmbInterpolation;
QPushButton *m_BtnApply2D;
QPushButton *m_BtnApplyForAllSlices2D;
QPushButton *m_BtnApply3D;
// T28261
// QPushButton *m_BtnSuggestPlane;
QCheckBox *m_ChkShowPositionNodes;
QPushButton *m_BtnReinit3DInterpolation;
mitk::DataNode::Pointer m_FeedbackNode;
mitk::DataNode::Pointer m_InterpolatedSurfaceNode;
mitk::DataNode::Pointer m_3DContourNode;
mitk::Image *m_Segmentation;
mitk::SliceNavigationController *m_LastSNC;
unsigned int m_LastSliceIndex;
- QHash<mitk::SliceNavigationController *, mitk::TimePointType> m_TimePoints;
+ mitk::TimePointType m_TimePoint;
bool m_2DInterpolationEnabled;
bool m_3DInterpolationEnabled;
unsigned int m_numTimesLabelSetConnectionAdded;
mitk::DataStorage::Pointer m_DataStorage;
QFuture<void> m_Future;
QFutureWatcher<void> m_Watcher;
QFuture<void> m_ModifyFuture;
QFutureWatcher<void> m_ModifyWatcher;
QTimer *m_Timer;
QFuture<void> m_PlaneFuture;
QFutureWatcher<void> m_PlaneWatcher;
mitk::Label::PixelType m_PreviousActiveLabelValue;
mitk::Label::PixelType m_CurrentActiveLabelValue;
unsigned int m_PreviousLayerIndex;
unsigned int m_CurrentLayerIndex;
bool m_FirstRun;
};
#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp
index 14d53c8f2b..f400af38f7 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.cpp
@@ -1,499 +1,500 @@
#include "QmitkTotalSegmentatorToolGUI.h"
#include "mitkProcessExecutor.h"
#include "mitkTotalSegmentatorTool.h"
#include <QApplication>
#include <QDir>
#include <QDirIterator>
#include <QFileDialog>
#include <QIcon>
#include <QmitkStyleManager.h>
#include <QMessageBox>
MITK_TOOL_GUI_MACRO(MITKSEGMENTATIONUI_EXPORT, QmitkTotalSegmentatorToolGUI, "")
QmitkTotalSegmentatorToolGUI::QmitkTotalSegmentatorToolGUI()
: QmitkMultiLabelSegWithPreviewToolGUIBase(), m_SuperclassEnableConfirmSegBtnFnc(m_EnableConfirmSegBtnFnc)
{
// Nvidia-smi command returning zero doesn't always imply lack of GPUs.
// Pytorch uses its own libraries to communicate to the GPUs. Hence, only a warning can be given.
if (m_GpuLoader.GetGPUCount() == 0)
{
std::string warning = "WARNING: No GPUs were detected on your machine. The TotalSegmentator tool can be very slow.";
this->ShowErrorMessage(warning);
}
m_EnableConfirmSegBtnFnc = [this](bool enabled)
{ return !m_FirstPreviewComputation ? m_SuperclassEnableConfirmSegBtnFnc(enabled) : false; };
}
void QmitkTotalSegmentatorToolGUI::ConnectNewTool(mitk::SegWithPreviewTool *newTool)
{
Superclass::ConnectNewTool(newTool);
m_FirstPreviewComputation = true;
}
void QmitkTotalSegmentatorToolGUI::InitializeUI(QBoxLayout *mainLayout)
{
m_Controls.setupUi(this);
#ifndef _WIN32
m_Controls.sysPythonComboBox->addItem("/usr/bin");
#endif
this->AutoParsePythonPaths();
m_Controls.sysPythonComboBox->addItem("Select");
m_Controls.sysPythonComboBox->setCurrentIndex(0);
m_Controls.pythonEnvComboBox->addItem("Select");
m_Controls.pythonEnvComboBox->setDuplicatesEnabled(false);
m_Controls.pythonEnvComboBox->setDisabled(true);
m_Controls.previewButton->setDisabled(true);
m_Controls.statusLabel->setTextFormat(Qt::RichText);
m_Controls.subtaskComboBox->addItems(VALID_TASKS);
QString welcomeText;
this->SetGPUInfo();
if (m_GpuLoader.GetGPUCount() != 0)
{
welcomeText = "<b>STATUS: </b><i>Welcome to TotalSegmentator tool. You're in luck: " +
QString::number(m_GpuLoader.GetGPUCount()) + " GPU(s) were detected.</i>";
}
else
{
welcomeText = "<b>STATUS: </b><i>Welcome to TotalSegmentator tool. Sorry, " +
QString::number(m_GpuLoader.GetGPUCount()) + " GPUs were detected.</i>";
}
connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnPreviewBtnClicked()));
connect(m_Controls.clearButton, SIGNAL(clicked()), this, SLOT(OnClearInstall()));
connect(m_Controls.installButton, SIGNAL(clicked()), this, SLOT(OnInstallBtnClicked()));
connect(m_Controls.overrideBox, SIGNAL(stateChanged(int)), this, SLOT(OnOverrideChecked(int)));
connect(m_Controls.pythonEnvComboBox,
QOverload<int>::of(&QComboBox::activated),
[=](int index) { OnPythonPathChanged(m_Controls.pythonEnvComboBox->itemText(index)); });
connect(m_Controls.sysPythonComboBox,
QOverload<int>::of(&QComboBox::activated),
[=](int index) { OnSystemPythonChanged(m_Controls.sysPythonComboBox->itemText(index)); });
QString lastSelectedPyEnv = m_Settings.value("TotalSeg/LastCustomPythonPath").toString();
if (!lastSelectedPyEnv.isEmpty() && lastSelectedPyEnv!= "Select")
{
m_Controls.pythonEnvComboBox->insertItem(0, lastSelectedPyEnv);
}
const QString storageDir = m_Installer.GetVirtualEnvPath();
m_IsInstalled = this->IsTotalSegmentatorInstalled(storageDir);
if (m_IsInstalled)
{
m_PythonPath = GetExactPythonPath(storageDir);
m_Installer.SetVirtualEnvPath(m_PythonPath);
this->EnableAll(m_IsInstalled);
welcomeText += " TotalSegmentator is already found installed.";
}
else
{
welcomeText += " TotalSegmentator is not installed. Please click on \"Install TotalSegmentator\" above.";
}
this->WriteStatusMessage(welcomeText);
QIcon deleteIcon =
QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/edit-delete.svg"));
QIcon arrowIcon =
QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/tango/scalable/actions/media-playback-start.svg"));
m_Controls.clearButton->setIcon(deleteIcon);
m_Controls.previewButton->setIcon(arrowIcon);
mainLayout->addLayout(m_Controls.verticalLayout);
Superclass::InitializeUI(mainLayout);
}
void QmitkTotalSegmentatorToolGUI::SetGPUInfo()
{
std::vector<QmitkGPUSpec> specs = m_GpuLoader.GetAllGPUSpecs();
for (const QmitkGPUSpec &gpuSpec : specs)
{
m_Controls.gpuComboBox->addItem(QString::number(gpuSpec.id) + ": " + gpuSpec.name + " (" + gpuSpec.memory + ")");
}
if (specs.empty())
{
m_Controls.gpuComboBox->setEditable(true);
m_Controls.gpuComboBox->addItem(QString::number(0));
m_Controls.gpuComboBox->setValidator(new QIntValidator(0, 999, this));
}
}
unsigned int QmitkTotalSegmentatorToolGUI::FetchSelectedGPUFromUI() const
{
QString gpuInfo = m_Controls.gpuComboBox->currentText();
if (m_GpuLoader.GetGPUCount() == 0)
{
return static_cast<unsigned int>(gpuInfo.toInt());
}
else
{
QString gpuId = gpuInfo.split(":", QString::SplitBehavior::SkipEmptyParts).first();
return static_cast<unsigned int>(gpuId.toInt());
}
}
void QmitkTotalSegmentatorToolGUI::EnableAll(bool isEnable)
{
m_Controls.previewButton->setEnabled(isEnable);
m_Controls.subtaskComboBox->setEnabled(isEnable);
m_Controls.installButton->setEnabled((!isEnable));
}
void QmitkTotalSegmentatorToolGUI::OnInstallBtnClicked()
{
bool isInstalled = false;
QString systemPython = OnSystemPythonChanged(m_Controls.sysPythonComboBox->currentText());
if (systemPython.isEmpty())
{
this->WriteErrorMessage("<b>ERROR: </b>Couldn't find Python.");
}
else
{
this->WriteStatusMessage("<b>STATUS: </b>Installing TotalSegmentator...");
m_Installer.SetSystemPythonPath(systemPython);
isInstalled = m_Installer.SetupVirtualEnv(m_Installer.VENV_NAME);
if (isInstalled)
{
m_PythonPath = this->GetExactPythonPath(m_Installer.GetVirtualEnvPath());
this->WriteStatusMessage("<b>STATUS: </b>Successfully installed TotalSegmentator.");
}
else
{
this->WriteErrorMessage("<b>ERROR: </b>Couldn't install TotalSegmentator.");
}
}
this->EnableAll(isInstalled);
}
void QmitkTotalSegmentatorToolGUI::OnPreviewBtnClicked()
{
auto tool = this->GetConnectedToolAs<mitk::TotalSegmentatorTool>();
if (nullptr == tool)
{
return;
}
try
{
m_Controls.previewButton->setEnabled(false);
qApp->processEvents();
if (!this->IsTotalSegmentatorInstalled(m_PythonPath))
{
throw std::runtime_error(WARNING_TOTALSEG_NOT_FOUND);
}
bool isFast = m_Controls.fastBox->isChecked();
QString subTask = m_Controls.subtaskComboBox->currentText();
if (subTask != VALID_TASKS[0])
{
isFast = true;
}
tool->SetPythonPath(m_PythonPath.toStdString());
tool->SetGpuId(FetchSelectedGPUFromUI());
tool->SetFast(isFast);
tool->SetSubTask(subTask.toStdString());
this->WriteStatusMessage(QString("<b>STATUS: </b><i>Starting Segmentation task... This might take a while.</i>"));
tool->UpdatePreview();
m_Controls.previewButton->setEnabled(true);
m_FirstPreviewComputation = false;
}
catch (const std::exception &e)
{
std::stringstream errorMsg;
errorMsg << "<b>STATUS: </b>Error while processing parameters for TotalSegmentator segmentation. Reason: "
<< e.what();
this->ShowErrorMessage(errorMsg.str());
this->WriteErrorMessage(QString::fromStdString(errorMsg.str()));
m_Controls.previewButton->setEnabled(true);
return;
}
catch (...)
{
std::string errorMsg = "Unkown error occured while generation TotalSegmentator segmentation.";
this->ShowErrorMessage(errorMsg);
m_Controls.previewButton->setEnabled(true);
return;
}
this->SetLabelSetPreview(tool->GetPreviewSegmentation());
this->ActualizePreviewLabelVisibility();
this->WriteStatusMessage("<b>STATUS: </b><i>Segmentation task finished successfully.</i>");
QString pythonPathTextItem = m_Controls.pythonEnvComboBox->currentText();
if (!pythonPathTextItem.isEmpty() && pythonPathTextItem != "Select") // only cache if the prediction ended without errors.
{
QString lastSelectedPyEnv = m_Settings.value("TotalSeg/LastCustomPythonPath").toString();
if (lastSelectedPyEnv != pythonPathTextItem)
{
m_Settings.setValue("TotalSeg/LastCustomPythonPath", pythonPathTextItem);
}
}
}
void QmitkTotalSegmentatorToolGUI::ShowErrorMessage(const std::string &message, QMessageBox::Icon icon)
{
this->setCursor(Qt::ArrowCursor);
QMessageBox *messageBox = new QMessageBox(icon, nullptr, message.c_str());
messageBox->exec();
delete messageBox;
MITK_WARN << message;
}
void QmitkTotalSegmentatorToolGUI::WriteStatusMessage(const QString &message)
{
m_Controls.statusLabel->setText(message);
m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: white");
qApp->processEvents();
}
void QmitkTotalSegmentatorToolGUI::WriteErrorMessage(const QString &message)
{
m_Controls.statusLabel->setText(message);
m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: red");
qApp->processEvents();
}
bool QmitkTotalSegmentatorToolGUI::IsTotalSegmentatorInstalled(const QString &pythonPath)
{
QString fullPath = pythonPath;
bool isPythonExists = false;
#ifdef _WIN32
isPythonExists = QFile::exists(fullPath + QDir::separator() + QString("python.exe"));
if (!(fullPath.endsWith("Scripts", Qt::CaseInsensitive) || fullPath.endsWith("Scripts/", Qt::CaseInsensitive)))
{
fullPath += QDir::separator() + QString("Scripts");
isPythonExists =
(!isPythonExists) ? QFile::exists(fullPath + QDir::separator() + QString("python.exe")) : isPythonExists;
}
#else
isPythonExists = QFile::exists(fullPath + QDir::separator() + QString("python3"));
if (!(fullPath.endsWith("bin", Qt::CaseInsensitive) || fullPath.endsWith("bin/", Qt::CaseInsensitive)))
{
fullPath += QDir::separator() + QString("bin");
isPythonExists =
(!isPythonExists) ? QFile::exists(fullPath + QDir::separator() + QString("python3")) : isPythonExists;
}
#endif
bool isExists = QFile::exists(fullPath + QDir::separator() + QString("TotalSegmentator")) && isPythonExists;
return isExists;
}
void QmitkTotalSegmentatorToolGUI::AutoParsePythonPaths()
{
QString homeDir = QDir::homePath();
std::vector<QString> searchDirs;
#ifdef _WIN32
searchDirs.push_back(QString("C:") + QDir::separator() + QString("ProgramData") + QDir::separator() +
QString("anaconda3"));
#else
// Add search locations for possible standard python paths here
searchDirs.push_back(homeDir + QDir::separator() + "environments");
searchDirs.push_back(homeDir + QDir::separator() + "anaconda3");
searchDirs.push_back(homeDir + QDir::separator() + "miniconda3");
searchDirs.push_back(homeDir + QDir::separator() + "opt" + QDir::separator() + "miniconda3");
searchDirs.push_back(homeDir + QDir::separator() + "opt" + QDir::separator() + "anaconda3");
#endif
for (QString searchDir : searchDirs)
{
if (searchDir.endsWith("anaconda3", Qt::CaseInsensitive))
{
if (QDir(searchDir).exists())
{
m_Controls.sysPythonComboBox->addItem("(base): " + searchDir);
searchDir.append((QDir::separator() + QString("envs")));
}
}
for (QDirIterator subIt(searchDir, QDir::AllDirs, QDirIterator::NoIteratorFlags); subIt.hasNext();)
{
subIt.next();
QString envName = subIt.fileName();
if (!envName.startsWith('.')) // Filter out irrelevent hidden folders, if any.
{
m_Controls.sysPythonComboBox->addItem("(" + envName + "): " + subIt.filePath());
}
}
}
}
QString QmitkTotalSegmentatorToolGUI::OnSystemPythonChanged(const QString &pyEnv)
{
QString pyPath;
if (pyEnv == QString("Select"))
{
m_Controls.previewButton->setDisabled(true);
QString path =
QFileDialog::getExistingDirectory(m_Controls.sysPythonComboBox->parentWidget(), "Python Path", "dir");
if (!path.isEmpty())
{
this->OnSystemPythonChanged(path); // recall same function for new path validation
bool oldState = m_Controls.sysPythonComboBox->blockSignals(true); // block signal firing while inserting item
m_Controls.sysPythonComboBox->insertItem(0, path);
m_Controls.sysPythonComboBox->setCurrentIndex(0);
m_Controls.sysPythonComboBox->blockSignals(
oldState); // unblock signal firing after inserting item. Remove this after Qt6 migration
}
}
else
{
QString uiPyPath = this->GetPythonPathFromUI(pyEnv);
pyPath = this->GetExactPythonPath(uiPyPath);
}
return pyPath;
}
void QmitkTotalSegmentatorToolGUI::OnPythonPathChanged(const QString &pyEnv)
{
if (pyEnv == QString("Select"))
{
m_Controls.previewButton->setDisabled(true);
QString path =
QFileDialog::getExistingDirectory(m_Controls.pythonEnvComboBox->parentWidget(), "Python Path", "dir");
if (!path.isEmpty())
{
this->OnPythonPathChanged(path); // recall same function for new path validation
bool oldState = m_Controls.pythonEnvComboBox->blockSignals(true); // block signal firing while inserting item
m_Controls.pythonEnvComboBox->insertItem(0, path);
m_Controls.pythonEnvComboBox->setCurrentIndex(0);
m_Controls.pythonEnvComboBox->blockSignals(
oldState); // unblock signal firing after inserting item. Remove this after Qt6 migration
}
}
else if (!this->IsTotalSegmentatorInstalled(pyEnv))
{
this->ShowErrorMessage(WARNING_TOTALSEG_NOT_FOUND);
m_Controls.previewButton->setDisabled(true);
}
else
{// Show positive status meeage
m_Controls.previewButton->setDisabled(false);
QString uiPyPath = this->GetPythonPathFromUI(pyEnv);
m_PythonPath = this->GetExactPythonPath(uiPyPath);
}
}
QString QmitkTotalSegmentatorToolGUI::GetPythonPathFromUI(const QString &pyUI) const
{
QString fullPath = pyUI;
if (-1 != fullPath.indexOf(")"))
{
fullPath = fullPath.mid(fullPath.indexOf(")") + 2);
}
return fullPath.simplified();
}
QString QmitkTotalSegmentatorToolGUI::GetExactPythonPath(const QString &pyEnv) const
{
QString fullPath = pyEnv;
bool isPythonExists = false;
#ifdef _WIN32
isPythonExists = QFile::exists(fullPath + QDir::separator() + QString("python.exe"));
if (!isPythonExists &&
!(fullPath.endsWith("Scripts", Qt::CaseInsensitive) || fullPath.endsWith("Scripts/", Qt::CaseInsensitive)))
{
fullPath += QDir::separator() + QString("Scripts");
isPythonExists = QFile::exists(fullPath + QDir::separator() + QString("python.exe"));
}
#else
isPythonExists = QFile::exists(fullPath + QDir::separator() + QString("python3"));
if (!isPythonExists && !(fullPath.endsWith("bin", Qt::CaseInsensitive) ||
fullPath.endsWith("bin/", Qt::CaseInsensitive)))
{
fullPath += QDir::separator() + QString("bin");
isPythonExists = QFile::exists(fullPath + QDir::separator() + QString("python3"));
}
#endif
if (!isPythonExists)
{
fullPath.clear();
}
return fullPath;
}
void QmitkTotalSegmentatorToolGUI::OnOverrideChecked(int state)
{
bool isEnabled = false;
if (state == Qt::Checked)
{
isEnabled = true;
m_Controls.previewButton->setDisabled(true);
m_PythonPath.clear();
}
else
{
m_PythonPath.clear();
m_Controls.previewButton->setDisabled(true);
if (m_IsInstalled)
{
const QString pythonPath = m_Installer.GetVirtualEnvPath();
m_PythonPath = this->GetExactPythonPath(pythonPath);
this->EnableAll(m_IsInstalled);
}
}
m_Controls.pythonEnvComboBox->setEnabled(isEnabled);
}
void QmitkTotalSegmentatorToolGUI::OnClearInstall()
{
QDir folderPath(m_Installer.GetVirtualEnvPath());
if (folderPath.removeRecursively())
{
m_Controls.installButton->setEnabled(true);
+ m_IsInstalled = false;
if (!m_Controls.overrideBox->isChecked())
{
m_Controls.previewButton->setEnabled(false);
}
}
else
{
MITK_ERROR
<< "The virtual environment couldn't be removed. Please check if you have the required access privileges or, some other process is accessing the folders.";
}
}
bool QmitkTotalSegmentatorToolInstaller::SetupVirtualEnv(const QString& venvName)
{
if (GetSystemPythonPath().isEmpty())
{
return false;
}
QDir folderPath(GetBaseDir());
folderPath.mkdir(venvName);
if (!folderPath.cd(venvName))
{
return false; // Check if directory creation was successful.
}
mitk::ProcessExecutor::ArgumentListType args;
auto spExec = mitk::ProcessExecutor::New();
auto spCommand = itk::CStyleCommand::New();
spCommand->SetCallback(&PrintProcessEvent);
spExec->AddObserver(mitk::ExternalProcessOutputEvent(), spCommand);
args.push_back("-m");
args.push_back("venv");
args.push_back(venvName.toStdString());
#ifdef _WIN32
QString pythonFile = GetSystemPythonPath() + QDir::separator() + "python.exe";
QString pythonExeFolder = "Scripts";
#else
QString pythonFile = GetSystemPythonPath() + QDir::separator() + "python3";
QString pythonExeFolder = "bin";
#endif
spExec->Execute(GetBaseDir().toStdString(), pythonFile.toStdString(), args); // Setup local virtual environment
if (folderPath.cd(pythonExeFolder))
{
this->SetPythonPath(folderPath.absolutePath());
this->SetPipPath(folderPath.absolutePath());
this->InstallPytorch();
for (auto &package : PACKAGES)
{
this->PipInstall(package.toStdString(), &PrintProcessEvent);
}
std::string pythonCode; // python syntax to check if torch is installed with CUDA.
pythonCode.append("import torch;");
pythonCode.append("print('Pytorch was installed with CUDA') if torch.cuda.is_available() else print('PyTorch was "
"installed WITHOUT CUDA');");
this->ExecutePython(pythonCode, &PrintProcessEvent);
return true;
}
return false;
}
QString QmitkTotalSegmentatorToolInstaller::GetVirtualEnvPath()
{
return STORAGE_DIR + VENV_NAME;
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h
index c100fe87cc..3fcf750bd5 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h
+++ b/Modules/SegmentationUI/Qmitk/QmitkTotalSegmentatorToolGUI.h
@@ -1,176 +1,177 @@
#ifndef QmitkTotalSegmentatorToolGUI_h_Included
#define QmitkTotalSegmentatorToolGUI_h_Included
#include "QmitkMultiLabelSegWithPreviewToolGUIBase.h"
#include "QmitkSetupVirtualEnvUtil.h"
#include "QmitknnUNetGPU.h"
#include "ui_QmitkTotalSegmentatorGUIControls.h"
#include <MitkSegmentationUIExports.h>
#include <QMessageBox>
#include <QSettings>
#include <QStandardPaths>
/**
* @brief Installer class for TotalSegmentator Tool.
* Class specifies the virtual environment name, install version, packages required to pip install
* and implements SetupVirtualEnv method.
*
*/
class QmitkTotalSegmentatorToolInstaller : public QmitkSetupVirtualEnvUtil
{
public:
const QString VENV_NAME = ".totalsegmentator";
const QString TOTALSEGMENTATOR_VERSION = "1.5.5";
const std::vector<QString> PACKAGES = {QString("Totalsegmentator==") + TOTALSEGMENTATOR_VERSION,
- QString("scipy==1.9.1")};
+ QString("scipy==1.9.1"),
+ QString("urllib3==1.26.15")};
const QString STORAGE_DIR;
inline QmitkTotalSegmentatorToolInstaller(
const QString baseDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator()
+ qApp->organizationName() + QDir::separator())
: QmitkSetupVirtualEnvUtil(baseDir), STORAGE_DIR(baseDir){};
bool SetupVirtualEnv(const QString &) override;
QString GetVirtualEnvPath() override;
};
/**
\ingroup org_mitk_gui_qt_interactivesegmentation_internal
\brief GUI for mitk::TotalSegmentatorTool.
\sa mitk::
*/
class MITKSEGMENTATIONUI_EXPORT QmitkTotalSegmentatorToolGUI : public QmitkMultiLabelSegWithPreviewToolGUIBase
{
Q_OBJECT
public:
mitkClassMacro(QmitkTotalSegmentatorToolGUI, QmitkMultiLabelSegWithPreviewToolGUIBase);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
protected slots:
/**
* @brief Qt Slot
*/
void OnPreviewBtnClicked();
/**
* @brief Qt Slot
*/
void OnPythonPathChanged(const QString &);
/**
* @brief Qt Slot
*/
QString OnSystemPythonChanged(const QString &);
/**
* @brief Qt Slot
*/
void OnInstallBtnClicked();
/**
* @brief Qt Slot
*/
void OnOverrideChecked(int);
/**
* @brief Qt Slot
*/
void OnClearInstall();
protected:
QmitkTotalSegmentatorToolGUI();
~QmitkTotalSegmentatorToolGUI() = default;
void ConnectNewTool(mitk::SegWithPreviewTool *newTool) override;
void InitializeUI(QBoxLayout *mainLayout) override;
/**
* @brief Enable (or Disable) GUI elements.
*/
void EnableAll(bool);
/**
* @brief Searches and parses paths of python virtual enviroments
* from predefined lookout locations
*/
void AutoParsePythonPaths();
/**
* @brief Checks if TotalSegmentator command is valid in the selected python virtual environment.
*
* @return bool
*/
bool IsTotalSegmentatorInstalled(const QString &);
/**
* @brief Creates a QMessage object and shows on screen.
*/
void ShowErrorMessage(const std::string &, QMessageBox::Icon = QMessageBox::Critical);
/**
* @brief Writes any message in white on the tool pane.
*/
void WriteStatusMessage(const QString &);
/**
* @brief Writes any message in red on the tool pane.
*/
void WriteErrorMessage(const QString &);
/**
* @brief Adds GPU information to the gpu combo box.
* In case, there aren't any GPUs avaialble, the combo box will be
* rendered editable.
*/
void SetGPUInfo();
/**
* @brief Returns GPU id of the selected GPU from the Combo box.
*
* @return unsigned int
*/
unsigned int FetchSelectedGPUFromUI() const;
/**
* @brief Get the virtual env path from UI combobox removing any
* extra special characters.
*
* @return QString
*/
QString GetPythonPathFromUI(const QString &) const;
/**
* @brief Get the Exact Python Path for any OS
* from the virtual environment path.
* @return QString
*/
QString GetExactPythonPath(const QString &) const;
/**
* @brief For storing values like Python path across sessions.
*/
QSettings m_Settings;
QString m_PythonPath;
QmitkGPULoader m_GpuLoader;
Ui_QmitkTotalSegmentatorToolGUIControls m_Controls;
bool m_FirstPreviewComputation = true;
bool m_IsInstalled = false;
EnableConfirmSegBtnFunctionType m_SuperclassEnableConfirmSegBtnFnc;
const std::string WARNING_TOTALSEG_NOT_FOUND =
"TotalSegmentator is not detected in the selected python environment.Please select a valid "
"python environment or install TotalSegmentator.";
const QStringList VALID_TASKS = {
"total",
"cerebral_bleed",
"hip_implant",
"coronary_arteries",
"body",
"lung_vessels",
"pleural_pericard_effusion"
};
QmitkTotalSegmentatorToolInstaller m_Installer;
};
#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.cpp
index 1182ce51b0..6e449c5a4e 100644
--- a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUI.cpp
@@ -1,1196 +1,1197 @@
/*============================================================================
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 "QmitknnUNetToolGUI.h"
#include "mitkProcessExecutor.h"
#include "mitknnUnetTool.h"
+#include <mitkTimeNavigationController.h>
#include <QApplication>
#include <QDir>
#include <QDirIterator>
#include <QIcon>
#include <QmitkStyleManager.h>
#include <QmitknnUNetEnsembleLayout.h>
#include <QtGlobal>
#include <algorithm>
#include <ctkCollapsibleGroupBox.h>
#include <itksys/SystemTools.hxx>
#include <nlohmann/json.hpp>
#include <mitkIOUtil.h>
MITK_TOOL_GUI_MACRO(MITKSEGMENTATIONUI_EXPORT, QmitknnUNetToolGUI, "")
QmitknnUNetToolGUI::QmitknnUNetToolGUI() : QmitkMultiLabelSegWithPreviewToolGUIBase(), m_SuperclassEnableConfirmSegBtnFnc(m_EnableConfirmSegBtnFnc)
{
// Nvidia-smi command returning zero doesn't always imply lack of GPUs.
// Pytorch uses its own libraries to communicate to the GPUs. Hence, only a warning can be given.
if (m_GpuLoader.GetGPUCount() == 0)
{
std::string warning = "WARNING: No GPUs were detected on your machine. The nnUNet tool might not work.";
this->ShowErrorMessage(warning);
}
// define predicates for multi modal data selection combobox
auto imageType = mitk::TNodePredicateDataType<mitk::Image>::New();
auto labelSetImageType = mitk::NodePredicateNot::New(mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
m_MultiModalPredicate = mitk::NodePredicateAnd::New(imageType, labelSetImageType).GetPointer();
m_nnUNetThread = new QThread(this);
m_Worker = new nnUNetDownloadWorker;
m_Worker->moveToThread(m_nnUNetThread);
m_EnableConfirmSegBtnFnc = [this](bool enabled)
{
return !m_FirstPreviewComputation ? m_SuperclassEnableConfirmSegBtnFnc(enabled) : false;
};
}
QmitknnUNetToolGUI::~QmitknnUNetToolGUI()
{
m_nnUNetThread->quit();
m_nnUNetThread->wait();
}
void QmitknnUNetToolGUI::ConnectNewTool(mitk::SegWithPreviewTool *newTool)
{
Superclass::ConnectNewTool(newTool);
newTool->IsTimePointChangeAwareOff();
m_FirstPreviewComputation = true;
}
void QmitknnUNetToolGUI::InitializeUI(QBoxLayout *mainLayout)
{
m_Controls.setupUi(this);
#ifndef _WIN32
m_Controls.pythonEnvComboBox->addItem("/usr/bin");
#endif
m_Controls.pythonEnvComboBox->addItem("Select");
AutoParsePythonPaths();
SetGPUInfo();
connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnPreviewRequested()));
connect(m_Controls.modeldirectoryBox,
SIGNAL(directoryChanged(const QString &)),
this,
SLOT(OnDirectoryChanged(const QString &)));
connect(
m_Controls.modelBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnModelChanged(const QString &)));
connect(m_Controls.taskBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnTaskChanged(const QString &)));
connect(
m_Controls.plannerBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnTrainerChanged(const QString &)));
connect(m_Controls.multiModalBox, SIGNAL(stateChanged(int)), this, SLOT(OnCheckBoxChanged(int)));
connect(m_Controls.pythonEnvComboBox,
#if QT_VERSION >= 0x050F00 // 5.15
SIGNAL(textActivated(const QString &)),
#elif QT_VERSION >= 0x050C00 // 5.12
SIGNAL(currentTextChanged(const QString &)),
#endif
this,
SLOT(OnPythonPathChanged(const QString &)));
connect(m_Controls.refreshdirectoryBox, SIGNAL(clicked()), this, SLOT(OnRefreshPresssed()));
connect(m_Controls.clearCacheButton, SIGNAL(clicked()), this, SLOT(OnClearCachePressed()));
connect(m_Controls.startDownloadButton, SIGNAL(clicked()), this, SLOT(OnDownloadModel()));
connect(m_Controls.stopDownloadButton, SIGNAL(clicked()), this, SLOT(OnStopDownload()));
// Qthreads
qRegisterMetaType<mitk::ProcessExecutor::Pointer>();
qRegisterMetaType<mitk::ProcessExecutor::ArgumentListType>();
connect(this, &QmitknnUNetToolGUI::Operate, m_Worker, &nnUNetDownloadWorker::DoWork);
connect(m_Worker, &nnUNetDownloadWorker::Exit, this, &QmitknnUNetToolGUI::OnDownloadWorkerExit);
connect(m_nnUNetThread, &QThread::finished, m_Worker, &QObject::deleteLater);
m_Controls.multiModalValueLabel->setStyleSheet("font-weight: bold; color: white");
m_Controls.multiModalValueLabel->setVisible(false);
m_Controls.requiredModalitiesLabel->setVisible(false);
m_Controls.stopDownloadButton->setVisible(false);
m_Controls.previewButton->setEnabled(false);
QIcon refreshIcon =
QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/view-refresh.svg"));
m_Controls.refreshdirectoryBox->setIcon(refreshIcon);
QIcon dirIcon =
QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/document-open.svg"));
m_Controls.modeldirectoryBox->setIcon(dirIcon);
m_Controls.refreshdirectoryBox->setEnabled(true);
QIcon stopIcon =
QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/status/dialog-error.svg"));
m_Controls.stopDownloadButton->setIcon(stopIcon);
m_Controls.statusLabel->setTextFormat(Qt::RichText);
if (m_GpuLoader.GetGPUCount() != 0)
{
WriteStatusMessage(QString("<b>STATUS: </b><i>Welcome to nnUNet. " + QString::number(m_GpuLoader.GetGPUCount()) +
" GPUs were detected.</i>"));
}
else
{
WriteErrorMessage(QString("<b>STATUS: </b><i>Welcome to nnUNet. " + QString::number(m_GpuLoader.GetGPUCount()) +
" GPUs were detected.</i>"));
}
mainLayout->addLayout(m_Controls.verticalLayout);
Superclass::InitializeUI(mainLayout);
m_UI_ROWS = m_Controls.advancedSettingsLayout->rowCount(); // Must do. Row count is correct only here.
this->DisableEverything();
QString lastSelectedPyEnv = m_Settings.value("nnUNet/LastPythonPath").toString();
m_Controls.pythonEnvComboBox->setCurrentText(lastSelectedPyEnv);
}
void QmitknnUNetToolGUI::EnableWidgets(bool enabled)
{
Superclass::EnableWidgets(enabled);
}
void QmitknnUNetToolGUI::ClearAllModalities()
{
m_Controls.multiModalBox->setChecked(false);
this->ClearAllModalLabels();
}
void QmitknnUNetToolGUI::ClearAllModalLabels()
{
for (auto modalLabel : m_ModalLabels)
{
delete modalLabel; // delete the layout item
m_ModalLabels.pop_back();
}
m_Controls.advancedSettingsLayout->update();
}
void QmitknnUNetToolGUI::DisableEverything()
{
m_Controls.modeldirectoryBox->setEnabled(false);
m_Controls.refreshdirectoryBox->setEnabled(false);
m_Controls.previewButton->setEnabled(false);
m_Controls.multiModalValueLabel->setVisible(false);
m_Controls.multiModalBox->setEnabled(false);
this->ClearAllComboBoxes();
this->ClearAllModalities();
}
void QmitknnUNetToolGUI::ClearAllComboBoxes()
{
m_Controls.modelBox->clear();
m_Controls.taskBox->clear();
m_Controls.foldBox->clear();
m_Controls.trainerBox->clear();
m_Controls.plannerBox->clear();
for (auto &layout : m_EnsembleParams)
{
layout->modelBox->clear();
layout->trainerBox->clear();
layout->plannerBox->clear();
layout->foldBox->clear();
}
}
std::vector<mitk::Image::ConstPointer> QmitknnUNetToolGUI::FetchMultiModalImagesFromUI()
{
std::vector<mitk::Image::ConstPointer> modals;
if (m_Controls.multiModalBox->isChecked() && !m_Modalities.empty())
{
std::set<std::string> nodeNames; // set container for keeping names of all nodes to check if they are added twice.
for (QmitkSingleNodeSelectionWidget *modality : m_Modalities)
{
mitk::DataNode::Pointer node = modality->GetSelectedNode();
if (nodeNames.find(node->GetName()) == nodeNames.end())
{
modals.push_back(dynamic_cast<const mitk::Image *>(node->GetData()));
nodeNames.insert(node->GetName());
}
else
{
throw std::runtime_error("Same modality is selected more than once. Please change your selection.");
break;
}
}
}
return modals;
}
bool QmitknnUNetToolGUI::IsNNUNetInstalled(const QString &pythonPath)
{
QString fullPath = pythonPath;
#ifdef _WIN32
if (!(fullPath.endsWith("Scripts", Qt::CaseInsensitive) || fullPath.endsWith("Scripts/", Qt::CaseInsensitive)))
{
fullPath += QDir::separator() + QString("Scripts");
}
#else
if (!(fullPath.endsWith("bin", Qt::CaseInsensitive) || fullPath.endsWith("bin/", Qt::CaseInsensitive)))
{
fullPath += QDir::separator() + QString("bin");
}
#endif
fullPath = fullPath.mid(fullPath.indexOf(" ") + 1);
bool isExists = QFile::exists(fullPath + QDir::separator() + QString("nnUNet_predict")) &&
QFile::exists(fullPath + QDir::separator() + QString("python3"));
return isExists;
}
void QmitknnUNetToolGUI::ShowErrorMessage(const std::string &message, QMessageBox::Icon icon)
{
this->setCursor(Qt::ArrowCursor);
QMessageBox *messageBox = new QMessageBox(icon, nullptr, message.c_str());
messageBox->exec();
delete messageBox;
MITK_WARN << message;
}
void QmitknnUNetToolGUI::WriteStatusMessage(const QString &message)
{
m_Controls.statusLabel->setText(message);
m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: white");
}
void QmitknnUNetToolGUI::WriteErrorMessage(const QString &message)
{
m_Controls.statusLabel->setText(message);
m_Controls.statusLabel->setStyleSheet("font-weight: bold; color: red");
}
void QmitknnUNetToolGUI::ProcessEnsembleModelsParams(mitk::nnUNetTool::Pointer tool)
{
if (m_EnsembleParams[0]->modelBox->currentText() == m_EnsembleParams[1]->modelBox->currentText())
{
throw std::runtime_error("Both models you have selected for ensembling are the same.");
}
QString taskName = m_Controls.taskBox->currentText();
bool isPPJson = m_Controls.postProcessingCheckBox->isChecked();
std::vector<mitk::ModelParams> requestQ;
QString ppDirFolderNamePart1 = "ensemble_";
QStringList ppDirFolderNameParts;
for (auto &layout : m_EnsembleParams)
{
QStringList ppDirFolderName;
QString modelName = layout->modelBox->currentText();
ppDirFolderName << modelName;
ppDirFolderName << "__";
QString trainer = layout->trainerBox->currentText();
ppDirFolderName << trainer;
ppDirFolderName << "__";
QString planId = layout->plannerBox->currentText();
ppDirFolderName << planId;
if (!this->IsModelExists(modelName, taskName, QString(trainer + "__" + planId)))
{
std::string errorMsg = "The configuration " + modelName.toStdString() +
" you have selected doesn't exist. Check your Results Folder again.";
throw std::runtime_error(errorMsg);
}
std::vector<std::string> testfold = FetchSelectedFoldsFromUI(layout->foldBox);
mitk::ModelParams modelObject = MapToRequest(modelName, taskName, trainer, planId, testfold);
requestQ.push_back(modelObject);
ppDirFolderNameParts << ppDirFolderName.join(QString(""));
}
tool->EnsembleOn();
if (isPPJson)
{
QString ppJsonFilePossibility1 = QDir::cleanPath(
m_ParentFolder->getResultsFolder() + QDir::separator() + "nnUNet" + QDir::separator() + "ensembles" +
QDir::separator() + taskName + QDir::separator() + ppDirFolderNamePart1 + ppDirFolderNameParts.first() + "--" +
ppDirFolderNameParts.last() + QDir::separator() + "postprocessing.json");
QString ppJsonFilePossibility2 = QDir::cleanPath(
m_ParentFolder->getResultsFolder() + QDir::separator() + "nnUNet" + QDir::separator() + "ensembles" +
QDir::separator() + taskName + QDir::separator() + ppDirFolderNamePart1 + ppDirFolderNameParts.last() + "--" +
ppDirFolderNameParts.first() + QDir::separator() + "postprocessing.json");
if (QFile(ppJsonFilePossibility1).exists())
{
tool->SetPostProcessingJsonDirectory(ppJsonFilePossibility1.toStdString());
const QString statusMsg = "<i>Post Processing JSON file found: </i>" + ppJsonFilePossibility1;
this->WriteStatusMessage(statusMsg);
}
else if (QFile(ppJsonFilePossibility2).exists())
{
tool->SetPostProcessingJsonDirectory(ppJsonFilePossibility2.toStdString());
const QString statusMsg = "<i>Post Processing JSON file found:</i>" + ppJsonFilePossibility2;
this->WriteStatusMessage(statusMsg);
}
else
{
std::string errorMsg =
"No post processing file was found for the selected ensemble combination. Continuing anyway...";
this->ShowErrorMessage(errorMsg);
}
}
tool->m_ParamQ.clear();
tool->m_ParamQ = requestQ;
}
void QmitknnUNetToolGUI::ProcessModelParams(mitk::nnUNetTool::Pointer tool)
{
tool->EnsembleOff();
std::vector<mitk::ModelParams> requestQ;
QString modelName = m_Controls.modelBox->currentText();
QString taskName = m_Controls.taskBox->currentText();
QString trainer = m_Controls.trainerBox->currentText();
QString planId = m_Controls.plannerBox->currentText();
std::vector<std::string> fetchedFolds = this->FetchSelectedFoldsFromUI(m_Controls.foldBox);
mitk::ModelParams modelObject = MapToRequest(modelName, taskName, trainer, planId, fetchedFolds);
requestQ.push_back(modelObject);
tool->m_ParamQ.clear();
tool->m_ParamQ = requestQ;
}
bool QmitknnUNetToolGUI::IsModelExists(const QString &modelName, const QString &taskName, const QString &trainerPlanner)
{
QString modelSearchPath =
QDir::cleanPath(m_ParentFolder->getResultsFolder() + QDir::separator() + "nnUNet" + QDir::separator() + modelName +
QDir::separator() + taskName + QDir::separator() + trainerPlanner);
if (QDir(modelSearchPath).exists())
{
return true;
}
return false;
}
void QmitknnUNetToolGUI::CheckAllInCheckableComboBox(ctkCheckableComboBox *foldBox)
{
// Recalling all added items to check-mark it.
const QAbstractItemModel *qaim = foldBox->checkableModel();
auto rows = qaim->rowCount();
for (std::remove_const_t<decltype(rows)> i = 0; i < rows; ++i)
{
const QModelIndex mi = qaim->index(i, 0);
foldBox->setCheckState(mi, Qt::Checked);
}
}
std::pair<QStringList, QStringList> QmitknnUNetToolGUI::ExtractTrainerPlannerFromString(QStringList trainerPlanners)
{
QString splitterString = "__";
QStringList trainers, planners;
for (const auto &trainerPlanner : trainerPlanners)
{
trainers << trainerPlanner.split(splitterString, QString::SplitBehavior::SkipEmptyParts).first();
planners << trainerPlanner.split(splitterString, QString::SplitBehavior::SkipEmptyParts).last();
}
trainers.removeDuplicates();
planners.removeDuplicates();
return std::make_pair(trainers, planners);
}
std::vector<std::string> QmitknnUNetToolGUI::FetchSelectedFoldsFromUI(ctkCheckableComboBox *foldBox)
{
std::vector<std::string> folds;
if (foldBox->noneChecked())
{
this->CheckAllInCheckableComboBox(foldBox);
}
QModelIndexList foldList = foldBox->checkedIndexes();
for (const auto &index : foldList)
{
QString foldQString = foldBox->itemText(index.row());
if(foldQString != "dummy_element_that_nobody_can_see")
{
foldQString = foldQString.split("_", QString::SplitBehavior::SkipEmptyParts).last();
folds.push_back(foldQString.toStdString());
}
else
{
throw std::runtime_error("Folds are not recognized. Please check if your nnUNet results folder structure is legitimate");
}
}
return folds;
}
void QmitknnUNetToolGUI::UpdateCacheCountOnUI()
{
QString cacheText = m_CACHE_COUNT_BASE_LABEL + QString::number(m_Cache.size());
m_Controls.cacheCountLabel->setText(cacheText);
}
void QmitknnUNetToolGUI::AddToCache(size_t &hashKey, mitk::LabelSetImage::ConstPointer mlPreview)
{
nnUNetCache *newCacheObj = new nnUNetCache;
newCacheObj->m_SegCache = mlPreview;
m_Cache.insert(hashKey, newCacheObj);
MITK_INFO << "New hash: " << hashKey << " " << newCacheObj->m_SegCache.GetPointer();
this->UpdateCacheCountOnUI();
}
void QmitknnUNetToolGUI::SetGPUInfo()
{
std::vector<QmitkGPUSpec> specs = m_GpuLoader.GetAllGPUSpecs();
for (const QmitkGPUSpec &gpuSpec : specs)
{
m_Controls.gpuComboBox->addItem(QString::number(gpuSpec.id) + ": " + gpuSpec.name + " (" + gpuSpec.memory + ")");
}
if (specs.empty())
{
m_Controls.gpuComboBox->setEditable(true);
m_Controls.gpuComboBox->addItem(QString::number(0));
m_Controls.gpuComboBox->setValidator(new QIntValidator(0, 999, this));
}
}
unsigned int QmitknnUNetToolGUI::FetchSelectedGPUFromUI()
{
QString gpuInfo = m_Controls.gpuComboBox->currentText();
if (m_GpuLoader.GetGPUCount() == 0)
{
return static_cast<unsigned int>(gpuInfo.toInt());
}
else
{
QString gpuId = gpuInfo.split(":", QString::SplitBehavior::SkipEmptyParts).first();
return static_cast<unsigned int>(gpuId.toInt());
}
}
QString QmitknnUNetToolGUI::FetchResultsFolderFromEnv()
{
const char *pathVal = itksys::SystemTools::GetEnv("RESULTS_FOLDER");
QString retVal;
if (pathVal)
{
retVal = QString::fromUtf8(pathVal);
}
else
{
retVal = m_Settings.value("nnUNet/LastRESULTS_FOLDERPath").toString();
}
return retVal;
}
void QmitknnUNetToolGUI::DumpJSONfromPickle(const QString &picklePath)
{
const QString pickleFile = picklePath + QDir::separator() + m_PICKLE_FILENAME;
const QString jsonFile = picklePath + QDir::separator() + m_MITK_EXPORT_JSON_FILENAME;
if (!QFile::exists(jsonFile))
{
mitk::ProcessExecutor::Pointer spExec = mitk::ProcessExecutor::New();
mitk::ProcessExecutor::ArgumentListType args;
args.push_back("-c");
std::string pythonCode; // python syntax to parse plans.pkl file and export as Json file.
pythonCode.append("import pickle;");
pythonCode.append("import json;");
pythonCode.append("loaded_pickle = pickle.load(open('");
pythonCode.append(pickleFile.toStdString());
pythonCode.append("','rb'));");
pythonCode.append("modal_dict = {key: loaded_pickle[key] for key in loaded_pickle.keys() if key in "
"['modalities','num_modalities']};");
pythonCode.append("json.dump(modal_dict, open('");
pythonCode.append(jsonFile.toStdString());
pythonCode.append("', 'w'))");
args.push_back(pythonCode);
try
{
spExec->Execute(m_PythonPath.toStdString(), "python3", args);
}
catch (const mitk::Exception &e)
{
MITK_ERROR << "Pickle parsing FAILED!" << e.GetDescription();
this->WriteStatusMessage(
"Parsing failed in backend. Multiple Modalities will now have to be manually entered by the user.");
}
}
}
void QmitknnUNetToolGUI::ExportAvailableModelsAsJSON(const QString &resultsFolder)
{
const QString jsonPath = resultsFolder + QDir::separator() + m_AVAILABLE_MODELS_JSON_FILENAME;
if (!QFile::exists(jsonPath))
{
auto spExec = mitk::ProcessExecutor::New();
mitk::ProcessExecutor::ArgumentListType args;
args.push_back("--export");
args.push_back(resultsFolder.toStdString());
try
{
spExec->Execute(m_PythonPath.toStdString(), "nnUNet_print_available_pretrained_models", args);
}
catch (const mitk::Exception &e)
{
MITK_ERROR << "Exporting information FAILED." << e.GetDescription();
this->WriteStatusMessage("Exporting information FAILED.");
}
}
}
void QmitknnUNetToolGUI::DisplayMultiModalInfoFromJSON(const QString &jsonPath)
{
std::ifstream file(jsonPath.toStdString());
if (file.is_open())
{
auto jsonObj = nlohmann::json::parse(file, nullptr, false);
if (jsonObj.is_discarded() || !jsonObj.is_object())
{
MITK_ERROR << "Could not parse \"" << jsonPath.toStdString() << "\" as JSON object!";
return;
}
auto num_mods = jsonObj["num_modalities"].get<int>();
this->ClearAllModalLabels();
if (num_mods > 1)
{
m_Controls.multiModalBox->setChecked(true);
m_Controls.multiModalBox->setEnabled(false);
m_Controls.multiModalValueLabel->setText(QString::number(num_mods));
OnModalitiesNumberChanged(num_mods);
m_Controls.advancedSettingsLayout->update();
auto obj = jsonObj["modalities"];
int count = 0;
for (const auto &value : obj)
{
QLabel *label = new QLabel(QString::fromStdString("<i>" + value.get<std::string>() + "</i>"), this);
m_ModalLabels.push_back(label);
m_Controls.advancedSettingsLayout->addWidget(label, m_UI_ROWS + 1 + count, 0);
count++;
}
m_Controls.advancedSettingsLayout->update();
}
else
{
m_Controls.multiModalBox->setChecked(false);
}
}
}
void QmitknnUNetToolGUI::FillAvailableModelsInfoFromJSON(const QString &jsonPath)
{
std::ifstream file(jsonPath.toStdString());
if (file.is_open() && m_Controls.availableBox->count() < 1)
{
auto jsonObj = nlohmann::json::parse(file, nullptr, false);
if (jsonObj.is_discarded() || !jsonObj.is_object())
{
MITK_ERROR << "Could not parse \"" << jsonPath.toStdString() << "\" as JSON object!";
return;
}
for (const auto &obj : jsonObj.items())
{
m_Controls.availableBox->addItem(QString::fromStdString(obj.key()));
}
}
}
mitk::ModelParams QmitknnUNetToolGUI::MapToRequest(const QString &modelName,
const QString &taskName,
const QString &trainer,
const QString &planId,
const std::vector<std::string> &folds)
{
mitk::ModelParams requestObject;
requestObject.model = modelName.toStdString();
requestObject.trainer = trainer.toStdString();
requestObject.planId = planId.toStdString();
requestObject.task = taskName.toStdString();
requestObject.folds = folds;
mitk::nnUNetTool::Pointer tool = this->GetConnectedToolAs<mitk::nnUNetTool>();
requestObject.inputName = tool->GetRefNode()->GetName();
requestObject.timeStamp =
std::to_string(mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint());
return requestObject;
}
void QmitknnUNetToolGUI::SetComboBoxToNone(ctkCheckableComboBox* comboBox)
{
comboBox->clear();
comboBox->addItem("dummy_element_that_nobody_can_see");
qobject_cast<QListView *>(comboBox->view())->setRowHidden(0, true); // For the cosmetic purpose of showing "None" on the combobox.
}
/* ---------------------SLOTS---------------------------------------*/
void QmitknnUNetToolGUI::OnPreviewRequested()
{
mitk::nnUNetTool::Pointer tool = this->GetConnectedToolAs<mitk::nnUNetTool>();
if (nullptr != tool)
{
QString pythonPathTextItem = "";
try
{
size_t hashKey(0);
m_Controls.previewButton->setEnabled(false); // To prevent misclicked back2back prediction.
qApp->processEvents();
tool->PredictOn(); // purposefully placed to make tool->GetMTime different than before.
QString modelName = m_Controls.modelBox->currentText();
if (modelName.startsWith("ensemble", Qt::CaseInsensitive))
{
this->ProcessEnsembleModelsParams(tool);
}
else
{
this->ProcessModelParams(tool);
}
pythonPathTextItem = m_Controls.pythonEnvComboBox->currentText();
QString pythonPath = m_PythonPath;
if (!this->IsNNUNetInstalled(pythonPath))
{
throw std::runtime_error("nnUNet is not detected in the selected python environment. Please select a valid "
"python environment or install nnUNet.");
}
tool->SetPythonPath(pythonPath.toStdString());
tool->SetModelDirectory(m_ParentFolder->getResultsFolder().toStdString());
// checkboxes
tool->SetMirror(m_Controls.mirrorBox->isChecked());
tool->SetMixedPrecision(m_Controls.mixedPrecisionBox->isChecked());
tool->SetNoPip(false);
bool doCache = m_Controls.enableCachingCheckBox->isChecked();
// Spinboxes
tool->SetGpuId(FetchSelectedGPUFromUI());
// Multi-Modal
tool->MultiModalOff();
if (m_Controls.multiModalBox->isChecked())
{
tool->m_OtherModalPaths.clear();
tool->m_OtherModalPaths = FetchMultiModalImagesFromUI();
tool->MultiModalOn();
}
if (doCache)
{
hashKey = nnUNetCache::GetUniqueHash(tool->m_ParamQ);
if (m_Cache.contains(hashKey))
{
tool->PredictOff(); // purposefully placed to make tool->GetMTime different than before.
}
}
if (tool->GetPredict())
{
tool->m_InputBuffer = nullptr;
this->WriteStatusMessage(
QString("<b>STATUS: </b><i>Starting Segmentation task... This might take a while.</i>"));
tool->UpdatePreview();
if (nullptr == tool->GetOutputBuffer())
{
this->SegmentationProcessFailed();
}
else
{
this->SegmentationResultHandler(tool);
if (doCache)
{
this->AddToCache(hashKey, tool->GetOutputBuffer());
}
tool->ClearOutputBuffer();
}
tool->PredictOff(); // purposefully placed to make tool->GetMTime different than before.
}
else
{
MITK_INFO << "won't do segmentation. Key found: " << QString::number(hashKey).toStdString();
if (m_Cache.contains(hashKey))
{
nnUNetCache *cacheObject = m_Cache[hashKey];
MITK_INFO << "fetched pointer " << cacheObject->m_SegCache.GetPointer();
tool->SetOutputBuffer(const_cast<mitk::LabelSetImage *>(cacheObject->m_SegCache.GetPointer()));
this->SegmentationResultHandler(tool, true);
}
}
m_Controls.previewButton->setEnabled(true);
}
catch (const std::exception &e)
{
std::stringstream errorMsg;
errorMsg << "<b>STATUS: </b>Error while processing parameters for nnUNet segmentation. Reason: " << e.what();
this->ShowErrorMessage(errorMsg.str());
this->WriteErrorMessage(QString::fromStdString(errorMsg.str()));
m_Controls.previewButton->setEnabled(true);
tool->PredictOff();
return;
}
catch (...)
{
std::string errorMsg = "Unkown error occured while generation nnUNet segmentation.";
this->ShowErrorMessage(errorMsg);
m_Controls.previewButton->setEnabled(true);
tool->PredictOff();
return;
}
if (!pythonPathTextItem.isEmpty())
{ // only cache if the prediction ended without errors.
m_Settings.setValue("nnUNet/LastPythonPath", pythonPathTextItem);
}
}
}
void QmitknnUNetToolGUI::OnRefreshPresssed()
{
const QString resultsFolder = m_Controls.modeldirectoryBox->directory();
this->OnDirectoryChanged(resultsFolder);
}
void QmitknnUNetToolGUI::OnDirectoryChanged(const QString &resultsFolder)
{
m_IsResultsFolderValid = false;
m_Controls.previewButton->setEnabled(false);
this->ClearAllComboBoxes();
this->ClearAllModalities();
m_ParentFolder = std::make_shared<QmitknnUNetFolderParser>(resultsFolder);
auto tasks = m_ParentFolder->getAllTasks<QStringList>();
tasks.removeDuplicates();
std::for_each(tasks.begin(), tasks.end(), [this](QString task) { m_Controls.taskBox->addItem(task); });
m_Settings.setValue("nnUNet/LastRESULTS_FOLDERPath", resultsFolder);
}
void QmitknnUNetToolGUI::OnModelChanged(const QString &model)
{
if (model.isEmpty())
{
return;
}
this->ClearAllModalities();
auto selectedTask = m_Controls.taskBox->currentText();
ctkComboBox *box = qobject_cast<ctkComboBox *>(sender());
if (box == m_Controls.modelBox)
{
if (model == m_VALID_MODELS.last())
{
m_Controls.trainerBox->setVisible(false);
m_Controls.trainerLabel->setVisible(false);
m_Controls.plannerBox->setVisible(false);
m_Controls.plannerLabel->setVisible(false);
m_Controls.foldBox->setVisible(false);
m_Controls.foldLabel->setVisible(false);
m_Controls.previewButton->setEnabled(false);
this->ShowEnsembleLayout(true);
auto models = m_ParentFolder->getModelsForTask<QStringList>(m_Controls.taskBox->currentText());
models.removeDuplicates();
models.removeOne(m_VALID_MODELS.last());
for (auto &layout : m_EnsembleParams)
{
layout->modelBox->clear();
layout->trainerBox->clear();
layout->plannerBox->clear();
std::for_each(models.begin(),
models.end(),
[&layout, this](QString model)
{
if (m_VALID_MODELS.contains(model, Qt::CaseInsensitive))
layout->modelBox->addItem(model);
});
}
}
else
{
m_Controls.trainerBox->setVisible(true);
m_Controls.trainerLabel->setVisible(true);
m_Controls.plannerBox->setVisible(true);
m_Controls.plannerLabel->setVisible(true);
m_Controls.foldBox->setVisible(true);
m_Controls.foldLabel->setVisible(true);
m_Controls.previewButton->setEnabled(false);
this->ShowEnsembleLayout(false);
m_Controls.trainerBox->clear();
m_Controls.plannerBox->clear();
auto trainerPlanners = m_ParentFolder->getTrainerPlannersForTask<QStringList>(selectedTask, model);
if(trainerPlanners.isEmpty())
{
this->ShowErrorMessage("No plans.pkl found for "+model.toStdString()+". Check your directory or download the task again.");
this->SetComboBoxToNone(m_Controls.foldBox);
return;
}
QStringList trainers, planners;
std::tie(trainers, planners) = ExtractTrainerPlannerFromString(trainerPlanners);
std::for_each(
trainers.begin(), trainers.end(), [this](QString trainer) { m_Controls.trainerBox->addItem(trainer); });
std::for_each(
planners.begin(), planners.end(), [this](QString planner) { m_Controls.plannerBox->addItem(planner); });
}
}
else if (!m_EnsembleParams.empty())
{
m_Controls.previewButton->setEnabled(false);
for (auto &layout : m_EnsembleParams)
{
if (box == layout->modelBox)
{
layout->trainerBox->clear();
layout->plannerBox->clear();
auto trainerPlanners = m_ParentFolder->getTrainerPlannersForTask<QStringList>(selectedTask, model);
if(trainerPlanners.isEmpty())
{
this->ShowErrorMessage("No plans.pkl found for "+model.toStdString()+". Check your directory or download the task again.");
this->SetComboBoxToNone(layout->foldBox);
return;
}
QStringList trainers, planners;
std::tie(trainers, planners) = ExtractTrainerPlannerFromString(trainerPlanners);
std::for_each(trainers.begin(),
trainers.end(),
[&layout](const QString &trainer) { layout->trainerBox->addItem(trainer); });
std::for_each(planners.begin(),
planners.end(),
[&layout](const QString &planner) { layout->plannerBox->addItem(planner); });
break;
}
}
}
}
void QmitknnUNetToolGUI::OnTaskChanged(const QString &task)
{
if (task.isEmpty())
{
return;
}
m_Controls.modelBox->clear();
auto models = m_ParentFolder->getModelsForTask<QStringList>(task);
models.removeDuplicates();
if (!models.contains(m_VALID_MODELS.last(), Qt::CaseInsensitive))
{
models << m_VALID_MODELS.last(); // add ensemble even if folder doesn't exist
}
std::for_each(models.begin(),
models.end(),
[this](QString model)
{
if (m_VALID_MODELS.contains(model, Qt::CaseInsensitive))
m_Controls.modelBox->addItem(model);
});
}
void QmitknnUNetToolGUI::OnTrainerChanged(const QString &plannerSelected)
{
if (plannerSelected.isEmpty())
{
return;
}
m_IsResultsFolderValid = false;
QString parentPath;
auto *box = qobject_cast<ctkComboBox *>(sender());
if (box == m_Controls.plannerBox)
{
m_Controls.foldBox->clear();
auto selectedTrainer = m_Controls.trainerBox->currentText();
auto selectedTask = m_Controls.taskBox->currentText();
auto selectedModel = m_Controls.modelBox->currentText();
auto folds = m_ParentFolder->getFoldsForTrainerPlanner<QStringList>(
selectedTrainer, plannerSelected, selectedTask, selectedModel);
if(folds.isEmpty())
{
this->ShowErrorMessage("No valid folds found. Check your directory or download the task again.");
this->SetComboBoxToNone(m_Controls.foldBox);
return;
}
std::for_each(folds.begin(),
folds.end(),
[this](QString fold)
{
if (fold.startsWith("fold_", Qt::CaseInsensitive)) // imposed by nnUNet
m_Controls.foldBox->addItem(fold);
});
if (m_Controls.foldBox->count() != 0)
{
m_IsResultsFolderValid = true;
this->CheckAllInCheckableComboBox(m_Controls.foldBox);
auto tempPath = QStringList() << m_ParentFolder->getResultsFolder() << "nnUNet" << selectedModel << selectedTask
<< QString("%1__%2").arg(selectedTrainer, plannerSelected);
parentPath = QDir::cleanPath(tempPath.join(QDir::separator()));
}
}
else if (!m_EnsembleParams.empty())
{
for (auto &layout : m_EnsembleParams)
{
if (box == layout->plannerBox)
{
layout->foldBox->clear();
auto selectedTrainer = layout->trainerBox->currentText();
auto selectedTask = m_Controls.taskBox->currentText();
auto selectedModel = layout->modelBox->currentText();
auto folds = m_ParentFolder->getFoldsForTrainerPlanner<QStringList>(
selectedTrainer, plannerSelected, selectedTask, selectedModel);
if(folds.isEmpty())
{
this->ShowErrorMessage("No valid folds found. Check your directory.");
this->SetComboBoxToNone(layout->foldBox);
return;
}
std::for_each(folds.begin(),
folds.end(),
[&layout](const QString &fold)
{
if (fold.startsWith("fold_", Qt::CaseInsensitive)) // imposed by nnUNet
layout->foldBox->addItem(fold);
});
if (layout->foldBox->count() != 0)
{
this->CheckAllInCheckableComboBox(layout->foldBox);
m_IsResultsFolderValid = true;
auto tempPath = QStringList() << m_ParentFolder->getResultsFolder() << "nnUNet" << selectedModel
<< selectedTask << QString("%1__%2").arg(selectedTrainer, plannerSelected);
parentPath = QDir::cleanPath(tempPath.join(QDir::separator()));
}
break;
}
}
}
if (m_IsResultsFolderValid)
{
m_Controls.previewButton->setEnabled(true);
const QString mitkJsonFile = parentPath + QDir::separator() + m_MITK_EXPORT_JSON_FILENAME;
this->DumpJSONfromPickle(parentPath);
if (QFile::exists(mitkJsonFile))
{
this->DisplayMultiModalInfoFromJSON(mitkJsonFile);
}
}
}
void QmitknnUNetToolGUI::OnPythonPathChanged(const QString &pyEnv)
{
if (pyEnv == QString("Select"))
{
QString path =
QFileDialog::getExistingDirectory(m_Controls.pythonEnvComboBox->parentWidget(), "Python Path", "dir");
if (!path.isEmpty())
{
this->OnPythonPathChanged(path); // recall same function for new path validation
m_Controls.pythonEnvComboBox->insertItem(0, path);
m_Controls.pythonEnvComboBox->setCurrentIndex(0);
}
}
else if (!this->IsNNUNetInstalled(pyEnv))
{
std::string warning =
"WARNING: nnUNet is not detected on the Python environment you selected. Please select another "
"environment or create one. For more info refer https://github.com/MIC-DKFZ/nnUNet";
this->ShowErrorMessage(warning);
this->DisableEverything();
m_Controls.availableBox->clear();
}
else
{
m_Controls.modeldirectoryBox->setEnabled(true);
m_Controls.refreshdirectoryBox->setEnabled(true);
m_Controls.multiModalBox->setEnabled(true);
QString setVal = this->FetchResultsFolderFromEnv();
if (!setVal.isEmpty())
{
m_Controls.modeldirectoryBox->setDirectory(setVal);
}
this->OnRefreshPresssed();
m_PythonPath = pyEnv.mid(pyEnv.indexOf(" ") + 1);
#ifdef _WIN32
if (!(m_PythonPath.endsWith("Scripts", Qt::CaseInsensitive) || m_PythonPath.endsWith("Scripts/", Qt::CaseInsensitive)))
{
m_PythonPath += QDir::separator() + QString("Scripts");
}
#else
if (!(m_PythonPath.endsWith("bin", Qt::CaseInsensitive) || m_PythonPath.endsWith("bin/", Qt::CaseInsensitive)))
{
m_PythonPath += QDir::separator() + QString("bin");
}
#endif
// Export available model info as json and fill them for Download
QString tempPath = QString::fromStdString(mitk::IOUtil::GetTempPath());
this->ExportAvailableModelsAsJSON(tempPath);
const QString jsonPath = tempPath + QDir::separator() + m_AVAILABLE_MODELS_JSON_FILENAME;
if (QFile::exists(jsonPath))
{
this->FillAvailableModelsInfoFromJSON(jsonPath);
}
}
}
void QmitknnUNetToolGUI::OnCheckBoxChanged(int state)
{
bool visibility = false;
if (state == Qt::Checked)
{
visibility = true;
}
ctkCheckBox *box = qobject_cast<ctkCheckBox *>(sender());
if (box != nullptr)
{
if (box->objectName() == QString("multiModalBox"))
{
m_Controls.requiredModalitiesLabel->setVisible(visibility);
m_Controls.multiModalValueLabel->setVisible(visibility);
if (!visibility)
{
this->OnModalitiesNumberChanged(0);
m_Controls.multiModalValueLabel->setText("0");
this->ClearAllModalLabels();
}
}
}
}
void QmitknnUNetToolGUI::OnModalitiesNumberChanged(int num)
{
while (num > static_cast<int>(m_Modalities.size()))
{
QmitkSingleNodeSelectionWidget *multiModalBox = new QmitkSingleNodeSelectionWidget(this);
mitk::nnUNetTool::Pointer tool = this->GetConnectedToolAs<mitk::nnUNetTool>();
multiModalBox->SetDataStorage(tool->GetDataStorage());
multiModalBox->SetInvalidInfo("Select corresponding modalities");
multiModalBox->SetNodePredicate(m_MultiModalPredicate);
multiModalBox->setObjectName(QString("multiModal_" + QString::number(m_Modalities.size() + 1)));
m_Controls.advancedSettingsLayout->addWidget(multiModalBox, m_UI_ROWS + m_Modalities.size() + 1, 1, 1, 3);
m_Modalities.push_back(multiModalBox);
}
while (num < static_cast<int>(m_Modalities.size()) && !m_Modalities.empty())
{
QmitkSingleNodeSelectionWidget *child = m_Modalities.back();
delete child; // delete the layout item
m_Modalities.pop_back();
}
m_Controls.advancedSettingsLayout->update();
}
void QmitknnUNetToolGUI::AutoParsePythonPaths()
{
QString homeDir = QDir::homePath();
std::vector<QString> searchDirs;
#ifdef _WIN32
searchDirs.push_back(QString("C:") + QDir::separator() + QString("ProgramData") + QDir::separator() +
QString("anaconda3"));
#else
// Add search locations for possible standard python paths here
searchDirs.push_back(homeDir + QDir::separator() + "environments");
searchDirs.push_back(homeDir + QDir::separator() + "anaconda3");
searchDirs.push_back(homeDir + QDir::separator() + "miniconda3");
searchDirs.push_back(homeDir + QDir::separator() + "opt" + QDir::separator() + "miniconda3");
searchDirs.push_back(homeDir + QDir::separator() + "opt" + QDir::separator() + "anaconda3");
#endif
for (QString searchDir : searchDirs)
{
if (searchDir.endsWith("anaconda3", Qt::CaseInsensitive))
{
if (QDir(searchDir).exists())
{
m_Controls.pythonEnvComboBox->insertItem(0, "(base): " + searchDir);
searchDir.append((QDir::separator() + QString("envs")));
}
}
for (QDirIterator subIt(searchDir, QDir::AllDirs, QDirIterator::NoIteratorFlags); subIt.hasNext();)
{
subIt.next();
QString envName = subIt.fileName();
if (!envName.startsWith('.')) // Filter out irrelevent hidden folders, if any.
{
m_Controls.pythonEnvComboBox->insertItem(0, "(" + envName + "): " + subIt.filePath());
}
}
}
m_Controls.pythonEnvComboBox->setCurrentIndex(-1);
}
void QmitknnUNetToolGUI::SegmentationProcessFailed()
{
this->WriteErrorMessage(
"<b>STATUS: </b><i>Error in the segmentation process. <br>No resulting segmentation can be loaded.</i>");
this->setCursor(Qt::ArrowCursor);
std::stringstream stream;
stream << "Error in the segmentation process. No resulting segmentation can be loaded.";
this->ShowErrorMessage(stream.str());
}
void QmitknnUNetToolGUI::SegmentationResultHandler(mitk::nnUNetTool *tool, bool forceRender)
{
if (forceRender)
{
tool->RenderOutputBuffer();
}
m_FirstPreviewComputation = false;
this->SetLabelSetPreview(tool->GetPreviewSegmentation());
this->WriteStatusMessage("<b>STATUS: </b><i>Segmentation task finished successfully.</i>");
this->ActualizePreviewLabelVisibility();
}
void QmitknnUNetToolGUI::ShowEnsembleLayout(bool visible)
{
if (m_EnsembleParams.empty())
{
ctkCollapsibleGroupBox *groupBoxModel1 = new ctkCollapsibleGroupBox(this);
auto lay1 = std::make_unique<QmitknnUNetTaskParamsUITemplate>(groupBoxModel1);
groupBoxModel1->setObjectName(QString::fromUtf8("model_1_Box"));
groupBoxModel1->setTitle(QString::fromUtf8("Model 1"));
groupBoxModel1->setMinimumSize(QSize(0, 0));
groupBoxModel1->setCollapsedHeight(5);
groupBoxModel1->setCollapsed(false);
groupBoxModel1->setFlat(true);
groupBoxModel1->setAlignment(Qt::AlignRight);
m_Controls.advancedSettingsLayout->addWidget(groupBoxModel1, 5, 0, 1, 2);
connect(lay1->modelBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnModelChanged(const QString &)));
connect(
lay1->plannerBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnTrainerChanged(const QString &)));
m_EnsembleParams.push_back(std::move(lay1));
ctkCollapsibleGroupBox *groupBoxModel2 = new ctkCollapsibleGroupBox(this);
auto lay2 = std::make_unique<QmitknnUNetTaskParamsUITemplate>(groupBoxModel2);
groupBoxModel2->setObjectName(QString::fromUtf8("model_2_Box"));
groupBoxModel2->setTitle(QString::fromUtf8("Model 2"));
groupBoxModel2->setMinimumSize(QSize(0, 0));
groupBoxModel2->setCollapsedHeight(5);
groupBoxModel2->setCollapsed(false);
groupBoxModel2->setFlat(true);
groupBoxModel2->setAlignment(Qt::AlignLeft);
m_Controls.advancedSettingsLayout->addWidget(groupBoxModel2, 5, 2, 1, 2);
connect(lay2->modelBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnModelChanged(const QString &)));
connect(
lay2->plannerBox, SIGNAL(currentTextChanged(const QString &)), this, SLOT(OnTrainerChanged(const QString &)));
m_EnsembleParams.push_back(std::move(lay2));
}
for (auto &layout : m_EnsembleParams)
{
layout->setVisible(visible);
}
}
void QmitknnUNetToolGUI::OnDownloadModel()
{
auto selectedTask = m_Controls.availableBox->currentText();
if(!selectedTask.isEmpty())
{
auto spExec = mitk::ProcessExecutor::New();
mitk::ProcessExecutor::ArgumentListType args;
args.push_back(selectedTask.toStdString());
this->WriteStatusMessage(
"Downloading the requested task in to the selected Results Folder. This might take some time "
"depending on your internet connection...");
m_Processes["DOWNLOAD"] = spExec;
if (!m_nnUNetThread->isRunning())
{
MITK_DEBUG << "Starting thread...";
m_nnUNetThread->start();
}
QString resultsFolder = m_ParentFolder->getResultsFolder();
emit Operate(resultsFolder, m_PythonPath, spExec, args);
m_Controls.stopDownloadButton->setVisible(true);
m_Controls.startDownloadButton->setVisible(false);
}
}
void QmitknnUNetToolGUI::OnDownloadWorkerExit(const bool isSuccess, const QString message)
{
if (isSuccess)
{
this->WriteStatusMessage(message + QString(" Click Refresh Results Folder to use the new Task."));
}
else
{
MITK_ERROR << "Download FAILED! " << message.toStdString();
this->WriteStatusMessage(QString("Download failed. Check your internet connection. " + message));
}
m_Controls.stopDownloadButton->setVisible(false);
m_Controls.startDownloadButton->setVisible(true);
}
void QmitknnUNetToolGUI::OnStopDownload()
{
mitk::ProcessExecutor::Pointer spExec = m_Processes["DOWNLOAD"];
spExec->KillProcess();
this->WriteStatusMessage("Download Killed by the user.");
m_Controls.stopDownloadButton->setVisible(false);
m_Controls.startDownloadButton->setVisible(true);
}
void QmitknnUNetToolGUI::OnClearCachePressed()
{
m_Cache.clear();
this->UpdateCacheCountOnUI();
}
diff --git a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUIControls.ui b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUIControls.ui
index cb46310c3f..6d1f17d26d 100644
--- a/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUIControls.ui
+++ b/Modules/SegmentationUI/Qmitk/QmitknnUNetToolGUIControls.ui
@@ -1,476 +1,476 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmitknnUNetToolGUIControls</class>
<widget class="QWidget" name="QmitknnUNetToolGUIControls">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>877</width>
<height>711</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100000</width>
<height>100000</height>
</size>
</property>
<property name="windowTitle">
<string>QmitknnUNetToolWidget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QGridLayout" name="advancedSettingsLayout">
<item row="5" column="3">
<widget class="ctkComboBox" name="plannerBox"/>
</item>
<item row="5" column="1">
<widget class="ctkComboBox" name="trainerBox"/>
</item>
<item row="3" column="1" colspan="3">
<widget class="QPushButton" name="refreshdirectoryBox">
<property name="text">
<string>Refresh Results Folder</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="pythonEnvLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Python Path:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="plannerLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Plan:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="trainerLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Trainer:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="pretraineddirLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>nnUNet Results Folder:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="ctkComboBox" name="taskBox"/>
</item>
<item row="7" column="1">
<widget class="ctkCheckBox" name="multiModalBox"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="multiModalLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Multi-Modal:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QLabel" name="welcomeNote">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Welcome to nnUNet in MITK. [Experimental]&lt;/p&gt;&lt;p&gt;Please note that this is only an interface to nnUNet. MITK does not ship with nnUNet. Make sure to have a working Python environment with nnUNet set up beforehand. Choose that environment in the Python Path before inferencing. &lt;/p&gt;&lt;p&gt;Refer to &lt;a href=&quot;https://github.com/MIC-DKFZ/nnUNet&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/MIC-DKFZ/nnUNet&lt;/span&gt;&lt;/a&gt; to learn everything about the nnUNet.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Welcome to nnU-Net in MITK. [Experimental]&lt;/p&gt;&lt;p&gt;Please note that this is only an interface to nnU-Net v1. MITK does not ship with nnU-Net v1. Make sure to have a working Python environment with nnU-Net v1 set up beforehand. Choose that environment in the Python Path before inferencing. &lt;/p&gt;&lt;p&gt;Refer to &lt;a href=&quot;https://github.com/MIC-DKFZ/nnUNet&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/MIC-DKFZ/nnUNet&lt;/span&gt;&lt;/a&gt; to learn everything about the nnU-Net.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1" colspan="3">
<widget class="ctkDirectoryButton" name="modeldirectoryBox" native="true"/>
</item>
<item row="4" column="2">
<widget class="QLabel" name="modelLabel">
<property name="text">
<string>Configuration:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="ctkComboBox" name="modelBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="taskLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Task:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="ctkCheckableComboBox" name="foldBox"/>
</item>
<item row="7" column="2">
<widget class="QLabel" name="requiredModalitiesLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Required Modalities:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="foldLabel">
<property name="text">
<string>Fold:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="ctkComboBox" name="pythonEnvComboBox"/>
</item>
<item row="7" column="3">
<widget class="QLabel" name="multiModalValueLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="ctkCollapsibleGroupBox" name="inputGroupBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Advanced</string>
</property>
<property name="alignment">
<set>Qt::AlignRight</set>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="collapsedHeight" stdset="0">
<number>5</number>
</property>
<property name="collapsed" stdset="0">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QGridLayout" name="_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="mixedPrecisionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mixed Precision:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QCheckBox" name="mixedPrecisionBox">
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="gpuSpinLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>GPU Id:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="ctkComboBox" name="gpuComboBox"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="mirrorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Enable Mirroring:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="ctkCheckBox" name="mirrorBox">
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="postProcessingLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use Postprocessing JSON:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="ctkCheckBox" name="postProcessingCheckBox">
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="enableCachingLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Enable Caching:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="ctkCheckBox" name="enableCachingCheckBox">
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="clearCacheButton">
<property name="text">
<string>Clear Cache</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QLabel" name="cacheCountLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cached Items: 0</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="AvailableModelsLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Available Models:</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="ctkComboBox" name="availableBox" native="true"/>
</item>
<item row="6" column="3">
<widget class="QPushButton" name="startDownloadButton">
<property name="text">
<string>Download</string>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QPushButton" name="stopDownloadButton">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="previewButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>100000</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Preview</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ctkDirectoryButton</class>
<extends>QWidget</extends>
<header location="global">ctkDirectoryButton.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ctkComboBox</class>
<extends>QComboBox</extends>
<header location="global">ctkComboBox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ctkCheckableComboBox</class>
<extends>QComboBox</extends>
<header location="global">ctkCheckableComboBox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ctkCheckBox</class>
<extends>QCheckBox</extends>
<header location="global">ctkCheckBox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ctkCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header location="global">ctkCollapsibleGroupBox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp
index c1e2aa0412..58d982de3f 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp
@@ -1,158 +1,157 @@
/*============================================================================
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 "QmitkBooleanOperationsWidget.h"
#include <ui_QmitkBooleanOperationsWidgetControls.h>
#include <mitkDataStorage.h>
#include <mitkException.h>
-#include <mitkSliceNavigationController.h>
+#include <mitkRenderingManager.h>
+#include <mitkTimeNavigationController.h>
#include <QMessageBox>
#include <cassert>
static const char* const HelpText = "Select two different segmentations above";
namespace
{
static std::string GetPrefix(mitk::BooleanOperation::Type type)
{
switch (type)
{
case mitk::BooleanOperation::Difference:
return "DifferenceFrom_";
case mitk::BooleanOperation::Intersection:
return "IntersectionWith_";
case mitk::BooleanOperation::Union:
return "UnionWith_";
default:
assert(false && "Unknown boolean operation type");
return "UNKNOWN_BOOLEAN_OPERATION_WITH_";
}
}
static void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, const std::string& name, mitk::DataNode::Pointer parent = nullptr)
{
if (dataStorage.IsNull())
{
std::string exception = "Cannot add result to the data storage. Data storage invalid.";
MITK_ERROR << "Boolean operation failed: " << exception;
QMessageBox::information(nullptr, "Boolean operation failed", QString::fromStdString(exception));
}
auto dataNode = mitk::DataNode::New();
dataNode->SetName(name);
dataNode->SetData(segmentation);
dataStorage->Add(dataNode, parent);
}
}
-QmitkBooleanOperationsWidget::QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent)
- : QmitkSegmentationUtilityWidget(timeNavigationController, parent)
+QmitkBooleanOperationsWidget::QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent)
+ : QWidget(parent)
{
m_Controls = new Ui::QmitkBooleanOperationsWidgetControls;
m_Controls->setupUi(this);
m_Controls->dataSelectionWidget->SetDataStorage(dataStorage);
m_Controls->dataSelectionWidget->AddDataSelection("<img width=16 height=16 src=\":/Qmitk/BooleanLabelA_32x32.png\"/>", "Select 1st segmentation", "Select 1st segmentation", "", QmitkDataSelectionWidget::SegmentationPredicate);
m_Controls->dataSelectionWidget->AddDataSelection("<img width=16 height=16 src=\":/Qmitk/BooleanLabelB_32x32.png\"/>", "Select 2nd segmentation", "Select 2nd segmentation", "", QmitkDataSelectionWidget::SegmentationPredicate);
m_Controls->dataSelectionWidget->SetHelpText(HelpText);
connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
connect(m_Controls->differenceButton, SIGNAL(clicked()), this, SLOT(OnDifferenceButtonClicked()));
connect(m_Controls->intersectionButton, SIGNAL(clicked()), this, SLOT(OnIntersectionButtonClicked()));
connect(m_Controls->unionButton, SIGNAL(clicked()), this, SLOT(OnUnionButtonClicked()));
}
QmitkBooleanOperationsWidget::~QmitkBooleanOperationsWidget()
{
}
void QmitkBooleanOperationsWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*)
{
auto dataSelectionWidget = m_Controls->dataSelectionWidget;
auto nodeA = dataSelectionWidget->GetSelection(0);
auto nodeB = dataSelectionWidget->GetSelection(1);
if (nodeA.IsNotNull() && nodeB.IsNotNull() && nodeA != nodeB)
{
dataSelectionWidget->SetHelpText("");
this->EnableButtons();
}
else
{
dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
}
}
void QmitkBooleanOperationsWidget::EnableButtons(bool enable)
{
m_Controls->differenceButton->setEnabled(enable);
m_Controls->intersectionButton->setEnabled(enable);
m_Controls->unionButton->setEnabled(enable);
}
void QmitkBooleanOperationsWidget::OnDifferenceButtonClicked()
{
this->DoBooleanOperation(mitk::BooleanOperation::Difference);
}
void QmitkBooleanOperationsWidget::OnIntersectionButtonClicked()
{
this->DoBooleanOperation(mitk::BooleanOperation::Intersection);
}
void QmitkBooleanOperationsWidget::OnUnionButtonClicked()
{
this->DoBooleanOperation(mitk::BooleanOperation::Union);
}
void QmitkBooleanOperationsWidget::DoBooleanOperation(mitk::BooleanOperation::Type type)
{
- auto timeNavigationController = this->GetTimeNavigationController();
+ const auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
assert(timeNavigationController != nullptr);
mitk::Image::Pointer segmentationA = dynamic_cast<mitk::Image*>(m_Controls->dataSelectionWidget->GetSelection(0)->GetData());
mitk::Image::Pointer segmentationB = dynamic_cast<mitk::Image*>(m_Controls->dataSelectionWidget->GetSelection(1)->GetData());
mitk::Image::Pointer result;
try
{
mitk::BooleanOperation booleanOperation(type, segmentationA, segmentationB, timeNavigationController->GetSelectedTimePoint());
result = booleanOperation.GetResult();
assert(result.IsNotNull());
auto dataSelectionWidget = m_Controls->dataSelectionWidget;
AddToDataStorage(
dataSelectionWidget->GetDataStorage(),
result,
GetPrefix(type) + dataSelectionWidget->GetSelection(1)->GetName(),
dataSelectionWidget->GetSelection(0));
}
catch (const mitk::Exception& exception)
{
MITK_ERROR << "Boolean operation failed: " << exception.GetDescription();
QMessageBox::information(nullptr, "Boolean operation failed", exception.GetDescription());
}
}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h
index 29b0e89e87..5d09e3eec6 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h
@@ -1,55 +1,54 @@
/*============================================================================
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 QmitkBooleanOperationsWidget_h
#define QmitkBooleanOperationsWidget_h
#include <MitkSegmentationUIExports.h>
#include <mitkBooleanOperation.h>
-#include <QmitkSegmentationUtilityWidget.h>
+
+#include <QWidget>
namespace Ui
{
class QmitkBooleanOperationsWidgetControls;
}
namespace mitk
{
class DataNode;
class DataStorage;
}
-class MITKSEGMENTATIONUI_EXPORT QmitkBooleanOperationsWidget : public QmitkSegmentationUtilityWidget
+class MITKSEGMENTATIONUI_EXPORT QmitkBooleanOperationsWidget : public QWidget
{
Q_OBJECT
public:
- explicit QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent = nullptr);
+ explicit QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
~QmitkBooleanOperationsWidget() override;
private slots:
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
void OnDifferenceButtonClicked();
void OnIntersectionButtonClicked();
void OnUnionButtonClicked();
private:
void EnableButtons(bool enable = true);
void DoBooleanOperation(mitk::BooleanOperation::Type type);
Ui::QmitkBooleanOperationsWidgetControls* m_Controls;
};
#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
index 883633b384..604206f78e 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
@@ -1,259 +1,258 @@
/*============================================================================
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 "QmitkContourModelToImageWidget.h"
#include <ui_QmitkContourModelToImageWidgetControls.h>
#include <mitkDataStorage.h>
#include <mitkImage.h>
#include <mitkContourModelSet.h>
#include <mitkContourModelSetToImageFilter.h>
#include <mitkLabelSetImage.h>
-#include <mitkSliceNavigationController.h>
+#include <mitkRenderingManager.h>
+#include <mitkTimeNavigationController.h>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <qmessagebox.h>
static const char* const HelpText = "Select a image and a contour(set)";
class QmitkContourModelToImageWidgetPrivate
{
public:
QmitkContourModelToImageWidgetPrivate();
~QmitkContourModelToImageWidgetPrivate();
/** @brief Check if selections is valid. */
void SelectionControl( unsigned int index, const mitk::DataNode* selection);
/** @brief Enable buttons if data selction is valid. */
void EnableButtons(bool enable = true);
/** @brief Does the actual contour filling */
mitk::LabelSetImage::Pointer FillContourModelSetIntoImage(mitk::Image *image, mitk::ContourModelSet *contourSet, mitk::TimePointType timePoint);
Ui::QmitkContourModelToImageWidgetControls m_Controls;
QFutureWatcher<mitk::LabelSetImage::Pointer> m_Watcher;
};
QmitkContourModelToImageWidgetPrivate::QmitkContourModelToImageWidgetPrivate()
{
}
QmitkContourModelToImageWidgetPrivate::~QmitkContourModelToImageWidgetPrivate()
{
}
void QmitkContourModelToImageWidgetPrivate::EnableButtons(bool enable)
{
m_Controls.btnProcess->setEnabled(enable);
}
void QmitkContourModelToImageWidgetPrivate::SelectionControl(unsigned int index, const mitk::DataNode* /*selection*/)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index);
dataSelectionWidget->SetHelpText("");
this->EnableButtons();
}
mitk::LabelSetImage::Pointer QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage(mitk::Image* image, mitk::ContourModelSet* contourSet, mitk::TimePointType timePoint)
{
// Use mitk::ContourModelSetToImageFilter to fill the ContourModelSet into the image
mitk::ContourModelSetToImageFilter::Pointer contourFiller = mitk::ContourModelSetToImageFilter::New();
auto timeStep = image->GetTimeGeometry()->TimePointToTimeStep(timePoint);
contourFiller->SetTimeStep(timeStep);
contourFiller->SetImage(image);
contourFiller->SetInput(contourSet);
contourFiller->MakeOutputBinaryOn();
try
{
contourFiller->Update();
}
catch (const std::exception & e)
{
MITK_ERROR << "Error while converting contour model. "<< e.what();
}
catch (...)
{
MITK_ERROR << "Unknown error while converting contour model.";
}
if (nullptr == contourFiller->GetOutput())
{
MITK_ERROR<<"Could not write the selected contours into the image!";
}
auto result = mitk::LabelSetImage::New();
result->InitializeByLabeledImage(contourFiller->GetOutput());
return result;
}
void QmitkContourModelToImageWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection)
{
Q_D(QmitkContourModelToImageWidget);
QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1);
if (node0.IsNull() || node1.IsNull() )
{
d->EnableButtons(false);
dataSelectionWidget->SetHelpText(HelpText);
}
else
{
d->SelectionControl(index, selection);
}
}
void QmitkContourModelToImageWidget::OnProcessingFinished()
{
// Called when processing finished
// Adding the result to the data storage
Q_D(QmitkContourModelToImageWidget);
// Adding the result to the data storage
auto result = d->m_Watcher.result();
if (result.IsNotNull())
{
QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1);
mitk::DataNode::Pointer filled = mitk::DataNode::New();
std::stringstream stream;
stream << imageNode->GetName();
stream << "_";
stream << contourNode->GetName();
filled->SetName(stream.str());
filled->SetData(result);
auto dataStorage = dataSelectionWidget->GetDataStorage();
if (dataStorage.IsNull())
{
std::string exception = "Cannot add result to the data storage. Data storage invalid.";
MITK_ERROR << "Error filling contours into an image: " << exception;
QMessageBox::information(nullptr, "Error filling contours into an image", QString::fromStdString(exception));
}
dataStorage->Add(filled, imageNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else
{
MITK_ERROR<<"Error filling contours into an image!";
}
d->EnableButtons();
}
void QmitkContourModelToImageWidget::OnProcessPressed()
{
Q_D(QmitkContourModelToImageWidget);
QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1);
// Check if data nodes are valid
if(imageNode.IsNull() || contourNode.IsNull() )
{
MITK_ERROR << "Selection does not contain valid data";
QMessageBox::information( this, "Contour To Image",
"Selection does not contain valid data, please select a binary image and a contour(set)",
QMessageBox::Ok );
d->m_Controls.btnProcess->setEnabled(false);
return;
}
mitk::Image::Pointer image = static_cast<mitk::Image*>(imageNode->GetData());
// Check if the image is valid
if (image.IsNull())
{
MITK_ERROR<<"Error writing contours into image! Invalid image data selected!";
return;
}
- const auto timePoint = this->GetTimeNavigationController()->GetSelectedTimePoint();
+ const mitk::TimePointType timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint))
{
MITK_ERROR << "Error writing contours into image! Currently selected time point is not supported by selected image data.";
return;
}
// Check if the selected contours are valid
mitk::ContourModelSet::Pointer contourSet;
mitk::ContourModel::Pointer contour = dynamic_cast<mitk::ContourModel*>(contourNode->GetData());
if (contour.IsNotNull())
{
contourSet = mitk::ContourModelSet::New();
contourSet->AddContourModel(contour);
}
else
{
contourSet = static_cast<mitk::ContourModelSet*>(contourNode->GetData());
if (contourSet.IsNull())
{
MITK_ERROR<<"Error writing contours into binary image! Invalid contour data selected!";
return;
}
}
//Disable Buttons during calculation and initialize Progressbar
d->EnableButtons(false);
// Start the computation in a background thread
QFuture< mitk::LabelSetImage::Pointer > future = QtConcurrent::run(d, &QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage, image, contourSet, timePoint);
d->m_Watcher.setFuture(future);
}
-QmitkContourModelToImageWidget::QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent)
- : QmitkSegmentationUtilityWidget(timeNavigationController, parent),
- d_ptr(new QmitkContourModelToImageWidgetPrivate())
+QmitkContourModelToImageWidget::QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent)
+ : QWidget(parent)
+ , d_ptr(new QmitkContourModelToImageWidgetPrivate())
{
Q_D(QmitkContourModelToImageWidget);
// Set up UI
d->m_Controls.setupUi(this);
d->m_Controls.dataSelectionWidget->SetDataStorage(dataStorage);
d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImageAndSegmentationPredicate);
d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ContourModelPredicate);
d->m_Controls.dataSelectionWidget->SetHelpText(HelpText);
d->EnableButtons(false);
// Create connections
connect (d->m_Controls.btnProcess, SIGNAL(pressed()), this, SLOT(OnProcessPressed()));
connect(d->m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
connect(&d->m_Watcher, SIGNAL(finished()), this, SLOT(OnProcessingFinished()));
if( d->m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() &&
d->m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() )
{
OnSelectionChanged(0, d->m_Controls.dataSelectionWidget->GetSelection(0));
}
}
QmitkContourModelToImageWidget::~QmitkContourModelToImageWidget()
{
}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
index 562d254434..797def3584 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
@@ -1,76 +1,72 @@
/*============================================================================
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 QmitkContourModelToImageWidget_h
#define QmitkContourModelToImageWidget_h
#include <MitkSegmentationUIExports.h>
-#include <QmitkSegmentationUtilityWidget.h>
-
#include <QScopedPointer>
+#include <QWidget>
class QmitkContourModelToImageWidgetPrivate;
namespace mitk
{
class DataNode;
class DataStorage;
class Image;
class ContourModelSet;
class ContourModel;
class Geometry3D;
class PlaneGeometry;
}
/*!
\brief QmitkContourModelToImageWidget
Tool masks an image with a binary image or a surface. The Method requires
an image and a binary image mask or a surface. The input image and the binary
image mask must be of the same size. Masking with a surface creates first a
binary image of the surface and then use this for the masking of the input image.
*/
-class MITKSEGMENTATIONUI_EXPORT QmitkContourModelToImageWidget : public QmitkSegmentationUtilityWidget
+class MITKSEGMENTATIONUI_EXPORT QmitkContourModelToImageWidget : public QWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
- explicit QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent = nullptr);
-
+ explicit QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
/** @brief Defaul destructor. */
~QmitkContourModelToImageWidget() override;
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
/** @brief This slot is called if user activates the button to mask an image. */
void OnProcessPressed();
/** @brief This slot is called after processing is finished */
void OnProcessingFinished();
private:
QScopedPointer<QmitkContourModelToImageWidgetPrivate> d_ptr;
Q_DECLARE_PRIVATE(QmitkContourModelToImageWidget)
Q_DISABLE_COPY(QmitkContourModelToImageWidget)
};
#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp
index 0e542d4d04..884c5a79cd 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp
@@ -1,393 +1,389 @@
/*============================================================================
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 "QmitkImageMaskingWidget.h"
#include <ui_QmitkImageMaskingWidgetControls.h>
-#include <mitkDataStorage.h>
#include <mitkException.h>
#include <mitkExceptionMacro.h>
#include <mitkImage.h>
#include <mitkImageStatisticsHolder.h>
#include <mitkMaskImageFilter.h>
#include <mitkProgressBar.h>
-#include <mitkSliceNavigationController.h>
#include <mitkSurfaceToImageFilter.h>
#include <mitkImageAccessByItk.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateGeometry.h>
#include <mitkNodePredicateNot.h>
#include <QMessageBox>
#include <limits>
namespace
{
bool IsSurface(const mitk::DataNode* dataNode)
{
if (nullptr != dataNode)
{
if (nullptr != dynamic_cast<const mitk::Surface*>(dataNode->GetData()))
return true;
}
return false;
}
}
static const char* const HelpText = "Select an image and a segmentation or surface";
-QmitkImageMaskingWidget::QmitkImageMaskingWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent)
- : QmitkSegmentationUtilityWidget(timeNavigationController, parent)
+QmitkImageMaskingWidget::QmitkImageMaskingWidget(mitk::DataStorage* dataStorage, QWidget* parent)
+ : QWidget(parent)
{
m_Controls = new Ui::QmitkImageMaskingWidgetControls;
m_Controls->setupUi(this);
m_Controls->dataSelectionWidget->SetDataStorage(dataStorage);
m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImagePredicate);
m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SegmentationOrSurfacePredicate);
m_Controls->dataSelectionWidget->SetHelpText(HelpText);
// T28795: Disable 2-d reference images since they do not work yet (segmentations are at least 3-d images with a single slice)
m_Controls->dataSelectionWidget->SetPredicate(0, mitk::NodePredicateAnd::New(
mitk::NodePredicateNot::New(mitk::NodePredicateDimension::New(2)),
m_Controls->dataSelectionWidget->GetPredicate(0)));
this->EnableButtons(false);
connect(m_Controls->btnMaskImage, SIGNAL(clicked()), this, SLOT(OnMaskImagePressed()));
connect(m_Controls->rbnCustom, SIGNAL(toggled(bool)), this, SLOT(OnCustomValueButtonToggled(bool)));
connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
if( m_Controls->dataSelectionWidget->GetSelection(0).IsNotNull() &&
m_Controls->dataSelectionWidget->GetSelection(1).IsNotNull() )
{
this->OnSelectionChanged(0, m_Controls->dataSelectionWidget->GetSelection(0));
}
}
QmitkImageMaskingWidget::~QmitkImageMaskingWidget()
{
}
void QmitkImageMaskingWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode *selection)
{
auto *dataSelectionWidget = m_Controls->dataSelectionWidget;
auto node0 = dataSelectionWidget->GetSelection(0);
if (index == 0)
{
dataSelectionWidget->SetPredicate(1, QmitkDataSelectionWidget::SegmentationOrSurfacePredicate);
if (node0.IsNotNull())
{
dataSelectionWidget->SetPredicate(1, mitk::NodePredicateAnd::New(
mitk::NodePredicateGeometry::New(node0->GetData()->GetGeometry()),
dataSelectionWidget->GetPredicate(1)));
}
}
auto node1 = dataSelectionWidget->GetSelection(1);
if (node0.IsNull() || node1.IsNull())
{
dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
}
else
{
this->SelectionControl(index, selection);
}
}
void QmitkImageMaskingWidget::SelectionControl(unsigned int index, const mitk::DataNode* selection)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index);
//if Image-Masking is enabled, check if image-dimension of reference and binary image is identical
if( !IsSurface(dataSelectionWidget->GetSelection(1)) )
{
if( dataSelectionWidget->GetSelection(0) == dataSelectionWidget->GetSelection(1) )
{
dataSelectionWidget->SetHelpText("Select two different images above");
this->EnableButtons(false);
return;
}
else if( node.IsNotNull() && selection )
{
mitk::Image::Pointer referenceImage = dynamic_cast<mitk::Image*> ( dataSelectionWidget->GetSelection(0)->GetData() );
mitk::Image::Pointer maskImage = dynamic_cast<mitk::Image*> ( dataSelectionWidget->GetSelection(1)->GetData() );
if (maskImage.IsNull())
{
dataSelectionWidget->SetHelpText("Different image sizes cannot be masked");
this->EnableButtons(false);
return;
}
}
else
{
dataSelectionWidget->SetHelpText(HelpText);
return;
}
}
dataSelectionWidget->SetHelpText("");
this->EnableButtons();
}
void QmitkImageMaskingWidget::EnableButtons(bool enable)
{
m_Controls->grpBackgroundValue->setEnabled(enable);
m_Controls->btnMaskImage->setEnabled(enable);
}
template<typename TPixel, unsigned int VImageDimension>
void GetRange(const itk::Image<TPixel, VImageDimension>*, double& bottom, double& top)
{
bottom = std::numeric_limits<TPixel>::lowest();
top = std::numeric_limits<TPixel>::max();
}
void QmitkImageMaskingWidget::OnCustomValueButtonToggled(bool checked)
{
m_Controls->txtCustom->setEnabled(checked);
}
void QmitkImageMaskingWidget::OnMaskImagePressed()
{
//Disable Buttons during calculation and initialize Progressbar
this->EnableButtons(false);
mitk::ProgressBar::GetInstance()->AddStepsToDo(4);
mitk::ProgressBar::GetInstance()->Progress();
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
//create result image, get mask node and reference image
mitk::Image::Pointer resultImage(nullptr);
mitk::DataNode::Pointer maskingNode = dataSelectionWidget->GetSelection(1);
mitk::Image::Pointer referenceImage = static_cast<mitk::Image*>(dataSelectionWidget->GetSelection(0)->GetData());
if(referenceImage.IsNull() || maskingNode.IsNull() )
{
MITK_ERROR << "Selection does not contain an image";
QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain an image", QMessageBox::Ok );
m_Controls->btnMaskImage->setEnabled(true);
return;
}
//Do Image-Masking
if (!IsSurface(maskingNode))
{
mitk::ProgressBar::GetInstance()->Progress();
mitk::Image::Pointer maskImage = dynamic_cast<mitk::Image*> ( maskingNode->GetData() );
if(maskImage.IsNull() )
{
MITK_ERROR << "Selection does not contain a segmentation";
QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a segmentation", QMessageBox::Ok );
this->EnableButtons();
return;
}
resultImage = this->MaskImage(referenceImage, maskImage);
}
//Do Surface-Masking
else
{
mitk::ProgressBar::GetInstance()->Progress();
//1. convert surface to image
mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface*> ( maskingNode->GetData() );
//TODO Get 3D Surface of current time step
if(surface.IsNull())
{
MITK_ERROR << "Selection does not contain a surface";
QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a surface", QMessageBox::Ok );
this->EnableButtons();
return;
}
mitk::Image::Pointer maskImage = this->ConvertSurfaceToImage( referenceImage, surface );
//2. mask reference image with mask image
if(maskImage.IsNotNull() &&
referenceImage->GetLargestPossibleRegion().GetSize() == maskImage->GetLargestPossibleRegion().GetSize() )
{
resultImage = this->MaskImage( referenceImage, maskImage );
}
}
mitk::ProgressBar::GetInstance()->Progress();
if( resultImage.IsNull() )
{
MITK_ERROR << "Masking failed";
QMessageBox::information( this, "Image and Surface Masking", "Masking failed. For more information please see logging window.", QMessageBox::Ok );
this->EnableButtons();
mitk::ProgressBar::GetInstance()->Progress(4);
return;
}
//Add result to data storage
this->AddToDataStorage(
dataSelectionWidget->GetDataStorage(),
resultImage,
dataSelectionWidget->GetSelection(0)->GetName() + "_" + dataSelectionWidget->GetSelection(1)->GetName(),
dataSelectionWidget->GetSelection(0));
this->EnableButtons();
mitk::ProgressBar::GetInstance()->Progress();
}
mitk::Image::Pointer QmitkImageMaskingWidget::MaskImage(mitk::Image::Pointer referenceImage, mitk::Image::Pointer maskImage )
{
mitk::ScalarType backgroundValue = 0.0;
if (m_Controls->rbnMinimum->isChecked())
{
backgroundValue = referenceImage->GetStatistics()->GetScalarValueMin();
}
else if (m_Controls->rbnCustom->isChecked())
{
auto warningTitle = QStringLiteral("Invalid custom pixel value");
bool ok = false;
auto originalBackgroundValue = m_Controls->txtCustom->text().toDouble(&ok);
if (!ok)
{
// Input is not even a number
QMessageBox::warning(nullptr, warningTitle, "Please enter a valid number as custom pixel value.");
return nullptr;
}
else
{
// Clamp to the numerical limits of the pixel/component type
double bottom, top;
if (referenceImage->GetDimension() == 4)
{
AccessFixedDimensionByItk_n(referenceImage, GetRange, 4, (bottom, top));
}
else
{
AccessByItk_n(referenceImage, GetRange, (bottom, top));
}
backgroundValue = std::max(bottom, std::min(originalBackgroundValue, top));
// Get rid of decimals for integral numbers
auto type = referenceImage->GetPixelType().GetComponentType();
if (type != itk::IOComponentEnum::FLOAT && type != itk::IOComponentEnum::DOUBLE)
backgroundValue = std::round(backgroundValue);
}
// Ask the user for permission before correcting their input
if (std::abs(originalBackgroundValue - backgroundValue) > 1e-4)
{
auto warningText = QString(
"<p>The custom pixel value <b>%1</b> lies not within the range of valid pixel values for the selected image.</p>"
"<p>Apply the closest valid pixel value <b>%2</b> instead?</p>").arg(originalBackgroundValue).arg(backgroundValue);
auto ret = QMessageBox::warning(
nullptr,
warningTitle,
warningText,
QMessageBox::StandardButton::Apply | QMessageBox::StandardButton::Cancel,
QMessageBox::StandardButton::Apply);
if (QMessageBox::StandardButton::Apply != ret)
return nullptr;
m_Controls->txtCustom->setText(QString("%1").arg(backgroundValue));
}
}
auto maskFilter = mitk::MaskImageFilter::New();
maskFilter->SetInput(referenceImage);
maskFilter->SetMask(maskImage);
maskFilter->OverrideOutsideValueOn();
maskFilter->SetOutsideValue(backgroundValue);
try
{
maskFilter->Update();
}
catch(const itk::ExceptionObject& e)
{
MITK_ERROR << e.GetDescription();
return nullptr;
}
return maskFilter->GetOutput();
}
mitk::Image::Pointer QmitkImageMaskingWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface )
{
mitk::ProgressBar::GetInstance()->AddStepsToDo(2);
mitk::ProgressBar::GetInstance()->Progress();
mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
surfaceToImageFilter->MakeOutputBinaryOn();
surfaceToImageFilter->SetInput(surface);
surfaceToImageFilter->SetImage(image);
try
{
surfaceToImageFilter->Update();
}
catch(itk::ExceptionObject& excpt)
{
MITK_ERROR << excpt.GetDescription();
return nullptr;
}
mitk::ProgressBar::GetInstance()->Progress();
mitk::Image::Pointer resultImage = mitk::Image::New();
resultImage = surfaceToImageFilter->GetOutput();
return resultImage;
}
void QmitkImageMaskingWidget::AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, const std::string& name, mitk::DataNode::Pointer parent )
{
if (dataStorage.IsNull())
{
std::string exception = "Cannot add result to the data storage. Data storage invalid.";
MITK_ERROR << "Masking failed: " << exception;
QMessageBox::information(nullptr, "Masking failed", QString::fromStdString(exception));
}
auto dataNode = mitk::DataNode::New();
dataNode->SetName(name);
dataNode->SetData(segmentation);
if (parent.IsNotNull())
{
mitk::LevelWindow levelWindow;
parent->GetLevelWindow(levelWindow);
dataNode->SetLevelWindow(levelWindow);
}
dataStorage->Add(dataNode, parent);
}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h
index b8be1847bf..5769a75990 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h
@@ -1,87 +1,85 @@
/*============================================================================
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 QmitkImageMaskingWidget_h
#define QmitkImageMaskingWidget_h
#include <MitkSegmentationUIExports.h>
#include <mitkDataStorage.h>
#include <mitkSurface.h>
-#include <QmitkSegmentationUtilityWidget.h>
+
+#include <QWidget>
namespace Ui
{
class QmitkImageMaskingWidgetControls;
}
namespace mitk
{
- class DataStorage;
class Image;
}
/*!
\brief QmitkImageMaskingWidget
Tool masks an image with a binary image or a surface. The Method requires
an image and a binary image mask or a surface. The input image and the binary
image mask must be of the same size. Masking with a surface creates first a
binary image of the surface and then use this for the masking of the input image.
*/
-class MITKSEGMENTATIONUI_EXPORT QmitkImageMaskingWidget : public QmitkSegmentationUtilityWidget
+class MITKSEGMENTATIONUI_EXPORT QmitkImageMaskingWidget : public QWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
- explicit QmitkImageMaskingWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent = nullptr);
+ explicit QmitkImageMaskingWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
/** @brief Defaul destructor. */
~QmitkImageMaskingWidget() override;
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
/** @brief This slot is called if user activates the button to mask an image. */
void OnMaskImagePressed();
/** @brief This slot is called if the user toggles the "Custom" radio button. */
void OnCustomValueButtonToggled(bool checked);
private:
/** @brief Check if selections is valid. */
void SelectionControl( unsigned int index, const mitk::DataNode* selection);
/** @brief Enable buttons if data selction is valid. */
void EnableButtons(bool enable = true);
/** @brief Mask an image with a given binary mask. Note that the input image and the mask image must be of the same size. */
itk::SmartPointer<mitk::Image> MaskImage(itk::SmartPointer<mitk::Image> referenceImage, itk::SmartPointer<mitk::Image> maskImage );
/** @brief Convert a surface into an binary image. */
itk::SmartPointer<mitk::Image> ConvertSurfaceToImage( itk::SmartPointer<mitk::Image> image, mitk::Surface::Pointer surface );
/** @brief Adds a new data object to the DataStorage.*/
void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, itk::SmartPointer<mitk::Image> segmentation,
const std::string& name, mitk::DataNode::Pointer parent = nullptr);
Ui::QmitkImageMaskingWidgetControls* m_Controls;
};
#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp
index b02a5ea938..ef4c3bc979 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp
@@ -1,258 +1,254 @@
/*============================================================================
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 "QmitkMorphologicalOperationsWidget.h"
#include <ui_QmitkMorphologicalOperationsWidgetControls.h>
#include <mitkProgressBar.h>
-#include <mitkSliceNavigationController.h>
-
#include <QCheckBox>
static const char* const HelpText = "Select a segmentation above";
-QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent)
- : QmitkSegmentationUtilityWidget(timeNavigationController, parent)
+QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent)
+ : QWidget(parent)
{
m_Controls = new Ui::QmitkMorphologicalOperationsWidgetControls;
m_Controls->setupUi(this);
m_Controls->dataSelectionWidget->SetDataStorage(dataStorage);
m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SegmentationPredicate);
m_Controls->dataSelectionWidget->SetHelpText(HelpText);
connect(m_Controls->btnClosing, SIGNAL(clicked()), this, SLOT(OnClosingButtonClicked()));
connect(m_Controls->btnOpening, SIGNAL(clicked()), this, SLOT(OnOpeningButtonClicked()));
connect(m_Controls->btnDilatation, SIGNAL(clicked()), this, SLOT(OnDilatationButtonClicked()));
connect(m_Controls->btnErosion, SIGNAL(clicked()), this, SLOT(OnErosionButtonClicked()));
connect(m_Controls->btnFillHoles, SIGNAL(clicked()), this, SLOT(OnFillHolesButtonClicked()));
connect(m_Controls->radioButtonMorphoCross, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked()));
connect(m_Controls->radioButtonMorphoBall, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked()));
connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
if (m_Controls->dataSelectionWidget->GetSelection(0).IsNotNull())
this->OnSelectionChanged(0, m_Controls->dataSelectionWidget->GetSelection(0));
}
QmitkMorphologicalOperationsWidget::~QmitkMorphologicalOperationsWidget()
{
}
void QmitkMorphologicalOperationsWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
if (node.IsNotNull())
{
m_Controls->dataSelectionWidget->SetHelpText("");
this->EnableButtons(true);
}
else
{
m_Controls->dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
}
}
void QmitkMorphologicalOperationsWidget::EnableButtons(bool enable)
{
m_Controls->btnClosing->setEnabled(enable);
m_Controls->btnDilatation->setEnabled(enable);
m_Controls->btnErosion->setEnabled(enable);
m_Controls->btnFillHoles->setEnabled(enable);
m_Controls->btnOpening->setEnabled(enable);
}
void QmitkMorphologicalOperationsWidget::OnRadioButtonsClicked()
{
bool enable = m_Controls->radioButtonMorphoBall->isChecked();
m_Controls->sliderMorphFactor->setEnabled(enable);
m_Controls->spinBoxMorphFactor->setEnabled(enable);
}
void QmitkMorphologicalOperationsWidget::OnClosingButtonClicked()
{
QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
mitk::Image::Pointer image = static_cast<mitk::Image*>(node->GetData());
mitk::MorphologicalOperations::StructuralElementType structuralElement = CreateStructerElement_UI();
try
{
int factor = m_Controls->spinBoxMorphFactor->isEnabled()
? m_Controls->spinBoxMorphFactor->value()
: 1;
mitk::MorphologicalOperations::Closing(image, factor, structuralElement);
}
catch (const itk::ExceptionObject& exception)
{
MITK_WARN << "Exception caught: " << exception.GetDescription();
QApplication::restoreOverrideCursor();
return;
}
node->SetData(image);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QApplication::restoreOverrideCursor();
}
void QmitkMorphologicalOperationsWidget::OnOpeningButtonClicked()
{
QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
mitk::Image::Pointer image = static_cast<mitk::Image*>(node->GetData());
mitk::MorphologicalOperations::StructuralElementType structuralElement = CreateStructerElement_UI();
try
{
int factor = m_Controls->spinBoxMorphFactor->isEnabled()
? m_Controls->spinBoxMorphFactor->value()
: 1;
mitk::MorphologicalOperations::Opening(image, factor, structuralElement);
}
catch (const itk::ExceptionObject& exception)
{
MITK_WARN << "Exception caught: " << exception.GetDescription();
QApplication::restoreOverrideCursor();
return;
}
node->SetData(image);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QApplication::restoreOverrideCursor();
}
void QmitkMorphologicalOperationsWidget::OnDilatationButtonClicked()
{
QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
mitk::Image::Pointer image = static_cast<mitk::Image*>(node->GetData());
mitk::MorphologicalOperations::StructuralElementType structuralElement = this->CreateStructerElement_UI();
try
{
int factor = m_Controls->spinBoxMorphFactor->isEnabled()
? m_Controls->spinBoxMorphFactor->value()
: 1;
mitk::MorphologicalOperations::Dilate(image, factor, structuralElement);
}
catch (const itk::ExceptionObject& exception)
{
MITK_WARN << "Exception caught: " << exception.GetDescription();
QApplication::restoreOverrideCursor();
return;
}
node->SetData(image);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QApplication::restoreOverrideCursor();
}
void QmitkMorphologicalOperationsWidget::OnErosionButtonClicked()
{
QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
mitk::Image::Pointer image = static_cast<mitk::Image*>(node->GetData());
mitk::MorphologicalOperations::StructuralElementType structuralElement = CreateStructerElement_UI();
try
{
int factor = m_Controls->spinBoxMorphFactor->isEnabled()
? m_Controls->spinBoxMorphFactor->value()
: 1;
mitk::MorphologicalOperations::Erode(image, factor, structuralElement);
}
catch (const itk::ExceptionObject& exception)
{
MITK_WARN << "Exception caught: " << exception.GetDescription();
QApplication::restoreOverrideCursor();
return;
}
node->SetData(image);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QApplication::restoreOverrideCursor();
}
void QmitkMorphologicalOperationsWidget::OnFillHolesButtonClicked()
{
QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0);
mitk::Image::Pointer image = static_cast<mitk::Image*>(node->GetData());
try
{
mitk::MorphologicalOperations::FillHoles(image);
}
catch (const itk::ExceptionObject& exception)
{
MITK_WARN << "Exception caught: " << exception.GetDescription();
QApplication::restoreOverrideCursor();
return;
}
node->SetData(image);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
QApplication::restoreOverrideCursor();
}
mitk::MorphologicalOperations::StructuralElementType QmitkMorphologicalOperationsWidget::CreateStructerElement_UI()
{
bool ball = m_Controls->radioButtonMorphoBall->isChecked();
int accum_flag = 0;
if(ball){
if(m_Controls->planeSelectionComboBox->currentIndex() == 0) accum_flag = mitk::MorphologicalOperations::Ball; // 3D Operation
if(m_Controls->planeSelectionComboBox->currentIndex() == 1) accum_flag = mitk::MorphologicalOperations::Ball_Axial; // 2D Operation - Axial plane
if(m_Controls->planeSelectionComboBox->currentIndex() == 2) accum_flag = mitk::MorphologicalOperations::Ball_Sagittal; // 2D Operation - Sagittal plane
if(m_Controls->planeSelectionComboBox->currentIndex() == 3) accum_flag = mitk::MorphologicalOperations::Ball_Coronal; // 2D Operation - Coronal plane
}else{
if(m_Controls->planeSelectionComboBox->currentIndex() == 0) accum_flag = mitk::MorphologicalOperations::Cross;
if(m_Controls->planeSelectionComboBox->currentIndex() == 1) accum_flag = mitk::MorphologicalOperations::Cross_Axial;
if(m_Controls->planeSelectionComboBox->currentIndex() == 2) accum_flag = mitk::MorphologicalOperations::Cross_Sagittal;
if(m_Controls->planeSelectionComboBox->currentIndex() == 3) accum_flag = mitk::MorphologicalOperations::Cross_Coronal;
}
return (mitk::MorphologicalOperations::StructuralElementType)accum_flag;
}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h
index 3d19b84668..5e3862e85e 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h
@@ -1,61 +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 QmitkMorphologicalOperationsWidget_h
#define QmitkMorphologicalOperationsWidget_h
#include <MitkSegmentationUIExports.h>
#include <mitkMorphologicalOperations.h>
-#include <QmitkSegmentationUtilityWidget.h>
+#include <mitkRenderingManager.h>
+
+#include <QWidget>
namespace Ui
{
class QmitkMorphologicalOperationsWidgetControls;
}
namespace mitk
{
class DataNode;
class DataStorage;
}
/** \brief GUI class for morphological segmentation tools.
*/
-class MITKSEGMENTATIONUI_EXPORT QmitkMorphologicalOperationsWidget : public QmitkSegmentationUtilityWidget
+class MITKSEGMENTATIONUI_EXPORT QmitkMorphologicalOperationsWidget : public QWidget
{
Q_OBJECT
public:
- explicit QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent = nullptr);
+ explicit QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
~QmitkMorphologicalOperationsWidget() override;
public slots:
void OnClosingButtonClicked();
void OnOpeningButtonClicked();
void OnDilatationButtonClicked();
void OnErosionButtonClicked();
void OnFillHolesButtonClicked();
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
void OnRadioButtonsClicked();
protected:
void EnableButtons(bool enable);
private:
Ui::QmitkMorphologicalOperationsWidgetControls* m_Controls;
mitk::MorphologicalOperations::StructuralElementType CreateStructerElement_UI();
};
#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp
deleted file mode 100644
index 2389dda82b..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp
+++ /dev/null
@@ -1,34 +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 "QmitkSegmentationUtilityWidget.h"
-
-QmitkSegmentationUtilityWidget::QmitkSegmentationUtilityWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent)
- : QWidget(parent)
-{
- this->SetTimeNavigationController(timeNavigationController);
-}
-
-QmitkSegmentationUtilityWidget::~QmitkSegmentationUtilityWidget()
-{
-}
-
-mitk::SliceNavigationController* QmitkSegmentationUtilityWidget::GetTimeNavigationController() const
-{
- return m_TimeNavigationController;
-}
-
-void QmitkSegmentationUtilityWidget::SetTimeNavigationController(mitk::SliceNavigationController* timeNavigationController)
-{
- m_TimeNavigationController = timeNavigationController;
- this->setEnabled(timeNavigationController != nullptr);
-}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.h
deleted file mode 100644
index d0328f9804..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.h
+++ /dev/null
@@ -1,53 +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.
-
-============================================================================*/
-
-#ifndef QmitkSegmentationUtilityWidget_h
-#define QmitkSegmentationUtilityWidget_h
-
-#include <MitkSegmentationUIExports.h>
-
-#include <QWidget>
-
-namespace mitk
-{
- class SliceNavigationController;
-}
-
-/** \brief Base class for segmentation utility widgets that need access to the time navigation controller.
- *
- * Call GetTimeNavigationController() in your derived class to gain access to the time navigation controller.
- * The time navigation controller is not not available at all times and hence this method can return nullptr.
- */
-class MITKSEGMENTATIONUI_EXPORT QmitkSegmentationUtilityWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit QmitkSegmentationUtilityWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = nullptr);
- ~QmitkSegmentationUtilityWidget() override;
-
- /** \brief Usually called only from QmitkSegmentationUtilitiesView::RenderWindowPartActivated() and QmitkSegmentationUtilitiesView::RenderWindowPartDeactivated().
- */
- void SetTimeNavigationController(mitk::SliceNavigationController* timeNavigationController);
-
-protected:
- /** \brief Call this method to access the time navigation controller.
- *
- * \return Pointer to the time navigation controller or nullptr, if it is not available.
- */
- mitk::SliceNavigationController* GetTimeNavigationController() const;
-
-private:
- mitk::SliceNavigationController* m_TimeNavigationController;
-};
-
-#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp
index 2e0edecc2f..7e6ad451b1 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp
@@ -1,170 +1,168 @@
/*============================================================================
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 "QmitkSurfaceToImageWidget.h"
#include <ui_QmitkSurfaceToImageWidgetControls.h>
#include <mitkDataStorage.h>
#include <mitkException.h>
#include <mitkExceptionMacro.h>
#include <mitkProgressBar.h>
#include <mitkProperties.h>
#include <mitkSurfaceToImageFilter.h>
#include <mitkSurface.h>
#include <mitkImage.h>
#include <mitkLabelSetImage.h>
#include <qmessagebox.h>
static const char* const HelpText = "Select an image and a surface above";
-QmitkSurfaceToImageWidget::QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent)
- : QmitkSegmentationUtilityWidget(timeNavigationController, parent)
+QmitkSurfaceToImageWidget::QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent)
+ : QWidget(parent)
{
m_Controls = new Ui::QmitkSurfaceToImageWidgetControls;
m_Controls->setupUi(this);
m_Controls->dataSelectionWidget->SetDataStorage(dataStorage);
m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImageAndSegmentationPredicate);
m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SurfacePredicate);
m_Controls->dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
connect (m_Controls->btnSurface2Image, SIGNAL(pressed()), this, SLOT(OnSurface2ImagePressed()));
connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
if( m_Controls->dataSelectionWidget->GetSelection(0).IsNotNull() &&
m_Controls->dataSelectionWidget->GetSelection(1).IsNotNull() )
{
this->OnSelectionChanged(0, m_Controls->dataSelectionWidget->GetSelection(0));
}
}
QmitkSurfaceToImageWidget::~QmitkSurfaceToImageWidget()
{
}
void QmitkSurfaceToImageWidget::EnableButtons(bool enable)
{
m_Controls->btnSurface2Image->setEnabled(enable);
}
void QmitkSurfaceToImageWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer surfaceNode = dataSelectionWidget->GetSelection(1);
if (imageNode.IsNull() || surfaceNode.IsNull() )
{
dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
}
else
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( dataSelectionWidget->GetSelection(0)->GetData() );
mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface*>( dataSelectionWidget->GetSelection(1)->GetData() );
if( image->GetTimeSteps() != surface->GetTimeSteps() )
{
dataSelectionWidget->SetHelpText("Image and surface are of different size");
this->EnableButtons(false);
}
else
{
dataSelectionWidget->SetHelpText("");
this->EnableButtons();
}
}
}
void QmitkSurfaceToImageWidget::OnSurface2ImagePressed()
{
this->EnableButtons(false);
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( dataSelectionWidget->GetSelection(0)->GetData() );
mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface*>( dataSelectionWidget->GetSelection(1)->GetData() );
if( image.IsNull() || surface.IsNull())
{
MITK_ERROR << "Selection does not contain an image and/or a surface";
QMessageBox::information( this, "Surface To Image", "Selection does not contain an image and/or a surface", QMessageBox::Ok );
this->EnableButtons();
return;
}
mitk::Image::Pointer resultImage(nullptr);
resultImage = this->ConvertSurfaceToImage( image, surface );
if( resultImage.IsNull() )
{
MITK_ERROR << "Convert Surface to binary image failed";
QMessageBox::information( this, "Surface To Image", "Convert Surface to binary image failed", QMessageBox::Ok );
this->EnableButtons();
return;
}
//create name for result node
std::string nameOfResultImage = dataSelectionWidget->GetSelection(0)->GetName();
nameOfResultImage.append("_");
nameOfResultImage.append(dataSelectionWidget->GetSelection(1)->GetName());
//create data node and add to data storage
mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
resultNode->SetData( resultImage );
resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) );
// resultNode->SetProperty("binary", mitk::BoolProperty::New(true) );
auto dataStorage = dataSelectionWidget->GetDataStorage();
if (dataStorage.IsNull())
{
std::string exception = "Cannot add result to the data storage. Data storage invalid.";
MITK_ERROR << "Error converting surface to binary image: " << exception;
QMessageBox::information(nullptr, "Error converting surface to binary image", QString::fromStdString(exception));
}
dataStorage->Add(resultNode, dataSelectionWidget->GetSelection(0));
this->EnableButtons();
}
mitk::LabelSetImage::Pointer QmitkSurfaceToImageWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface )
{
mitk::ProgressBar::GetInstance()->AddStepsToDo(2);
mitk::ProgressBar::GetInstance()->Progress();
mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
surfaceToImageFilter->MakeOutputBinaryOn();
surfaceToImageFilter->SetInput(surface);
surfaceToImageFilter->SetImage(image);
try
{
surfaceToImageFilter->Update();
}
catch(itk::ExceptionObject& excpt)
{
MITK_ERROR << excpt.GetDescription();
return nullptr;
}
mitk::ProgressBar::GetInstance()->Progress();
mitk::Image::Pointer resultImage = surfaceToImageFilter->GetOutput();
mitk::LabelSetImage::Pointer multilabelImage = mitk::LabelSetImage::New();
multilabelImage->InitializeByLabeledImage(resultImage);
return multilabelImage;
}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
index 55e2178163..b218cf76c9 100644
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
@@ -1,77 +1,75 @@
/*============================================================================
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 QmitkSurfaceToImageWidget_h
#define QmitkSurfaceToImageWidget_h
#include <MitkSegmentationUIExports.h>
-#include <QmitkSegmentationUtilityWidget.h>
-
#include "itkSmartPointer.h"
+#include <QWidget>
+
namespace Ui
{
class QmitkSurfaceToImageWidgetControls;
}
namespace mitk
{
class DataNode;
class DataStorage;
class Surface;
class Image;
class LabelSetImage;
}
/*!
\brief QmitkSurfaceToImageWidget
The Tool converts a surface to a binary image. The Method requires
a surface and an image, which header information defines the output
image. The resulting binary image has the same dimension, size, and
Geometry3D as the input image.
*/
-class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceToImageWidget : public QmitkSegmentationUtilityWidget
+class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceToImageWidget : public QWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
- explicit QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage,
- mitk::SliceNavigationController* timeNavigationController,
- QWidget* parent = nullptr);
+ explicit QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
/** @brief Defaul destructor. */
~QmitkSurfaceToImageWidget() override;
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
/** @brief This slot is called if user activates the button to convert a surface into a binary image. */
void OnSurface2ImagePressed();
private:
/** @brief Enable buttons if data selction is valid. */
void EnableButtons(bool enable = true);
/** @brief Convert a surface into an binary image. */
itk::SmartPointer<mitk::LabelSetImage> ConvertSurfaceToImage( itk::SmartPointer<mitk::Image> image, itk::SmartPointer<mitk::Surface> surface );
Ui::QmitkSurfaceToImageWidgetControls* m_Controls;
};
#endif
diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake
index dd90c58132..90e890363e 100644
--- a/Modules/SegmentationUI/files.cmake
+++ b/Modules/SegmentationUI/files.cmake
@@ -1,124 +1,125 @@
set(CPP_FILES
Qmitk/QmitkSegWithPreviewToolGUIBase.cpp
Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.cpp
Qmitk/QmitkBinaryThresholdToolGUIBase.cpp
Qmitk/QmitkBinaryThresholdToolGUI.cpp
Qmitk/QmitkBinaryThresholdULToolGUI.cpp
Qmitk/QmitkConfirmSegmentationDialog.cpp
Qmitk/QmitkCopyToClipBoardDialog.cpp
Qmitk/QmitkDrawPaintbrushToolGUI.cpp
Qmitk/QmitkErasePaintbrushToolGUI.cpp
Qmitk/QmitkEditableContourToolGUIBase.cpp
Qmitk/QmitkGrowCutToolGUI.cpp
Qmitk/QmitkLiveWireTool2DGUI.cpp
Qmitk/QmitkLassoToolGUI.cpp
Qmitk/QmitkOtsuTool3DGUI.cpp
Qmitk/QmitkPaintbrushToolGUI.cpp
Qmitk/QmitkPickingToolGUI.cpp
Qmitk/QmitkSlicesInterpolator.cpp
Qmitk/QmitkToolGUI.cpp
Qmitk/QmitkToolGUIArea.cpp
Qmitk/QmitkToolSelectionBox.cpp
Qmitk/QmitknnUNetFolderParser.cpp
Qmitk/QmitknnUNetToolGUI.cpp
Qmitk/QmitknnUNetWorker.cpp
Qmitk/QmitknnUNetGPU.cpp
Qmitk/QmitkSurfaceStampWidget.cpp
Qmitk/QmitkMaskStampWidget.cpp
Qmitk/QmitkStaticDynamicSegmentationDialog.cpp
Qmitk/QmitkSimpleLabelSetListWidget.cpp
Qmitk/QmitkSegmentationTaskListWidget.cpp
Qmitk/QmitkTotalSegmentatorToolGUI.cpp
Qmitk/QmitkSetupVirtualEnvUtil.cpp
Qmitk/QmitkMultiLabelInspector.cpp
Qmitk/QmitkMultiLabelManager.cpp
Qmitk/QmitkMultiLabelTreeModel.cpp
Qmitk/QmitkMultiLabelTreeView.cpp
Qmitk/QmitkMultiLabelPresetHelper.cpp
Qmitk/QmitkLabelColorItemDelegate.cpp
Qmitk/QmitkLabelToggleItemDelegate.cpp
+ Qmitk/QmitkFindSegmentationTaskDialog.cpp
Qmitk/QmitkMonaiLabelToolGUI.cpp
SegmentationUtilities/QmitkBooleanOperationsWidget.cpp
SegmentationUtilities/QmitkContourModelToImageWidget.cpp
SegmentationUtilities/QmitkImageMaskingWidget.cpp
SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp
SegmentationUtilities/QmitkSurfaceToImageWidget.cpp
- SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp
SegmentationUtilities/QmitkDataSelectionWidget.cpp
)
set(H_FILES
Qmitk/QmitkMultiLabelPresetHelper.h
)
set(MOC_H_FILES
Qmitk/QmitkSegWithPreviewToolGUIBase.h
Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.h
Qmitk/QmitkBinaryThresholdToolGUIBase.h
Qmitk/QmitkBinaryThresholdToolGUI.h
Qmitk/QmitkBinaryThresholdULToolGUI.h
Qmitk/QmitkConfirmSegmentationDialog.h
Qmitk/QmitkCopyToClipBoardDialog.h
Qmitk/QmitkDrawPaintbrushToolGUI.h
Qmitk/QmitkErasePaintbrushToolGUI.h
Qmitk/QmitkEditableContourToolGUIBase.h
Qmitk/QmitkGrowCutToolGUI.h
Qmitk/QmitkLiveWireTool2DGUI.h
Qmitk/QmitkLassoToolGUI.h
Qmitk/QmitkOtsuTool3DGUI.h
Qmitk/QmitkPaintbrushToolGUI.h
Qmitk/QmitkPickingToolGUI.h
Qmitk/QmitkSlicesInterpolator.h
Qmitk/QmitkToolGUI.h
Qmitk/QmitkToolGUIArea.h
Qmitk/QmitkToolSelectionBox.h
Qmitk/QmitknnUNetFolderParser.h
Qmitk/QmitknnUNetToolGUI.h
Qmitk/QmitknnUNetGPU.h
Qmitk/QmitknnUNetWorker.h
Qmitk/QmitknnUNetEnsembleLayout.h
Qmitk/QmitkSurfaceStampWidget.h
Qmitk/QmitkMaskStampWidget.h
Qmitk/QmitkStaticDynamicSegmentationDialog.h
Qmitk/QmitkSimpleLabelSetListWidget.h
Qmitk/QmitkSegmentationTaskListWidget.h
Qmitk/QmitkTotalSegmentatorToolGUI.h
Qmitk/QmitkSetupVirtualEnvUtil.h
Qmitk/QmitkMultiLabelInspector.h
Qmitk/QmitkMultiLabelManager.h
Qmitk/QmitkMultiLabelTreeModel.h
Qmitk/QmitkMultiLabelTreeView.h
Qmitk/QmitkLabelColorItemDelegate.h
Qmitk/QmitkLabelToggleItemDelegate.h
+ Qmitk/QmitkFindSegmentationTaskDialog.h
Qmitk/QmitkMonaiLabelToolGUI.h
SegmentationUtilities/QmitkBooleanOperationsWidget.h
SegmentationUtilities/QmitkContourModelToImageWidget.h
SegmentationUtilities/QmitkImageMaskingWidget.h
SegmentationUtilities/QmitkMorphologicalOperationsWidget.h
SegmentationUtilities/QmitkSurfaceToImageWidget.h
- SegmentationUtilities/QmitkSegmentationUtilityWidget.h
SegmentationUtilities/QmitkDataSelectionWidget.h
)
set(UI_FILES
Qmitk/QmitkConfirmSegmentationDialog.ui
Qmitk/QmitkGrowCutToolWidgetControls.ui
Qmitk/QmitkOtsuToolWidgetControls.ui
Qmitk/QmitkSurfaceStampWidgetGUIControls.ui
Qmitk/QmitkMaskStampWidgetGUIControls.ui
Qmitk/QmitknnUNetToolGUIControls.ui
Qmitk/QmitkEditableContourToolGUIControls.ui
Qmitk/QmitkSegmentationTaskListWidget.ui
Qmitk/QmitkTotalSegmentatorGUIControls.ui
Qmitk/QmitkMultiLabelInspectorControls.ui
Qmitk/QmitkMultiLabelManagerControls.ui
+ Qmitk/QmitkFindSegmentationTaskDialog.ui
SegmentationUtilities/QmitkBooleanOperationsWidgetControls.ui
SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui
SegmentationUtilities/QmitkImageMaskingWidgetControls.ui
SegmentationUtilities/QmitkMorphologicalOperationsWidgetControls.ui
SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui
SegmentationUtilities/QmitkDataSelectionWidgetControls.ui
)
set(QRC_FILES
resources/SegmentationUI.qrc
)
diff --git a/Modules/SegmentationUI/resources/SegmentationUI.qrc b/Modules/SegmentationUI/resources/SegmentationUI.qrc
index 53c9b6eeb7..37014d77db 100644
--- a/Modules/SegmentationUI/resources/SegmentationUI.qrc
+++ b/Modules/SegmentationUI/resources/SegmentationUI.qrc
@@ -1,35 +1,36 @@
<RCC>
<qresource prefix="/Qmitk" >
<file>BooleanDifference_48x48.png</file>
<file>BooleanIntersection_48x48.png</file>
<file>BooleanUnion_48x48.png</file>
<file>BooleanLabelA_32x32.png</file>
<file>BooleanLabelB_32x32.png</file>
<file>Dilate_48x48.png</file>
<file>Erode_48x48.png</file>
<file>Closing_48x48.png</file>
<file>Opening_48x48.png</file>
<file>FillHoles_48x48.png</file>
<file>DeleteLayer_48x48.png</file>
<file>PreviousLayer_48x48.png</file>
<file>NextLayer_48x48.png</file>
<file>AddLayer_48x48.png</file>
<file>LockExterior_48x48.png</file>
<file>UnlockExterior_48x48.png</file>
<file>NewLabel_48x48.png</file>
<file>NewSegmentation_48x48.png</file>
<file>MergeLabels.png</file>
<file>RemoveLabel.png</file>
<file>EraseLabel.png</file>
<file>CreateSurface.png</file>
<file>CreateMask.png</file>
<file>RandomColor.png</file>
<file>RenameLabel.png</file>
<file>icon_label_add.svg</file>
<file>icon_label_add_instance.svg</file>
<file>icon_label_delete.svg</file>
<file>icon_label_delete_instance.svg</file>
<file>icon_group_add.svg</file>
<file>icon_group_delete.svg</file>
+ <file>icon_find.svg</file>
</qresource>
</RCC>
diff --git a/Modules/SegmentationUI/resources/icon_find.svg b/Modules/SegmentationUI/resources/icon_find.svg
new file mode 100644
index 0000000000..27fe0315c5
--- /dev/null
+++ b/Modules/SegmentationUI/resources/icon_find.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ height="128"
+ width="128"
+ version="1.1"
+ id="svg6"
+ sodipodi:docname="icon_find.svg"
+ inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ id="namedview8"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ showgrid="false"
+ inkscape:zoom="8.0234375"
+ inkscape:cx="63.937683"
+ inkscape:cy="63.937683"
+ inkscape:window-width="5120"
+ inkscape:window-height="1377"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg6" />
+ <path
+ d="M50.2 0C22.551 0 0 22.468 0 50.016s22.551 50.018 50.2 50.018a49.93 49.93 0 0 0 25.665-7.071 12.048 12.004 0 0 0 1.808 2.27l29.818 29.308a12.048 12.004 0 0 0 17.039-.115 12.048 12.004 0 0 0-.116-16.974l-29.818-29.31a12.048 12.004 0 0 0-1.935-1.543c4.774-7.545 7.589-16.435 7.708-25.955a6.406 6.383 0 0 0 .031-.627 6.406 6.383 0 0 0-.033-.645C100.014 22.123 77.63 0 50.2 0zm0 12.768c20.724 0 37.387 16.6 37.387 37.248S70.924 87.266 50.2 87.266s-37.387-16.602-37.387-37.25S29.476 12.768 50.2 12.768z"
+ fill="#00ff00"
+ id="path4" />
+</svg>
diff --git a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp
index 20faa7a6e4..26418f9785 100644
--- a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp
+++ b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp
@@ -1,1097 +1,1097 @@
/*============================================================================
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 <mitkSurfaceInterpolationController.h>
#include <mitkTestFixture.h>
#include <mitkTestingMacros.h>
#include <mitkImageTimeSelector.h>
#include <mitkLabelSetImage.h>
#include <vtkDebugLeaks.h>
#include <vtkDoubleArray.h>
#include <vtkFieldData.h>
#include <vtkPolygon.h>
#include <vtkRegularPolygonSource.h>
class mitkSurfaceInterpolationControllerTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkSurfaceInterpolationControllerTestSuite);
MITK_TEST(TestSingleton);
MITK_TEST(TestSetCurrentInterpolationSession);
MITK_TEST(TestReplaceInterpolationSession);
MITK_TEST(TestRemoveAllInterpolationSessions);
MITK_TEST(TestRemoveInterpolationSession);
MITK_TEST(TestOnSegmentationDeleted);
MITK_TEST(TestSetCurrentInterpolationSession4D);
MITK_TEST(TestReplaceInterpolationSession4D);
MITK_TEST(TestRemoveAllInterpolationSessions4D);
MITK_TEST(TestRemoveInterpolationSession4D);
MITK_TEST(TestOnSegmentationDeleted4D);
/// \todo Workaround for memory leak in TestAddNewContour. Bug 18096.
vtkDebugLeaks::SetExitError(0);
MITK_TEST(TestAddNewContour);
MITK_TEST(TestRemoveContour);
CPPUNIT_TEST_SUITE_END();
private:
mitk::SurfaceInterpolationController::Pointer m_Controller;
public:
mitk::Image::Pointer createImage(unsigned int *dimensions)
{
mitk::Image::Pointer newImage = mitk::Image::New();
// mitk::LabelSetImage::Pointer newImage = mitk::LabelSetImage::New();
mitk::PixelType p_type = mitk::MakeScalarPixelType<unsigned char>();
newImage->Initialize(p_type, 3, dimensions);
return newImage;
}
mitk::LabelSetImage::Pointer createLabelSetImage(unsigned int *dimensions)
{
mitk::Image::Pointer image = createImage(dimensions);
mitk::LabelSetImage::Pointer newImage = mitk::LabelSetImage::New();
newImage->InitializeByLabeledImage(image);
return newImage;
}
mitk::Image::Pointer createImage4D(unsigned int *dimensions)
{
mitk::Image::Pointer newImage = mitk::Image::New();
mitk::PixelType p_type = mitk::MakeScalarPixelType<unsigned char>();
newImage->Initialize(p_type, 4, dimensions);
return newImage;
}
mitk::LabelSetImage::Pointer createLabelSetImage4D(unsigned int *dimensions)
{
mitk::Image::Pointer image = createImage4D(dimensions);
mitk::LabelSetImage::Pointer newImage = mitk::LabelSetImage::New();
newImage->InitializeByLabeledImage(image);
return newImage;
}
void setUp() override
{
m_Controller = mitk::SurfaceInterpolationController::GetInstance();
m_Controller->RemoveAllInterpolationSessions();
m_Controller->SetCurrentTimePoint(0);
vtkSmartPointer<vtkRegularPolygonSource> polygonSource = vtkSmartPointer<vtkRegularPolygonSource>::New();
polygonSource->SetRadius(100);
polygonSource->SetNumberOfSides(7);
polygonSource->Update();
mitk::Surface::Pointer surface = mitk::Surface::New();
surface->SetVtkPolyData(polygonSource->GetOutput());
}
void TestSingleton()
{
mitk::SurfaceInterpolationController::Pointer controller2 = mitk::SurfaceInterpolationController::GetInstance();
CPPUNIT_ASSERT_MESSAGE("SurfaceInterpolationController pointers are not equal!",
m_Controller.GetPointer() == controller2.GetPointer());
}
void TestSetCurrentInterpolationSession()
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
unsigned int dimensions2[] = {20, 10, 30};
mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage(dimensions2);
// Test 1
m_Controller->SetCurrentInterpolationSession(segmentation_1);
MITK_ASSERT_EQUAL(
m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal");
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
// Test 2
m_Controller->SetCurrentInterpolationSession(segmentation_2);
MITK_ASSERT_EQUAL(
m_Controller->GetCurrentSegmentation(), segmentation_2->Clone(), "Segmentation images are not equal");
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test 3
m_Controller->SetCurrentInterpolationSession(segmentation_1);
MITK_ASSERT_EQUAL(
m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal");
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test 4
m_Controller->SetCurrentInterpolationSession(segmentation_1);
MITK_ASSERT_EQUAL(
m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal");
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// // Test 5
m_Controller->SetCurrentInterpolationSession(nullptr);
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().IsNull());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
}
mitk::PlaneGeometry::Pointer GetPlaneGeometry()
{
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal, spacing;
mitk::ScalarType width, height;
mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
auto planegeometry = mitk::PlaneGeometry::New();
width = 100;
widthInMM = width;
height = 200;
heightInMM = height;
thicknessInMM = 1.0;
mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
mitk::FillVector3D(right, widthInMM, 0, 0);
mitk::FillVector3D(bottom, 0, heightInMM, 0);
mitk::FillVector3D(normal, 0, 0, thicknessInMM);
mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
planegeometry->InitializeStandardPlane(right, bottom);
planegeometry->SetOrigin(origin);
planegeometry->SetSpacing(spacing);
return planegeometry;
}
void TestReplaceInterpolationSession()
{
// Create segmentation image
unsigned int dimensions1[] = {10, 10, 10};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
m_Controller->SetCurrentInterpolationSession(segmentation_1);
// Create some contours
double center_1[3] = {1.25f, 3.43f, 4.44f};
double normal_1[3] = {0.25f, 1.76f, 0.93f};
vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source->SetNumberOfSides(20);
p_source->SetCenter(center_1);
p_source->SetRadius(4);
p_source->SetNormal(normal_1);
p_source->Update();
vtkPolyData *poly_1 = p_source->GetOutput();
mitk::Surface::Pointer surf_1 = mitk::Surface::New();
surf_1->SetVtkPolyData(poly_1);
vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
int1Array->InsertNextValue(1);
int1Array->InsertNextValue(0);
int1Array->InsertNextValue(0);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
double1Array->InsertNextValue(center_1[0]);
double1Array->InsertNextValue(center_1[1]);
double1Array->InsertNextValue(center_1[2]);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
double center_2[3] = {4.0f, 4.0f, 4.0f};
double normal_2[3] = {1.0f, 0.0f, 0.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_2->SetNumberOfSides(80);
p_source_2->SetCenter(center_2);
p_source_2->SetRadius(4);
p_source_2->SetNormal(normal_2);
p_source_2->Update();
vtkPolyData *poly_2 = p_source_2->GetOutput();
mitk::Surface::Pointer surf_2 = mitk::Surface::New();
surf_2->SetVtkPolyData(poly_2);
vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
int2Array->InsertNextValue(1);
int2Array->InsertNextValue(0);
int2Array->InsertNextValue(0);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
vtkSmartPointer<vtkDoubleArray> doubleArray = vtkSmartPointer<vtkDoubleArray>::New();
doubleArray->InsertNextValue(center_2[0]);
doubleArray->InsertNextValue(center_2[1]);
doubleArray->InsertNextValue(center_2[2]);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(doubleArray);
std::vector<mitk::Surface::Pointer> surfaces;
surfaces.push_back(surf_1);
surfaces.push_back(surf_2);
const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
std::vector<const mitk::PlaneGeometry*> planeGeometries;
planeGeometries.push_back(planeGeometry1);
planeGeometries.push_back(planeGeometry2);
// Add contours
m_Controller->AddNewContours(surfaces, planeGeometries, true);
// Check if all contours are there
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1;
mitk::ScalarType n[3];
vtkPolygon::ComputeNormal(surf_1->GetVtkPolyData()->GetPoints(), n);
contourInfo1.ContourNormal = n;
contourInfo1.ContourPoint = center_1;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
vtkPolygon::ComputeNormal(surf_2->GetVtkPolyData()->GetPoints(), n);
contourInfo2.ContourNormal = n;
contourInfo2.ContourPoint = center_2;
const mitk::Surface *contour_1 = m_Controller->GetContour(contourInfo1);
const mitk::Surface *contour_2 = m_Controller->GetContour(contourInfo2);
CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2);
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage(dimensions1);
bool success = m_Controller->ReplaceInterpolationSession(segmentation_1, segmentation_2);
CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == true);
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
unsigned int dimensions2[] = {10, 20, 10};
mitk::Image::Pointer segmentation_3 = createLabelSetImage(dimensions2);
success = m_Controller->ReplaceInterpolationSession(segmentation_1, segmentation_3);
CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == false);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
}
void TestRemoveAllInterpolationSessions()
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10};
auto segmentation_1 = createLabelSetImage(dimensions1);
unsigned int dimensions2[] = {20, 10, 30};
auto segmentation_2 = createLabelSetImage(dimensions2);
// Test 1
m_Controller->SetCurrentInterpolationSession(segmentation_1);
m_Controller->SetCurrentInterpolationSession(segmentation_2);
m_Controller->RemoveAllInterpolationSessions();
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
m_Controller->GetNumberOfInterpolationSessions() == 0);
}
void TestRemoveInterpolationSession()
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
unsigned int dimensions2[] = {20, 10, 30};
mitk::Image::Pointer segmentation_2 = createLabelSetImage(dimensions2);
// Test 1
m_Controller->SetCurrentInterpolationSession(segmentation_1);
m_Controller->SetCurrentInterpolationSession(segmentation_2);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test current segmentation should not be null if another one was removed
m_Controller->RemoveInterpolationSession(segmentation_1);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Current segmentation is null after another one was removed",
m_Controller->GetCurrentSegmentation().IsNotNull());
m_Controller->SetCurrentInterpolationSession(segmentation_1);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test current segmentation should not be null if another one was removed
m_Controller->RemoveInterpolationSession(segmentation_1);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
CPPUNIT_ASSERT_MESSAGE("Current segmentation is not null after session was removed",
m_Controller->GetCurrentSegmentation().IsNull());
}
void TestOnSegmentationDeleted()
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10};
auto segmentation_1 = createLabelSetImage(dimensions1);
m_Controller->SetCurrentInterpolationSession(segmentation_1);
segmentation_1 = nullptr;
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
m_Controller->GetNumberOfInterpolationSessions() == 0);
}
void TestAddNewContour()
{
// Create segmentation image
unsigned int dimensions1[] = {10, 10, 10};
mitk::Image::Pointer segmentation_1 = createLabelSetImage(dimensions1);
m_Controller->SetCurrentInterpolationSession(segmentation_1);
// Create some contours
double center_1[3] = {1.25f, 3.43f, 4.44f};
double normal_1[3] = {0.25f, 1.76f, 0.93f};
vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source->SetNumberOfSides(20);
p_source->SetCenter(center_1);
p_source->SetRadius(4);
p_source->SetNormal(normal_1);
p_source->Update();
vtkPolyData *poly_1 = p_source->GetOutput();
mitk::Surface::Pointer surf_1 = mitk::Surface::New();
surf_1->SetVtkPolyData(poly_1);
vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
int1Array->InsertNextValue(1);
int1Array->InsertNextValue(0);
int1Array->InsertNextValue(0);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
double1Array->InsertNextValue(center_1[0]);
double1Array->InsertNextValue(center_1[1]);
double1Array->InsertNextValue(center_1[2]);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
double center_2[3] = {4.0f, 4.0f, 4.0f};
double normal_2[3] = {1.0f, 0.0f, 0.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_2->SetNumberOfSides(80);
p_source_2->SetCenter(center_2);
p_source_2->SetRadius(4);
p_source_2->SetNormal(normal_2);
p_source_2->Update();
vtkPolyData *poly_2 = p_source_2->GetOutput();
mitk::Surface::Pointer surf_2 = mitk::Surface::New();
surf_2->SetVtkPolyData(poly_2);
vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
int2Array->InsertNextValue(1);
int2Array->InsertNextValue(0);
int2Array->InsertNextValue(0);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
vtkSmartPointer<vtkDoubleArray> double2Array = vtkSmartPointer<vtkDoubleArray>::New();
double2Array->InsertNextValue(center_2[0]);
double2Array->InsertNextValue(center_2[1]);
double2Array->InsertNextValue(center_2[2]);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array);
double center_3[3] = {4.0f, 4.0f, 3.0f};
double normal_3[3] = {0.0f, 0.0f, 1.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_3 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_3->SetNumberOfSides(10);
p_source_3->SetCenter(center_3);
p_source_3->SetRadius(4);
p_source_3->SetNormal(normal_3);
p_source_3->Update();
vtkPolyData *poly_3 = p_source_3->GetOutput();
mitk::Surface::Pointer surf_3 = mitk::Surface::New();
surf_3->SetVtkPolyData(poly_3);
vtkSmartPointer<vtkIntArray> int3Array = vtkSmartPointer<vtkIntArray>::New();
int3Array->InsertNextValue(1);
int3Array->InsertNextValue(0);
int3Array->InsertNextValue(0);
surf_3->GetVtkPolyData()->GetFieldData()->AddArray(int3Array);
vtkSmartPointer<vtkDoubleArray> double3Array = vtkSmartPointer<vtkDoubleArray>::New();
double3Array->InsertNextValue(center_3[0]);
double3Array->InsertNextValue(center_3[1]);
double3Array->InsertNextValue(center_3[2]);
surf_3->GetVtkPolyData()->GetFieldData()->AddArray(double3Array);
std::vector<mitk::Surface::Pointer> surfaces;
surfaces.push_back(surf_1);
surfaces.push_back(surf_2);
surfaces.push_back(surf_3);
const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry3 = GetPlaneGeometry();
std::vector<const mitk::PlaneGeometry*> planeGeometries;
planeGeometries.push_back(planeGeometry1);
planeGeometries.push_back(planeGeometry2);
planeGeometries.push_back(planeGeometry3);
// Add contours
m_Controller->AddNewContours(surfaces, planeGeometries, true);
mitk::ScalarType n[3];
// Check if all contours are there
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1;
vtkPolygon::ComputeNormal(surf_1->GetVtkPolyData()->GetPoints(), n);
contourInfo1.ContourNormal = n;
contourInfo1.ContourPoint = center_1;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
vtkPolygon::ComputeNormal(surf_2->GetVtkPolyData()->GetPoints(), n);
contourInfo2.ContourNormal = n;
contourInfo2.ContourPoint = center_2;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3;
vtkPolygon::ComputeNormal(surf_3->GetVtkPolyData()->GetPoints(), n);
contourInfo3.ContourNormal = n;
contourInfo3.ContourPoint = center_3;
const mitk::Surface *contour_1 = m_Controller->GetContour(contourInfo1);
const mitk::Surface *contour_2 = m_Controller->GetContour(contourInfo2);
const mitk::Surface *contour_3 = m_Controller->GetContour(contourInfo3);
CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3);
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_3->GetVtkPolyData()), 0.000001, true));
// Create another segmentation image
unsigned int dimensions2[] = {20, 20, 20};
mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage(dimensions2);
m_Controller->SetCurrentInterpolationSession(segmentation_2);
// Create some contours
double center_4[3] = {10.0f, 10.0f, 10.0f};
double normal_4[3] = {0.0f, 1.0f, 0.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_4 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_4->SetNumberOfSides(8);
p_source_4->SetCenter(center_4);
p_source_4->SetRadius(5);
p_source_4->SetNormal(normal_4);
p_source_4->Update();
vtkPolyData *poly_4 = p_source_4->GetOutput();
mitk::Surface::Pointer surf_4 = mitk::Surface::New();
surf_4->SetVtkPolyData(poly_4);
vtkSmartPointer<vtkIntArray> int4Array = vtkSmartPointer<vtkIntArray>::New();
int4Array->InsertNextValue(2);
int4Array->InsertNextValue(0);
int4Array->InsertNextValue(0);
surf_4->GetVtkPolyData()->GetFieldData()->AddArray(int4Array);
vtkSmartPointer<vtkDoubleArray> double4Array = vtkSmartPointer<vtkDoubleArray>::New();
double4Array->InsertNextValue(center_4[0]);
double4Array->InsertNextValue(center_4[1]);
double4Array->InsertNextValue(center_4[2]);
surf_4->GetVtkPolyData()->GetFieldData()->AddArray(double4Array);
double center_5[3] = {3.0f, 10.0f, 10.0f};
double normal_5[3] = {1.0f, 0.0f, 0.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_5 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_5->SetNumberOfSides(16);
p_source_5->SetCenter(center_5);
p_source_5->SetRadius(8);
p_source_5->SetNormal(normal_5);
p_source_5->Update();
vtkPolyData *poly_5 = p_source_5->GetOutput();
mitk::Surface::Pointer surf_5 = mitk::Surface::New();
surf_5->SetVtkPolyData(poly_5);
vtkSmartPointer<vtkIntArray> int5Array = vtkSmartPointer<vtkIntArray>::New();
int5Array->InsertNextValue(2);
int5Array->InsertNextValue(0);
int5Array->InsertNextValue(0);
surf_5->GetVtkPolyData()->GetFieldData()->AddArray(int5Array);
vtkSmartPointer<vtkDoubleArray> double5Array = vtkSmartPointer<vtkDoubleArray>::New();
double5Array->InsertNextValue(center_5[0]);
double5Array->InsertNextValue(center_5[1]);
double5Array->InsertNextValue(center_5[2]);
surf_5->GetVtkPolyData()->GetFieldData()->AddArray(double5Array);
double center_6[3] = {10.0f, 10.0f, 3.0f};
double normal_6[3] = {0.0f, 0.0f, 1.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_6 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_6->SetNumberOfSides(100);
p_source_6->SetCenter(center_6);
p_source_6->SetRadius(5);
p_source_6->SetNormal(normal_6);
p_source_6->Update();
vtkPolyData *poly_6 = p_source_6->GetOutput();
mitk::Surface::Pointer surf_6 = mitk::Surface::New();
surf_6->SetVtkPolyData(poly_6);
vtkSmartPointer<vtkIntArray> int6Array = vtkSmartPointer<vtkIntArray>::New();
int6Array->InsertNextValue(2);
int6Array->InsertNextValue(0);
int6Array->InsertNextValue(0);
surf_6->GetVtkPolyData()->GetFieldData()->AddArray(int6Array);
vtkSmartPointer<vtkDoubleArray> double6Array = vtkSmartPointer<vtkDoubleArray>::New();
double6Array->InsertNextValue(center_6[0]);
double6Array->InsertNextValue(center_6[1]);
double6Array->InsertNextValue(center_6[2]);
surf_6->GetVtkPolyData()->GetFieldData()->AddArray(double6Array);
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo4;
vtkPolygon::ComputeNormal(surf_4->GetVtkPolyData()->GetPoints(), n);
contourInfo4.ContourNormal = n;
contourInfo4.ContourPoint = center_4;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo5;
vtkPolygon::ComputeNormal(surf_5->GetVtkPolyData()->GetPoints(), n);
contourInfo5.ContourNormal = n;
contourInfo5.ContourPoint = center_5;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo6;
vtkPolygon::ComputeNormal(surf_6->GetVtkPolyData()->GetPoints(), n);
contourInfo6.ContourNormal = n;
contourInfo6.ContourPoint = center_6;
const mitk::PlaneGeometry * planeGeometry4 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry5 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry6 = GetPlaneGeometry();
std::vector<mitk::Surface::Pointer> surfaces2;
surfaces2.push_back(surf_4);
surfaces2.push_back(surf_5);
surfaces2.push_back(surf_6);
std::vector<const mitk::PlaneGeometry*> planeGeometries2;
planeGeometries2.push_back(planeGeometry4);
planeGeometries2.push_back(planeGeometry5);
planeGeometries2.push_back(planeGeometry6);
m_Controller->AddNewContours(surfaces2, planeGeometries2, true);
// Check if all contours are there
auto contour_4 = m_Controller->GetContour(contourInfo4);
auto contour_5 = m_Controller->GetContour(contourInfo5);
auto contour_6 = m_Controller->GetContour(contourInfo6);
CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3);
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_4->GetVtkPolyData()), *(contour_4->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_5->GetVtkPolyData()), *(contour_5->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_6->GetVtkPolyData()), *(contour_6->GetVtkPolyData()), 0.000001, true));
// Modify some contours
vtkSmartPointer<vtkRegularPolygonSource> p_source_7 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_7->SetNumberOfSides(200);
p_source_7->SetCenter(3.0, 10.0, 10.0);
p_source_7->SetRadius(5);
p_source_7->SetNormal(1, 0, 0);
p_source_7->Update();
vtkPolyData *poly_7 = p_source_7->GetOutput();
mitk::Surface::Pointer surf_7 = mitk::Surface::New();
surf_7->SetVtkPolyData(poly_7);
vtkSmartPointer<vtkIntArray> int7Array = vtkSmartPointer<vtkIntArray>::New();
int7Array->InsertNextValue(2);
int7Array->InsertNextValue(0);
int7Array->InsertNextValue(0);
surf_7->GetVtkPolyData()->GetFieldData()->AddArray(int7Array);
vtkSmartPointer<vtkDoubleArray> double7Array = vtkSmartPointer<vtkDoubleArray>::New();
double7Array->InsertNextValue(3.0);
double7Array->InsertNextValue(10.0);
double7Array->InsertNextValue(10.0);
surf_7->GetVtkPolyData()->GetFieldData()->AddArray(double7Array);
std::vector<mitk::Surface::Pointer> surfaces3;
surfaces3.push_back(surf_7);
const mitk::PlaneGeometry * planeGeometry7 = GetPlaneGeometry();
std::vector<const mitk::PlaneGeometry*> planeGeometries3;
planeGeometries3.push_back(planeGeometry7);
m_Controller->AddNewContours(surfaces3, planeGeometries3, true);
mitk::ScalarType center_7[3];
center_7[0] = 3.0;
center_7[1] = 10.0;
center_7[2] = 10.0;
vtkPolygon::ComputeNormal(surf_7->GetVtkPolyData()->GetPoints(), n);
contourInfo5.ContourNormal = n;
contourInfo5.ContourPoint = center_7;
auto contour_7 = m_Controller->GetContour(contourInfo5);
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_7->GetVtkPolyData()), *(contour_7->GetVtkPolyData()), 0.000001, true));
// Change session and test if all contours are available
m_Controller->SetCurrentInterpolationSession(segmentation_1);
auto contour_8 = m_Controller->GetContour(contourInfo1);
auto contour_9 = m_Controller->GetContour(contourInfo2);
auto contour_10 = m_Controller->GetContour(contourInfo3);
CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3);
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_8->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_9->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_10->GetVtkPolyData()), 0.000001, true));
}
void TestRemoveContour()
{
// Create segmentation image
unsigned int dimensions1[] = {12, 12, 12};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
m_Controller->SetCurrentInterpolationSession(segmentation_1);
// Create some contours
double center_1[3] = {4.0f, 4.0f, 4.0f};
double normal_1[3] = {0.0f, 1.0f, 0.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source->SetNumberOfSides(20);
p_source->SetCenter(center_1);
p_source->SetRadius(4);
p_source->SetNormal(normal_1);
p_source->Update();
vtkPolyData *poly_1 = p_source->GetOutput();
mitk::Surface::Pointer surf_1 = mitk::Surface::New();
surf_1->SetVtkPolyData(poly_1);
vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
int1Array->InsertNextValue(1);
int1Array->InsertNextValue(0);
int1Array->InsertNextValue(0);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
double1Array->InsertNextValue(center_1[0]);
double1Array->InsertNextValue(center_1[1]);
double1Array->InsertNextValue(center_1[2]);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
double center_2[3] = {4.0f, 4.0f, 4.0f};
double normal_2[3] = {1.0f, 0.0f, 0.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_2->SetNumberOfSides(80);
p_source_2->SetCenter(center_2);
p_source_2->SetRadius(4);
p_source_2->SetNormal(normal_2);
p_source_2->Update();
vtkPolyData *poly_2 = p_source_2->GetOutput();
mitk::Surface::Pointer surf_2 = mitk::Surface::New();
surf_2->SetVtkPolyData(poly_2);
vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
int2Array->InsertNextValue(1);
int2Array->InsertNextValue(0);
int2Array->InsertNextValue(0);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
vtkSmartPointer<vtkDoubleArray> double2Array = vtkSmartPointer<vtkDoubleArray>::New();
double2Array->InsertNextValue(center_2[0]);
double2Array->InsertNextValue(center_2[1]);
double2Array->InsertNextValue(center_2[2]);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array);
std::vector<mitk::Surface::Pointer> surfaces;
surfaces.push_back(surf_1);
surfaces.push_back(surf_2);
const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
std::vector<const mitk::PlaneGeometry*> planeGeometries;
planeGeometries.push_back(planeGeometry1);
planeGeometries.push_back(planeGeometry2);
m_Controller->AddNewContours(surfaces, planeGeometries, true);
// // Add contours
CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2);
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3;
contourInfo3.Contour = surf_1->Clone();
contourInfo3.ContourNormal = normal_1;
contourInfo3.ContourPoint = center_1;
// Shift the new contour so that it is different
- contourInfo3.ContourPoint += 0.5;
+ contourInfo3.ContourPoint += mitk::Vector(0.5);
bool success = m_Controller->RemoveContour(contourInfo3);
CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was unintentionally removed!",
(m_Controller->GetNumberOfContours() == 2) && !success);
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
contourInfo2.ContourNormal = normal_2;
contourInfo2.ContourPoint = center_2;
contourInfo2.Contour = surf_2;
success = m_Controller->RemoveContour(contourInfo2);
CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was not removed!",
(m_Controller->GetNumberOfContours() == 1) && success);
// // Let's see if the other contour No. 1 is still there
- contourInfo3.ContourPoint -= 0.5;
+ contourInfo3.ContourPoint -= mitk::Vector(0.5);
const mitk::Surface *remainingContour = m_Controller->GetContour(contourInfo3);
CPPUNIT_ASSERT_MESSAGE(
"Remove failed - contour was accidentally removed!",
(m_Controller->GetNumberOfContours() == 1) &&
mitk::Equal(*(surf_1->GetVtkPolyData()), *(remainingContour->GetVtkPolyData()), 0.000001, true) && success);
}
bool AssertImagesEqual4D(mitk::LabelSetImage *img1, mitk::LabelSetImage *img2)
{
auto selector1 = mitk::ImageTimeSelector::New();
selector1->SetInput(img1);
selector1->SetChannelNr(0);
auto selector2 = mitk::ImageTimeSelector::New();
selector2->SetInput(img2);
selector2->SetChannelNr(0);
int numTs1 = img1->GetTimeSteps();
int numTs2 = img2->GetTimeSteps();
if (numTs1 != numTs2)
{
return false;
}
/*mitk::ImagePixelWriteAccessor<unsigned char,4> accessor( img1 );
itk::Index<4> ind;
ind[0] = 5;
ind[1] = 5;
ind[2] = 5;
ind[3] = 2;
accessor.SetPixelByIndex( ind, 7 );*/
for (int ts = 0; ts < numTs1; ++ts)
{
selector1->SetTimeNr(ts);
selector2->SetTimeNr(ts);
selector1->Update();
selector2->Update();
mitk::Image::Pointer imgSel1 = selector1->GetOutput();
mitk::Image::Pointer imgSel2 = selector2->GetOutput();
MITK_ASSERT_EQUAL(imgSel1, imgSel2, "Segmentation images are not equal");
}
return true;
}
void TestSetCurrentInterpolationSession4D()
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10, 5};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
// mitk::Image * segmentationImage_1 = dynamic_cast<mitk::Image *>(segmentation_1.GetPointer());
unsigned int dimensions2[] = {20, 10, 30, 4};
mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions2);
// Test 1
m_Controller->SetCurrentInterpolationSession(segmentation_1);
auto currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone());
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
// Test 2
m_Controller->SetCurrentInterpolationSession(segmentation_2);
// MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_2->Clone(), "Segmentation images are not
// equal");
currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
// AssertImagesEqual4D(currentSegmentation, segmentation_2->Clone());
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
currentSegmentation == segmentation_2.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test 3
m_Controller->SetCurrentInterpolationSession(segmentation_1);
// MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not
// equal");
currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone());
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test 4
m_Controller->SetCurrentInterpolationSession(segmentation_1);
// MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not
// equal");
currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone());
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test 5
m_Controller->SetCurrentInterpolationSession(nullptr);
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().IsNull());
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
}
void TestReplaceInterpolationSession4D()
{
// Create segmentation image
unsigned int dimensions1[] = {10, 10, 10, 5};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
m_Controller->SetCurrentInterpolationSession(segmentation_1);
m_Controller->SetCurrentTimePoint(0);
// Create some contours
double center_1[3] = {1.25f, 3.43f, 4.44f};
double normal_1[3] = {0.25f, 1.76f, 0.93f};
vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source->SetNumberOfSides(20);
p_source->SetCenter(center_1);
p_source->SetRadius(4);
p_source->SetNormal(normal_1);
p_source->Update();
vtkPolyData *poly_1 = p_source->GetOutput();
mitk::Surface::Pointer surf_1 = mitk::Surface::New();
surf_1->SetVtkPolyData(poly_1);
vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
int1Array->InsertNextValue(1);
int1Array->InsertNextValue(0);
int1Array->InsertNextValue(0);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
double1Array->InsertNextValue(center_1[0]);
double1Array->InsertNextValue(center_1[1]);
double1Array->InsertNextValue(center_1[2]);
surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
double center_2[3] = {4.0f, 4.0f, 4.0f};
double normal_2[3] = {1.0f, 0.0f, 0.0f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_2->SetNumberOfSides(80);
p_source_2->SetCenter(center_2);
p_source_2->SetRadius(4);
p_source_2->SetNormal(normal_2);
p_source_2->Update();
vtkPolyData *poly_2 = p_source_2->GetOutput();
mitk::Surface::Pointer surf_2 = mitk::Surface::New();
surf_2->SetVtkPolyData(poly_2);
vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
int2Array->InsertNextValue(1);
int2Array->InsertNextValue(0);
int2Array->InsertNextValue(0);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
vtkSmartPointer<vtkDoubleArray> double2Array = vtkSmartPointer<vtkDoubleArray>::New();
double2Array->InsertNextValue(center_2[0]);
double2Array->InsertNextValue(center_2[1]);
double2Array->InsertNextValue(center_2[2]);
surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array);
std::vector<mitk::Surface::Pointer> surfaces;
surfaces.push_back(surf_1);
surfaces.push_back(surf_2);
const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
std::vector<const mitk::PlaneGeometry*> planeGeometries;
planeGeometries.push_back(planeGeometry1);
planeGeometries.push_back(planeGeometry2);
// Add contours
m_Controller->AddNewContours(surfaces, planeGeometries, true);
// Add contours for another timestep
m_Controller->SetCurrentTimePoint(2);
double center_3[3] = {1.3f, 3.5f, 4.6f};
double normal_3[3] = {0.20f, 1.6f, 0.8f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_3 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_3->SetNumberOfSides(20);
p_source_3->SetCenter(center_3);
p_source_3->SetRadius(4);
p_source_3->SetNormal(normal_3);
p_source_3->Update();
vtkPolyData *poly_3 = p_source_3->GetOutput();
mitk::Surface::Pointer surf_3 = mitk::Surface::New();
surf_3->SetVtkPolyData(poly_3);
vtkSmartPointer<vtkIntArray> int3Array = vtkSmartPointer<vtkIntArray>::New();
int3Array->InsertNextValue(1);
int3Array->InsertNextValue(0);
int3Array->InsertNextValue(2);
surf_3->GetVtkPolyData()->GetFieldData()->AddArray(int3Array);
vtkSmartPointer<vtkDoubleArray> double3Array = vtkSmartPointer<vtkDoubleArray>::New();
double3Array->InsertNextValue(center_3[0]);
double3Array->InsertNextValue(center_3[1]);
double3Array->InsertNextValue(center_3[2]);
surf_3->GetVtkPolyData()->GetFieldData()->AddArray(double3Array);
double center_4[3] = {1.32f, 3.53f, 4.8f};
double normal_4[3] = {0.22f, 1.5f, 0.85f};
vtkSmartPointer<vtkRegularPolygonSource> p_source_4 = vtkSmartPointer<vtkRegularPolygonSource>::New();
p_source_4->SetNumberOfSides(20);
p_source_4->SetCenter(center_4);
p_source_4->SetRadius(4);
p_source_4->SetNormal(normal_4);
p_source_4->Update();
vtkPolyData *poly_4 = p_source_4->GetOutput();
mitk::Surface::Pointer surf_4 = mitk::Surface::New();
surf_4->SetVtkPolyData(poly_4);
vtkSmartPointer<vtkIntArray> int4Array = vtkSmartPointer<vtkIntArray>::New();
int4Array->InsertNextValue(1);
int4Array->InsertNextValue(0);
int4Array->InsertNextValue(2);
surf_4->GetVtkPolyData()->GetFieldData()->AddArray(int4Array);
vtkSmartPointer<vtkDoubleArray> double4Array = vtkSmartPointer<vtkDoubleArray>::New();
double4Array->InsertNextValue(center_4[0]);
double4Array->InsertNextValue(center_4[1]);
double4Array->InsertNextValue(center_4[2]);
surf_4->GetVtkPolyData()->GetFieldData()->AddArray(double4Array);
std::vector<mitk::Surface::Pointer> surfaces2;
surfaces2.push_back(surf_3);
surfaces2.push_back(surf_4);
const mitk::PlaneGeometry * planeGeometry3 = GetPlaneGeometry();
const mitk::PlaneGeometry * planeGeometry4 = GetPlaneGeometry();
std::vector<const mitk::PlaneGeometry*> planeGeometries2;
planeGeometries2.push_back(planeGeometry3);
planeGeometries2.push_back(planeGeometry4);
// Add contours
m_Controller->AddNewContours(surfaces2, planeGeometries2, true);
m_Controller->SetCurrentTimePoint(0);
// Check if all contours are there
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1;
contourInfo1.ContourNormal = normal_1;
contourInfo1.ContourPoint = center_1;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
contourInfo2.ContourNormal = normal_2;
contourInfo2.ContourPoint = center_2;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3;
mitk::ScalarType n[3];
vtkPolygon::ComputeNormal(surf_3->GetVtkPolyData()->GetPoints(), n);
contourInfo3.ContourNormal = n;
contourInfo3.ContourPoint = center_3;
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo4;
// mitk::ScalarType n[3];
vtkPolygon::ComputeNormal(surf_4->GetVtkPolyData()->GetPoints(), n);
contourInfo4.ContourNormal = n;
contourInfo4.ContourPoint = center_4;
const mitk::Surface *contour_1 = m_Controller->GetContour(contourInfo1);
const mitk::Surface *contour_2 = m_Controller->GetContour(contourInfo2);
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true));
m_Controller->SetCurrentTimePoint(2);
const mitk::Surface *contour_3 = m_Controller->GetContour(contourInfo3);
const mitk::Surface *contour_4 = m_Controller->GetContour(contourInfo4);
CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2);
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_3->GetVtkPolyData()), 0.000001, true));
CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
mitk::Equal(*(surf_4->GetVtkPolyData()), *(contour_4->GetVtkPolyData()), 0.000001, true));
mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions1);
bool success = m_Controller->ReplaceInterpolationSession(segmentation_1, segmentation_2);
CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == true);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
}
void TestRemoveAllInterpolationSessions4D()
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10, 4};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
unsigned int dimensions2[] = {20, 10, 30, 5};
mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions2);
// Test 1
m_Controller->SetCurrentInterpolationSession(segmentation_1);
m_Controller->SetCurrentInterpolationSession(segmentation_2);
m_Controller->RemoveAllInterpolationSessions();
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
m_Controller->GetNumberOfInterpolationSessions() == 0);
}
void TestRemoveInterpolationSession4D()
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10, 3};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
unsigned int dimensions2[] = {20, 10, 30, 6};
mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions2);
// Test 1
m_Controller->SetCurrentInterpolationSession(segmentation_1);
m_Controller->SetCurrentInterpolationSession(segmentation_2);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test current segmentation should not be null if another one was removed
m_Controller->RemoveInterpolationSession(segmentation_1);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
CPPUNIT_ASSERT_MESSAGE("Current segmentation is null after another one was removed",
m_Controller->GetCurrentSegmentation().IsNotNull());
m_Controller->SetCurrentInterpolationSession(segmentation_1);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
m_Controller->GetNumberOfInterpolationSessions() == 2);
// Test current segmentation should not be null if another one was removed
m_Controller->RemoveInterpolationSession(segmentation_1);
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
m_Controller->GetNumberOfInterpolationSessions() == 1);
CPPUNIT_ASSERT_MESSAGE("Current segmentation is not null after session was removed",
m_Controller->GetCurrentSegmentation().IsNull());
}
void TestOnSegmentationDeleted4D()
{
{
// Create image for testing
unsigned int dimensions1[] = {10, 10, 10, 7};
mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
m_Controller->SetCurrentInterpolationSession(segmentation_1);
m_Controller->SetCurrentTimePoint(3);
}
CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
m_Controller->GetNumberOfInterpolationSessions() == 0);
}
};
MITK_TEST_SUITE_REGISTRATION(mitkSurfaceInterpolationController)
diff --git a/Modules/SurfaceInterpolation/mitkCreateDistanceImageFromSurfaceFilter.cpp b/Modules/SurfaceInterpolation/mitkCreateDistanceImageFromSurfaceFilter.cpp
index 87de1560a1..16952fd4a7 100644
--- a/Modules/SurfaceInterpolation/mitkCreateDistanceImageFromSurfaceFilter.cpp
+++ b/Modules/SurfaceInterpolation/mitkCreateDistanceImageFromSurfaceFilter.cpp
@@ -1,617 +1,617 @@
/*============================================================================
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 "mitkCreateDistanceImageFromSurfaceFilter.h"
#include "mitkImageCast.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkDoubleArray.h"
#include "vtkPolyData.h"
#include "vtkSmartPointer.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkNeighborhoodIterator.h"
#include <queue>
void mitk::CreateDistanceImageFromSurfaceFilter::CreateEmptyDistanceImage()
{
// Determine the bounds of the input points in index- and world-coordinates
DistanceImageType::PointType minPointInWorldCoordinates, maxPointInWorldCoordinates;
DistanceImageType::IndexType minPointInIndexCoordinates, maxPointInIndexCoordinates;
DetermineBounds(
minPointInWorldCoordinates, maxPointInWorldCoordinates, minPointInIndexCoordinates, maxPointInIndexCoordinates);
// Calculate the extent of the region that contains all given points in MM.
// To do this, we take the difference between the maximal and minimal
// index-coordinates (must not be less than 1) and multiply it with the
// spacing of the reference-image.
Vector3D extentMM;
for (unsigned int dim = 0; dim < 3; ++dim)
{
extentMM[dim] = (std::abs(maxPointInIndexCoordinates[dim] - minPointInIndexCoordinates[dim])) *
m_ReferenceImage->GetSpacing()[dim];
}
/*
* Now create an empty distance image. The created image will always have the same number of pixels, independent from
* the original image (e.g. always consists of 500000 pixels) and will have an isotropic spacing.
* The spacing is calculated like the following:
* The image's volume = 500000 Pixels = extentX*spacing*extentY*spacing*extentZ*spacing
* So the spacing is: spacing = ( extentX*extentY*extentZ / 500000 )^(1/3)
*/
double basis = (extentMM[0] * extentMM[1] * extentMM[2]) / m_DistanceImageVolume;
double exponent = 1.0 / 3.0;
m_DistanceImageSpacing = pow(basis, exponent);
// calculate the number of pixels of the distance image for each direction
unsigned int numberOfXPixel = extentMM[0] / m_DistanceImageSpacing;
unsigned int numberOfYPixel = extentMM[1] / m_DistanceImageSpacing;
unsigned int numberOfZPixel = extentMM[2] / m_DistanceImageSpacing;
// We increase the sizeOfRegion by 4 as we decrease the origin by 2 later.
// This expansion of the region is necessary to achieve a complete
// interpolation.
DistanceImageType::SizeType sizeOfRegion;
sizeOfRegion[0] = numberOfXPixel + 8;
sizeOfRegion[1] = numberOfYPixel + 8;
sizeOfRegion[2] = numberOfZPixel + 8;
// The region starts at index 0,0,0
DistanceImageType::IndexType initialOriginAsIndex;
initialOriginAsIndex.Fill(0);
DistanceImageType::PointType originAsWorld = minPointInWorldCoordinates;
DistanceImageType::RegionType lpRegion;
lpRegion.SetSize(sizeOfRegion);
lpRegion.SetIndex(initialOriginAsIndex);
// We initialize the itk::Image with
// * origin and direction to have it correctly placed and rotated in the world
// * the largest possible region to set the extent to be calculated
// * the isotropic spacing that we have calculated above
m_DistanceImageITK = DistanceImageType::New();
m_DistanceImageITK->SetOrigin(originAsWorld);
m_DistanceImageITK->SetDirection(m_ReferenceImage->GetDirection());
m_DistanceImageITK->SetRegions(lpRegion);
- m_DistanceImageITK->SetSpacing(m_DistanceImageSpacing);
+ m_DistanceImageITK->SetSpacing(itk::Vector<double, 3>(m_DistanceImageSpacing));
m_DistanceImageITK->Allocate();
// First of all the image is initialized with the value 10*m_DistanceImageSpacing for each pixel
m_DistanceImageDefaultBufferValue = 10 * m_DistanceImageSpacing;
m_DistanceImageITK->FillBuffer(m_DistanceImageDefaultBufferValue);
// Now we move the origin of the distanceImage 2 index-Coordinates
// in all directions
DistanceImageType::IndexType originAsIndex;
m_DistanceImageITK->TransformPhysicalPointToIndex(originAsWorld, originAsIndex);
originAsIndex[0] -= 2;
originAsIndex[1] -= 2;
originAsIndex[2] -= 2;
m_DistanceImageITK->TransformIndexToPhysicalPoint(originAsIndex, originAsWorld);
m_DistanceImageITK->SetOrigin(originAsWorld);
}
mitk::CreateDistanceImageFromSurfaceFilter::CreateDistanceImageFromSurfaceFilter()
: m_DistanceImageSpacing(0.0), m_DistanceImageDefaultBufferValue(0.0)
{
m_DistanceImageVolume = 50000;
this->m_UseProgressBar = false;
this->m_ProgressStepSize = 5;
mitk::Image::Pointer output = mitk::Image::New();
this->SetNthOutput(0, output.GetPointer());
}
mitk::CreateDistanceImageFromSurfaceFilter::~CreateDistanceImageFromSurfaceFilter()
{
}
void mitk::CreateDistanceImageFromSurfaceFilter::GenerateData()
{
this->PreprocessContourPoints();
this->CreateEmptyDistanceImage();
// First of all we have to build the equation-system from the existing contour-edge-points
this->CreateSolutionMatrixAndFunctionValues();
if (this->m_UseProgressBar)
mitk::ProgressBar::GetInstance()->Progress(1);
m_Weights = m_SolutionMatrix.partialPivLu().solve(m_FunctionValues);
if (this->m_UseProgressBar)
mitk::ProgressBar::GetInstance()->Progress(2);
// The last step is to create the distance map with the interpolated distance function
this->FillDistanceImage();
if (this->m_UseProgressBar)
mitk::ProgressBar::GetInstance()->Progress(2);
m_Centers.clear();
m_Normals.clear();
}
void mitk::CreateDistanceImageFromSurfaceFilter::PreprocessContourPoints()
{
unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
if (numberOfInputs == 0)
{
MITK_ERROR << "mitk::CreateDistanceImageFromSurfaceFilter: No input available. Please set an input!" << std::endl;
itkExceptionMacro("mitk::CreateDistanceImageFromSurfaceFilter: No input available. Please set an input!");
return;
}
// First of all we have to extract the nomals and the surface points.
// Duplicated points can be eliminated
vtkSmartPointer<vtkPolyData> polyData;
vtkSmartPointer<vtkDoubleArray> currentCellNormals;
vtkSmartPointer<vtkCellArray> existingPolys;
vtkSmartPointer<vtkPoints> existingPoints;
double p[3];
PointType currentPoint;
PointType normal;
for (unsigned int i = 0; i < numberOfInputs; i++)
{
auto currentSurface = this->GetInput(i);
polyData = currentSurface->GetVtkPolyData();
if (polyData->GetNumberOfPolys() == 0)
{
MITK_INFO << "mitk::CreateDistanceImageFromSurfaceFilter: No input-polygons available. Please be sure the input "
"surface consists of polygons!"
<< std::endl;
}
currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());
existingPolys = polyData->GetPolys();
existingPoints = polyData->GetPoints();
existingPolys->InitTraversal();
const vtkIdType *cell(nullptr);
vtkIdType cellSize(0);
for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
{
for (vtkIdType j = 0; j < cellSize; j++)
{
existingPoints->GetPoint(cell[j], p);
currentPoint.copy_in(p);
int count = std::count(m_Centers.begin(), m_Centers.end(), currentPoint);
if (count == 0)
{
double currentNormal[3];
currentCellNormals->GetTuple(cell[j], currentNormal);
normal.copy_in(currentNormal);
m_Normals.push_back(normal);
m_Centers.push_back(currentPoint);
}
} // end for all points
} // end for all cells
} // end for all outputs
}
void mitk::CreateDistanceImageFromSurfaceFilter::CreateSolutionMatrixAndFunctionValues()
{
// For we can now calculate the exact size of the centers we initialize the data structures
unsigned int numberOfCenters = m_Centers.size();
m_Centers.reserve(numberOfCenters * 3);
m_FunctionValues.resize(numberOfCenters * 3);
m_FunctionValues.fill(0);
PointType currentPoint;
PointType normal;
// Create inner points
for (unsigned int i = 0; i < numberOfCenters; i++)
{
currentPoint = m_Centers.at(i);
normal = m_Normals.at(i);
currentPoint[0] = currentPoint[0] - normal[0] * m_DistanceImageSpacing;
currentPoint[1] = currentPoint[1] - normal[1] * m_DistanceImageSpacing;
currentPoint[2] = currentPoint[2] - normal[2] * m_DistanceImageSpacing;
m_Centers.push_back(currentPoint);
m_FunctionValues[numberOfCenters + i] = -m_DistanceImageSpacing;
}
// Create outer points
for (unsigned int i = 0; i < numberOfCenters; i++)
{
currentPoint = m_Centers.at(i);
normal = m_Normals.at(i);
currentPoint[0] = currentPoint[0] + normal[0] * m_DistanceImageSpacing;
currentPoint[1] = currentPoint[1] + normal[1] * m_DistanceImageSpacing;
currentPoint[2] = currentPoint[2] + normal[2] * m_DistanceImageSpacing;
m_Centers.push_back(currentPoint);
m_FunctionValues[numberOfCenters * 2 + i] = m_DistanceImageSpacing;
}
// Now we have created all centers and all function values. Next step is to create the solution matrix
numberOfCenters = m_Centers.size();
m_SolutionMatrix.resize(numberOfCenters, numberOfCenters);
m_Weights.resize(numberOfCenters);
PointType p1;
PointType p2;
double norm;
for (unsigned int i = 0; i < numberOfCenters; i++)
{
for (unsigned int j = 0; j < numberOfCenters; j++)
{
// Calculate the RBF value. Currently using Phi(r) = r with r is the euclidian distance between two points
p1 = m_Centers.at(i);
p2 = m_Centers.at(j);
p1 = p1 - p2;
norm = p1.two_norm();
m_SolutionMatrix(i, j) = norm;
}
}
}
void mitk::CreateDistanceImageFromSurfaceFilter::FillDistanceImage()
{
/*
* Now we must calculate the distance for each pixel. But instead of calculating the distance value
* for all of the image's pixels we proceed similar to the region growing algorithm:
*
* 1. Take the first pixel from the narrowband_point_list and calculate the distance for each neighbor (6er)
* 2. If the current index's distance value is below a certain threshold push it into the list
* 3. Next iteration take the next index from the list and originAsIndex with 1. again
*
* This is done until the narrowband_point_list is empty.
*/
typedef itk::ImageRegionIteratorWithIndex<DistanceImageType> ImageIterator;
typedef itk::NeighborhoodIterator<DistanceImageType> NeighborhoodImageIterator;
std::queue<DistanceImageType::IndexType> narrowbandPoints;
PointType currentPoint = m_Centers.at(0);
double distance = this->CalculateDistanceValue(currentPoint);
// create itk::Point from vnl_vector
DistanceImageType::PointType currentPointAsPoint;
currentPointAsPoint[0] = currentPoint[0];
currentPointAsPoint[1] = currentPoint[1];
currentPointAsPoint[2] = currentPoint[2];
// Transform the input point in world-coordinates to index-coordinates
DistanceImageType::IndexType currentIndex;
m_DistanceImageITK->TransformPhysicalPointToIndex(currentPointAsPoint, currentIndex);
assert(
m_DistanceImageITK->GetLargestPossibleRegion().IsInside(currentIndex)); // we are quite certain this should hold
narrowbandPoints.push(currentIndex);
m_DistanceImageITK->SetPixel(currentIndex, distance);
NeighborhoodImageIterator::RadiusType radius;
radius.Fill(1);
NeighborhoodImageIterator nIt(radius, m_DistanceImageITK, m_DistanceImageITK->GetLargestPossibleRegion());
unsigned int relativeNbIdx[] = {4, 10, 12, 14, 16, 22};
bool isInBounds = false;
while (!narrowbandPoints.empty())
{
nIt.SetLocation(narrowbandPoints.front());
narrowbandPoints.pop();
unsigned int *relativeNb = &relativeNbIdx[0];
for (int i = 0; i < 6; i++)
{
nIt.GetPixel(*relativeNb, isInBounds);
if (isInBounds && nIt.GetPixel(*relativeNb) == m_DistanceImageDefaultBufferValue)
{
currentIndex = nIt.GetIndex(*relativeNb);
// Transform the currently checked point from index-coordinates to
// world-coordinates
m_DistanceImageITK->TransformIndexToPhysicalPoint(currentIndex, currentPointAsPoint);
// create a vnl_vector
currentPoint[0] = currentPointAsPoint[0];
currentPoint[1] = currentPointAsPoint[1];
currentPoint[2] = currentPointAsPoint[2];
// and check the distance
distance = this->CalculateDistanceValue(currentPoint);
if (std::fabs(distance) <= m_DistanceImageSpacing * 2)
{
nIt.SetPixel(*relativeNb, distance);
narrowbandPoints.push(currentIndex);
}
}
relativeNb++;
}
}
ImageIterator imgRegionIterator(m_DistanceImageITK, m_DistanceImageITK->GetLargestPossibleRegion());
imgRegionIterator.GoToBegin();
double prevPixelVal = 1;
DistanceImageType::IndexType _size;
_size.Fill(-1);
_size += m_DistanceImageITK->GetLargestPossibleRegion().GetSize();
// Set every pixel inside the surface to -m_DistanceImageDefaultBufferValue except the edge point (so that the
// received surface is closed)
while (!imgRegionIterator.IsAtEnd())
{
if (imgRegionIterator.Get() == m_DistanceImageDefaultBufferValue && prevPixelVal < 0)
{
while (imgRegionIterator.Get() == m_DistanceImageDefaultBufferValue)
{
if (imgRegionIterator.GetIndex()[0] == _size[0] || imgRegionIterator.GetIndex()[1] == _size[1] ||
imgRegionIterator.GetIndex()[2] == _size[2] || imgRegionIterator.GetIndex()[0] == 0U ||
imgRegionIterator.GetIndex()[1] == 0U || imgRegionIterator.GetIndex()[2] == 0U)
{
imgRegionIterator.Set(m_DistanceImageDefaultBufferValue);
prevPixelVal = m_DistanceImageDefaultBufferValue;
++imgRegionIterator;
break;
}
else
{
imgRegionIterator.Set((-1) * m_DistanceImageDefaultBufferValue);
++imgRegionIterator;
prevPixelVal = (-1) * m_DistanceImageDefaultBufferValue;
}
}
}
else if (imgRegionIterator.GetIndex()[0] == _size[0] || imgRegionIterator.GetIndex()[1] == _size[1] ||
imgRegionIterator.GetIndex()[2] == _size[2] || imgRegionIterator.GetIndex()[0] == 0U ||
imgRegionIterator.GetIndex()[1] == 0U || imgRegionIterator.GetIndex()[2] == 0U)
{
imgRegionIterator.Set(m_DistanceImageDefaultBufferValue);
prevPixelVal = m_DistanceImageDefaultBufferValue;
++imgRegionIterator;
}
else
{
prevPixelVal = imgRegionIterator.Get();
++imgRegionIterator;
}
}
Image::Pointer resultImage = this->GetOutput();
// Cast the created distance-Image from itk::Image to the mitk::Image
// that is our output.
CastToMitkImage(m_DistanceImageITK, resultImage);
}
double mitk::CreateDistanceImageFromSurfaceFilter::CalculateDistanceValue(PointType p)
{
double distanceValue(0);
PointType p1;
PointType p2;
double norm;
CenterList::iterator centerIter;
unsigned int count(0);
for (centerIter = m_Centers.begin(); centerIter != m_Centers.end(); centerIter++)
{
p1 = *centerIter;
p2 = p - p1;
norm = p2.two_norm();
distanceValue = distanceValue + (norm * m_Weights[count]);
++count;
}
return distanceValue;
}
void mitk::CreateDistanceImageFromSurfaceFilter::GenerateOutputInformation()
{
}
void mitk::CreateDistanceImageFromSurfaceFilter::PrintEquationSystem()
{
std::stringstream out;
out << "Nummber of rows: " << m_SolutionMatrix.rows() << " ****** Number of columns: " << m_SolutionMatrix.cols()
<< endl;
out << "[ ";
for (int i = 0; i < m_SolutionMatrix.rows(); i++)
{
for (int j = 0; j < m_SolutionMatrix.cols(); j++)
{
out << m_SolutionMatrix(i, j) << " ";
}
out << ";" << endl;
}
out << " ]\n\n\n";
for (unsigned int i = 0; i < m_Centers.size(); i++)
{
out << m_Centers.at(i) << ";" << endl;
}
std::cout << "Equation system: \n\n\n" << out.str();
}
void mitk::CreateDistanceImageFromSurfaceFilter::SetInput(const mitk::Surface *surface)
{
this->SetInput(0, surface);
}
void mitk::CreateDistanceImageFromSurfaceFilter::SetInput(unsigned int idx, const mitk::Surface *surface)
{
if (this->GetInput(idx) != surface)
{
this->SetNthInput(idx, const_cast<mitk::Surface *>(surface));
this->Modified();
}
}
const mitk::Surface *mitk::CreateDistanceImageFromSurfaceFilter::GetInput()
{
if (this->GetNumberOfIndexedInputs() < 1)
return nullptr;
return static_cast<const mitk::Surface *>(this->ProcessObject::GetInput(0));
}
const mitk::Surface *mitk::CreateDistanceImageFromSurfaceFilter::GetInput(unsigned int idx)
{
if (this->GetNumberOfIndexedInputs() < 1)
return nullptr;
return static_cast<const mitk::Surface *>(this->ProcessObject::GetInput(idx));
}
void mitk::CreateDistanceImageFromSurfaceFilter::RemoveInputs(mitk::Surface *input)
{
DataObjectPointerArraySizeType nb = this->GetNumberOfIndexedInputs();
for (DataObjectPointerArraySizeType i = 0; i < nb; i++)
{
if (this->GetInput(i) == input)
{
this->RemoveInput(i);
return;
}
}
}
void mitk::CreateDistanceImageFromSurfaceFilter::Reset()
{
for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
{
this->PopBackInput();
}
this->SetNumberOfIndexedInputs(0);
this->SetNumberOfIndexedOutputs(1);
mitk::Image::Pointer output = mitk::Image::New();
this->SetNthOutput(0, output.GetPointer());
}
void mitk::CreateDistanceImageFromSurfaceFilter::SetUseProgressBar(bool status)
{
this->m_UseProgressBar = status;
}
void mitk::CreateDistanceImageFromSurfaceFilter::SetProgressStepSize(unsigned int stepSize)
{
this->m_ProgressStepSize = stepSize;
}
void mitk::CreateDistanceImageFromSurfaceFilter::SetReferenceImage(itk::ImageBase<3>::Pointer referenceImage)
{
m_ReferenceImage = referenceImage;
}
void mitk::CreateDistanceImageFromSurfaceFilter::DetermineBounds(
DistanceImageType::PointType &minPointInWorldCoordinates,
DistanceImageType::PointType &maxPointInWorldCoordinates,
DistanceImageType::IndexType &minPointInIndexCoordinates,
DistanceImageType::IndexType &maxPointInIndexCoordinates)
{
PointType firstCenter = m_Centers.at(0);
DistanceImageType::PointType tmpPoint;
tmpPoint[0] = firstCenter[0];
tmpPoint[1] = firstCenter[1];
tmpPoint[2] = firstCenter[2];
// transform the first point from world-coordinates to index-coordinates
itk::ContinuousIndex<double, 3> tmpIndex;
m_ReferenceImage->TransformPhysicalPointToContinuousIndex(tmpPoint, tmpIndex);
// initialize the variables with this first point
DistanceImageType::IndexValueType xmin = tmpIndex[0];
DistanceImageType::IndexValueType ymin = tmpIndex[1];
DistanceImageType::IndexValueType zmin = tmpIndex[2];
DistanceImageType::IndexValueType xmax = tmpIndex[0];
DistanceImageType::IndexValueType ymax = tmpIndex[1];
DistanceImageType::IndexValueType zmax = tmpIndex[2];
// iterate over the rest of the points
auto centerIter = m_Centers.begin();
for (++centerIter; centerIter != m_Centers.end(); centerIter++)
{
tmpPoint[0] = (*centerIter)[0];
tmpPoint[1] = (*centerIter)[1];
tmpPoint[2] = (*centerIter)[2];
// transform each point from world-coordinates to index-coordinates
m_ReferenceImage->TransformPhysicalPointToContinuousIndex(tmpPoint, tmpIndex);
// and set the variables accordingly to find the minimum
// and maximum in all directions in index-coordinates
if (xmin > tmpIndex[0])
{
xmin = tmpIndex[0];
}
if (ymin > tmpIndex[1])
{
ymin = tmpIndex[1];
}
if (zmin > tmpIndex[2])
{
zmin = tmpIndex[2];
}
if (xmax < tmpIndex[0])
{
xmax = tmpIndex[0];
}
if (ymax < tmpIndex[1])
{
ymax = tmpIndex[1];
}
if (zmax < tmpIndex[2])
{
zmax = tmpIndex[2];
}
}
// put the found coordinates into Index-Points
minPointInIndexCoordinates[0] = xmin;
minPointInIndexCoordinates[1] = ymin;
minPointInIndexCoordinates[2] = zmin;
maxPointInIndexCoordinates[0] = xmax;
maxPointInIndexCoordinates[1] = ymax;
maxPointInIndexCoordinates[2] = zmax;
// and transform them into world-coordinates
m_ReferenceImage->TransformIndexToPhysicalPoint(minPointInIndexCoordinates, minPointInWorldCoordinates);
m_ReferenceImage->TransformIndexToPhysicalPoint(maxPointInIndexCoordinates, maxPointInWorldCoordinates);
}
diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
index 015595cda7..f939d7a447 100644
--- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
+++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
@@ -1,1402 +1,1406 @@
/*============================================================================
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 <mitkSurfaceInterpolationController.h>
#include <mitkCreateDistanceImageFromSurfaceFilter.h>
#include <mitkComputeContourSetNormalsFilter.h>
#include <mitkImageAccessByItk.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkImageTimeSelector.h>
#include <mitkImageToSurfaceFilter.h>
#include <mitkLabelSetImage.h>
#include <mitkMemoryUtilities.h>
#include <mitkNodePredicateDataUID.h>
#include <mitkNodePredicateProperty.h>
#include <mitkPlanarCircle.h>
#include <mitkPlaneGeometry.h>
#include <mitkReduceContourSetFilter.h>
#include <vtkFieldData.h>
#include <vtkMath.h>
#include <vtkPolygon.h>
// Check whether the given contours are coplanar
bool ContoursCoplanar(mitk::SurfaceInterpolationController::ContourPositionInformation leftHandSide,
mitk::SurfaceInterpolationController::ContourPositionInformation rightHandSide)
{
// Here we check two things:
// 1. Whether the normals of both contours are at least parallel
// 2. Whether both contours lie in the same plane
// Check for coplanarity:
// a. Span a vector between two points one from each contour
// b. Calculate dot product for the vector and one of the normals
// c. If the dot is zero the two vectors are orthogonal and the contours are coplanar
double vec[3];
vec[0] = leftHandSide.ContourPoint[0] - rightHandSide.ContourPoint[0];
vec[1] = leftHandSide.ContourPoint[1] - rightHandSide.ContourPoint[1];
vec[2] = leftHandSide.ContourPoint[2] - rightHandSide.ContourPoint[2];
double n[3];
n[0] = rightHandSide.ContourNormal[0];
n[1] = rightHandSide.ContourNormal[1];
n[2] = rightHandSide.ContourNormal[2];
double dot = vtkMath::Dot(n, vec);
double n2[3];
n2[0] = leftHandSide.ContourNormal[0];
n2[1] = leftHandSide.ContourNormal[1];
n2[2] = leftHandSide.ContourNormal[2];
// The normals of both contours have to be parallel but not of the same orientation
double lengthLHS = leftHandSide.ContourNormal.GetNorm();
double lengthRHS = rightHandSide.ContourNormal.GetNorm();
double dot2 = vtkMath::Dot(n, n2);
bool contoursParallel = mitk::Equal(fabs(lengthLHS * lengthRHS), fabs(dot2), 0.001);
if (mitk::Equal(dot, 0.0, 0.001) && contoursParallel)
return true;
else
return false;
}
mitk::SurfaceInterpolationController::ContourPositionInformation CreateContourPositionInformation(
mitk::Surface::Pointer contour, const mitk::PlaneGeometry* planeGeometry)
{
mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo;
contourInfo.Contour = contour;
mitk::ScalarType n[3];
vtkPolygon::ComputeNormal(contour->GetVtkPolyData()->GetPoints(), n);
contourInfo.ContourNormal = n;
contourInfo.Pos = -1;
contourInfo.TimeStep = std::numeric_limits<long unsigned int>::max();
contourInfo.Plane = const_cast<mitk::PlaneGeometry *>(planeGeometry);
auto contourIntArray = vtkIntArray::SafeDownCast( contour->GetVtkPolyData()->GetFieldData()->GetAbstractArray(0) );
if (contourIntArray->GetSize() < 2)
{
MITK_ERROR << "In CreateContourPositionInformation. The contourIntArray is empty.";
}
contourInfo.LabelValue = contourIntArray->GetValue(0);
contourInfo.LayerValue = contourIntArray->GetValue(1);
if (contourIntArray->GetSize() >= 3)
{
contourInfo.TimeStep = contourIntArray->GetValue(2);
}
contourInfo.SliceIndex = 0;
return contourInfo;
};
mitk::SurfaceInterpolationController::SurfaceInterpolationController()
: m_SelectedSegmentation(nullptr),
m_CurrentTimePoint(0.),
m_ContourIndex(0),
m_ContourPosIndex(0),
m_NumberOfLayersInCurrentSegmentation(0),
m_PreviousActiveLabelValue(0),
m_CurrentActiveLabelValue(0),
m_PreviousLayerIndex(0),
m_CurrentLayerIndex(0)
{
m_DistanceImageSpacing = 0.0;
m_ReduceFilter = ReduceContourSetFilter::New();
m_NormalsFilter = ComputeContourSetNormalsFilter::New();
m_InterpolateSurfaceFilter = CreateDistanceImageFromSurfaceFilter::New();
// m_TimeSelector = ImageTimeSelector::New();
m_ReduceFilter->SetUseProgressBar(false);
// m_ReduceFilter->SetProgressStepSize(1);
m_NormalsFilter->SetUseProgressBar(true);
m_NormalsFilter->SetProgressStepSize(1);
m_InterpolateSurfaceFilter->SetUseProgressBar(true);
m_InterpolateSurfaceFilter->SetProgressStepSize(7);
m_Contours = Surface::New();
m_PolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
m_PolyData->SetPoints(points);
m_NumberOfConnectionsAdded = 0;
m_InterpolationResult = nullptr;
m_CurrentNumberOfReducedContours = 0;
}
mitk::SurfaceInterpolationController::~SurfaceInterpolationController()
{
// Removing all observers
this->RemoveObservers();
}
void mitk::SurfaceInterpolationController::RemoveObservers()
{
// Removing all observers
auto dataIter = m_SegmentationObserverTags.begin();
for (; dataIter != m_SegmentationObserverTags.end(); ++dataIter)
{
(*dataIter).first->RemoveObserver((*dataIter).second);
}
m_SegmentationObserverTags.clear();
}
mitk::SurfaceInterpolationController *mitk::SurfaceInterpolationController::GetInstance()
{
static mitk::SurfaceInterpolationController::Pointer m_Instance;
if (m_Instance.IsNull())
{
m_Instance = SurfaceInterpolationController::New();
}
return m_Instance;
}
void mitk::SurfaceInterpolationController::AddNewContour(mitk::Surface::Pointer newContour)
{
if (newContour->GetVtkPolyData()->GetNumberOfPoints() > 0)
{
ContourPositionInformation contourInfo = CreateContourPositionInformation(newContour, nullptr);
this->AddToInterpolationPipeline(contourInfo);
this->Modified();
}
}
void mitk::SurfaceInterpolationController::AddNewContours(const std::vector<mitk::Surface::Pointer>& newContours,
std::vector<const mitk::PlaneGeometry*>& contourPlanes,
bool reinitializationAction)
{
if (nullptr == m_SelectedSegmentation) return;
if (newContours.size() != contourPlanes.size())
{
MITK_ERROR << "SurfaceInterpolationController::AddNewContours. contourPlanes and newContours are not of the same size.";
}
for (size_t i = 0; i < newContours.size(); ++i)
{
const auto &newContour = newContours[i];
const mitk::PlaneGeometry * planeGeometry = contourPlanes[i];
if (newContour->GetVtkPolyData()->GetNumberOfPoints() > 0)
{
auto contourInfo = CreateContourPositionInformation(newContour, planeGeometry);
if (!reinitializationAction)
{
contourInfo.ContourPoint = this->ComputeInteriorPointOfContour(contourInfo,
dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation) );
}
else
{
auto vtkPolyData = contourInfo.Contour->GetVtkPolyData();
auto pointVtkArray = vtkDoubleArray::SafeDownCast(vtkPolyData->GetFieldData()->GetAbstractArray(1));
mitk::ScalarType *ptArr = new mitk::ScalarType[3];
for (int i = 0; i < pointVtkArray->GetSize(); ++i)
ptArr[i] = pointVtkArray->GetValue(i);
mitk::Point3D pt3D;
pt3D.FillPoint(ptArr);
contourInfo.ContourPoint = pt3D;
}
this->AddToInterpolationPipeline(contourInfo, reinitializationAction);
}
}
this->Modified();
}
mitk::DataNode* mitk::SurfaceInterpolationController::GetSegmentationImageNode()
{
DataNode* segmentationNode = nullptr;
mitk::NodePredicateDataUID::Pointer dataUIDPredicate = mitk::NodePredicateDataUID::New(m_SelectedSegmentation->GetUID());
auto dataNodeObjects = m_DataStorage->GetSubset(dataUIDPredicate);
if (dataNodeObjects->Size() != 0)
{
for (auto it = dataNodeObjects->Begin(); it != dataNodeObjects->End(); ++it)
{
segmentationNode = it->Value();
}
}
else
{
MITK_ERROR << "Unable to find the labelSetImage with the desired UID.";
}
return segmentationNode;
}
void mitk::SurfaceInterpolationController::AddPlaneGeometryNodeToDataStorage(const ContourPositionInformation& contourInfo)
{
auto planeGeometry = contourInfo.Plane;
auto planeGeometryData = mitk::PlanarCircle::New();
planeGeometryData->SetPlaneGeometry(planeGeometry);
mitk::Point2D p1;
planeGeometry->Map(planeGeometry->GetCenter(), p1);
planeGeometryData->PlaceFigure(p1);
planeGeometryData->SetCurrentControlPoint(p1);
planeGeometryData->SetProperty("initiallyplaced", mitk::BoolProperty::New(true));
if (planeGeometry)
{
auto segmentationNode = this->GetSegmentationImageNode();
auto isContourPlaneGeometry = mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
m_DataStorage->GetDerivations(segmentationNode, isContourPlaneGeometry);
auto contourFound = false;
// Go through the pre-existing contours and check if the contour position matches them.
for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
{
auto layerID = dynamic_cast<mitk::UIntProperty *>(it->Value()->GetProperty("layerID"))->GetValue();
auto labelID = dynamic_cast<mitk::UShortProperty *>(it->Value()->GetProperty("labelID"))->GetValue();
auto posID = dynamic_cast<mitk::IntProperty *>(it->Value()->GetProperty("position"))->GetValue();
bool sameLayer = (layerID == contourInfo.LayerValue);
bool sameLabel = (labelID == contourInfo.LabelValue);
bool samePos = (posID == contourInfo.Pos);
if (samePos & sameLabel & sameLayer)
{
contourFound = true;
it->Value()->SetData(planeGeometryData);
break;
}
}
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
MITK_ERROR << "Invalid time point requested in AddPlaneGeometryNodeToDataStorage.";
return;
}
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
// Go through the contourPlaneGeometry Data and add the segmentationNode to it.
if (!contourFound)
{
std::string contourName = "contourPlane " + std::to_string(m_ContourIndex);
auto contourPlaneGeometryDataNode = mitk::DataNode::New();
contourPlaneGeometryDataNode->SetData(planeGeometryData);
// No need to change properties
contourPlaneGeometryDataNode->SetProperty("helper object", mitk::BoolProperty::New(false));
contourPlaneGeometryDataNode->SetProperty("hidden object", mitk::BoolProperty::New(true));
contourPlaneGeometryDataNode->SetProperty("isContourPlaneGeometry", mitk::BoolProperty::New(true));
contourPlaneGeometryDataNode->SetVisibility(false);
// Need to change properties
contourPlaneGeometryDataNode->SetProperty("name", mitk::StringProperty::New(contourName) );
contourPlaneGeometryDataNode->SetProperty("layerID", mitk::UIntProperty::New(contourInfo.LayerValue));
contourPlaneGeometryDataNode->SetProperty("labelID", mitk::UShortProperty::New(contourInfo.LabelValue));
contourPlaneGeometryDataNode->SetProperty("position", mitk::IntProperty::New(contourInfo.Pos));
contourPlaneGeometryDataNode->SetProperty("timeStep", mitk::IntProperty::New(currentTimeStep));
contourPlaneGeometryDataNode->SetProperty("px", mitk::DoubleProperty::New(contourInfo.ContourPoint[0]));
contourPlaneGeometryDataNode->SetProperty("py", mitk::DoubleProperty::New(contourInfo.ContourPoint[1]));
contourPlaneGeometryDataNode->SetProperty("pz", mitk::DoubleProperty::New(contourInfo.ContourPoint[2]));
m_DataStorage->Add(contourPlaneGeometryDataNode, segmentationNode);
}
}
}
void mitk::SurfaceInterpolationController::AddToInterpolationPipeline(ContourPositionInformation& contourInfo, bool reinitializationAction)
{
if (!m_SelectedSegmentation)
return;
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
return;
}
// Get current time step either from the
auto GetCurrentTimeStep = [=](ContourPositionInformation contourInfo)
{
if (reinitializationAction)
{
return contourInfo.TimeStep;
}
return static_cast<size_t>(m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint));
};
const auto currentTimeStep = GetCurrentTimeStep(contourInfo);
auto GetContourLayerID = [=](ContourPositionInformation contourInfo)
{
unsigned int currentLayerID;
if(reinitializationAction)
{
if (contourInfo.LayerValue == std::numeric_limits<unsigned int>::max())
{
MITK_ERROR << "In mitk::SurfaceInterpolationController::AddToInterpolationPipeline. Problem in finding layerID";
}
currentLayerID = contourInfo.LayerValue;
}
else
{
try
{
currentLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
}
catch (const std::exception& e)
{
MITK_ERROR << "Unable to cast image to LabelSetImage. " << e.what() << '\n';
}
}
return currentLayerID;
};
unsigned int currentLayerID = GetContourLayerID(contourInfo);
ContourPositionInformationVec3D &currentImageContours = m_ListOfContours.at(m_SelectedSegmentation);
ContourPositionInformationVec2D &currentTimeStepContoursList = currentImageContours.at(currentTimeStep);
ContourPositionInformationList &currentContourList = currentTimeStepContoursList.at(currentLayerID);
int replacementIndex = -1;
int pos = -1;
mitk::Surface* newContour = contourInfo.Contour;
for (size_t i = 0; i < currentContourList.size(); i++)
{
auto& contourFromList = currentContourList.at(i);
bool contoursAreCoplanar = ContoursCoplanar(contourInfo, contourFromList);
bool contoursHaveSameLabel = contourInfo.LabelValue == contourFromList.LabelValue;
// Coplanar contours have the same "pos".
if (contoursAreCoplanar)
{
pos = contourFromList.Pos;
if (contoursHaveSameLabel)
{
replacementIndex = i;
}
}
}
// The current contour has the same label and position as the current slice and a replacement is done.
if (replacementIndex != -1)
{
contourInfo.Pos = pos;
m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).at(replacementIndex) = contourInfo;
if (!reinitializationAction)
{
this->AddPlaneGeometryNodeToDataStorage(contourInfo);
}
return;
}
// Case that there is no contour in the current slice with the current label
if (pos == -1)
pos = m_ContourPosIndex++;
m_ContourIndex++;
contourInfo.Pos = pos;
m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).push_back(contourInfo);
if (contourInfo.Plane == nullptr)
{
MITK_ERROR << "contourInfo plane is null.";
}
if (!reinitializationAction)
{
this->AddPlaneGeometryNodeToDataStorage(contourInfo);
}
if (newContour->GetVtkPolyData()->GetNumberOfPoints() == 0)
{
this->RemoveContour(contourInfo);
if (m_ContourIndex > 0)
m_ContourIndex--;
if (m_ContourIndex > 0)
m_ContourIndex--;
}
}
bool mitk::SurfaceInterpolationController::RemoveContour(ContourPositionInformation contourInfo)
{
if (!m_SelectedSegmentation)
{
return false;
}
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
return false;
}
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
unsigned int currentLayerID = 0;
try
{
currentLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
}
catch (const std::exception& e)
{
MITK_ERROR << e.what() << '\n';
}
auto it = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).begin();
while (it != m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).end())
{
const ContourPositionInformation &currentContour = (*it);
if (ContoursCoplanar(currentContour, contourInfo))
{
m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).erase(it);
this->ReinitializeInterpolation();
return true;
}
++it;
}
return false;
}
const mitk::Surface *mitk::SurfaceInterpolationController::GetContour(const ContourPositionInformation &contourInfo)
{
if (!m_SelectedSegmentation)
{
return nullptr;
}
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
return nullptr;
}
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
const auto activeLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
const auto &contourList = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(activeLayerID);
for (auto &currentContour : contourList)
{
if (ContoursCoplanar(contourInfo, currentContour))
{
return currentContour.Contour;
}
}
return nullptr;
}
unsigned int mitk::SurfaceInterpolationController::GetNumberOfContours()
{
if (!m_SelectedSegmentation)
{
return -1;
}
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
return -1;
}
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
auto contourDoubleList = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep);
unsigned int numContours = 0;
for (auto& contourList : contourDoubleList)
{
numContours += contourList.size();
}
return numContours;
}
void mitk::SurfaceInterpolationController::AddActiveLabelContoursForInterpolation(mitk::Label::PixelType activeLabel)
{
this->ReinitializeInterpolation();
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
return;
}
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
unsigned int currentLayerID = 0;
try
{
currentLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
}
catch (const std::exception& e)
{
MITK_ERROR << e.what() << '\n';
}
ContourPositionInformationVec3D &currentImageContours = m_ListOfContours.at(m_SelectedSegmentation);
if (currentImageContours.size() <= currentTimeStep)
{
MITK_INFO << "Contours for current time step don't exist.";
return;
}
ContourPositionInformationVec2D &currentTimeStepContoursList = currentImageContours.at(currentTimeStep);
if (currentTimeStepContoursList.size() <= currentLayerID)
{
MITK_INFO << "Contours for current layer don't exist.";
return;
}
ContourPositionInformationList &currentContours = currentTimeStepContoursList.at(currentLayerID);
for (size_t i = 0; i < currentContours.size(); ++i)
{
if (currentContours.at(i).LabelValue == activeLabel)
{
m_ListOfInterpolationSessions.at(m_SelectedSegmentation).at(currentTimeStep).push_back(currentContours.at(i));
m_ReduceFilter->SetInput(m_ListOfInterpolationSessions.at(m_SelectedSegmentation).at(currentTimeStep).size()-1, currentContours.at(i).Contour);
}
}
}
void mitk::SurfaceInterpolationController::Interpolate()
{
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
MITK_WARN << "No interpolation possible, currently selected timepoint is not in the time bounds of currently selected segmentation. Time point: " << m_CurrentTimePoint;
m_InterpolationResult = nullptr;
return;
}
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
m_ReduceFilter->Update();
m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs();
if (m_CurrentNumberOfReducedContours == 1)
{
vtkPolyData *tmp = m_ReduceFilter->GetOutput(0)->GetVtkPolyData();
if (tmp == nullptr)
{
m_CurrentNumberOfReducedContours = 0;
}
}
// We use the timeSelector to get the segmentation image for the current segmentation.
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(m_SelectedSegmentation);
timeSelector->SetTimeNr(currentTimeStep);
timeSelector->SetChannelNr(0);
timeSelector->Update();
mitk::Image::Pointer refSegImage = timeSelector->GetOutput();
itk::ImageBase<3>::Pointer itkImage = itk::ImageBase<3>::New();
AccessFixedDimensionByItk_1(refSegImage, GetImageBase, 3, itkImage);
m_NormalsFilter->SetSegmentationBinaryImage(refSegImage);
for (size_t i = 0; i < m_CurrentNumberOfReducedContours; ++i)
{
mitk::Surface::Pointer reducedContour = m_ReduceFilter->GetOutput(i);
reducedContour->DisconnectPipeline();
m_NormalsFilter->SetInput(i, reducedContour);
m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i));
}
if (m_CurrentNumberOfReducedContours < 2)
{
// If no interpolation is possible reset the interpolation result
MITK_INFO << "Interpolation impossible: not enough contours.";
m_InterpolationResult = nullptr;
return;
}
// Setting up progress bar
mitk::ProgressBar::GetInstance()->AddStepsToDo(10);
// create a surface from the distance-image
mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New();
imageToSurfaceFilter->SetInput(m_InterpolateSurfaceFilter->GetOutput());
imageToSurfaceFilter->SetThreshold(0);
imageToSurfaceFilter->SetSmooth(true);
imageToSurfaceFilter->SetSmoothIteration(1);
imageToSurfaceFilter->Update();
mitk::Surface::Pointer interpolationResult = mitk::Surface::New();
interpolationResult->Expand(m_SelectedSegmentation->GetTimeSteps());
auto geometry = m_SelectedSegmentation->GetTimeGeometry()->Clone();
geometry->ReplaceTimeStepGeometries(mitk::Geometry3D::New());
interpolationResult->SetTimeGeometry(geometry);
interpolationResult->SetVtkPolyData(imageToSurfaceFilter->GetOutput()->GetVtkPolyData(), currentTimeStep);
m_InterpolationResult = interpolationResult;
m_DistanceImageSpacing = m_InterpolateSurfaceFilter->GetDistanceImageSpacing();
auto* contoursGeometry = static_cast<mitk::ProportionalTimeGeometry*>(m_Contours->GetTimeGeometry());
auto timeBounds = geometry->GetTimeBounds(currentTimeStep);
contoursGeometry->SetFirstTimePoint(timeBounds[0]);
contoursGeometry->SetStepDuration(timeBounds[1] - timeBounds[0]);
// Last progress step
mitk::ProgressBar::GetInstance()->Progress(20);
m_InterpolationResult->DisconnectPipeline();
}
mitk::Surface::Pointer mitk::SurfaceInterpolationController::GetInterpolationResult()
{
return m_InterpolationResult;
}
mitk::Surface *mitk::SurfaceInterpolationController::GetContoursAsSurface()
{
return m_Contours;
}
void mitk::SurfaceInterpolationController::SetDataStorage(DataStorage::Pointer ds)
{
m_DataStorage = ds;
}
void mitk::SurfaceInterpolationController::SetMinSpacing(double minSpacing)
{
m_ReduceFilter->SetMinSpacing(minSpacing);
}
void mitk::SurfaceInterpolationController::SetMaxSpacing(double maxSpacing)
{
m_ReduceFilter->SetMaxSpacing(maxSpacing);
m_NormalsFilter->SetMaxSpacing(maxSpacing);
}
void mitk::SurfaceInterpolationController::SetDistanceImageVolume(unsigned int distImgVolume)
{
m_InterpolateSurfaceFilter->SetDistanceImageVolume(distImgVolume);
}
mitk::Image::Pointer mitk::SurfaceInterpolationController::GetCurrentSegmentation()
{
return m_SelectedSegmentation;
}
mitk::Image *mitk::SurfaceInterpolationController::GetImage()
{
return m_InterpolateSurfaceFilter->GetOutput();
}
double mitk::SurfaceInterpolationController::EstimatePortionOfNeededMemory()
{
double numberOfPointsAfterReduction = m_ReduceFilter->GetNumberOfPointsAfterReduction() * 3;
double sizeOfPoints = pow(numberOfPointsAfterReduction, 2) * sizeof(double);
double totalMem = mitk::MemoryUtilities::GetTotalSizeOfPhysicalRam();
double percentage = sizeOfPoints / totalMem;
return percentage;
}
unsigned int mitk::SurfaceInterpolationController::GetNumberOfInterpolationSessions()
{
return m_ListOfInterpolationSessions.size();
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::SurfaceInterpolationController::GetImageBase(itk::Image<TPixel, VImageDimension> *input,
itk::ImageBase<3>::Pointer &result)
{
result->Graft(input);
}
void mitk::SurfaceInterpolationController::SetCurrentSegmentationInterpolationList(mitk::Image::Pointer segmentation)
{
this->SetCurrentInterpolationSession(segmentation);
}
void mitk::SurfaceInterpolationController::SetCurrentInterpolationSession(mitk::Image::Pointer currentSegmentationImage)
{
if (currentSegmentationImage.GetPointer() == m_SelectedSegmentation)
{
return;
}
if (currentSegmentationImage.IsNull())
{
m_SelectedSegmentation = nullptr;
return;
}
m_SelectedSegmentation = currentSegmentationImage.GetPointer();
try
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
auto it = m_ListOfContours.find(currentSegmentationImage.GetPointer());
// If the session does not exist yet create a new ContourPositionPairList otherwise reinitialize the interpolation
// pipeline
if (it == m_ListOfContours.end())
{
ContourPositionInformationVec3D newList;
auto numTimeSteps = labelSetImage->GetTimeGeometry()->CountTimeSteps();
for (size_t t = 0; t < numTimeSteps; ++t)
{
auto twoDList = ContourPositionInformationVec2D();
auto contourList = ContourPositionInformationList();
twoDList.push_back(contourList);
newList.push_back(twoDList);
}
m_ListOfContours[m_SelectedSegmentation] = newList;
m_InterpolationResult = nullptr;
m_CurrentNumberOfReducedContours = 0;
auto command = itk::MemberCommand<SurfaceInterpolationController>::New();
command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted);
m_SegmentationObserverTags[m_SelectedSegmentation] = labelSetImage->AddObserver(itk::DeleteEvent(), command);
m_NumberOfLayersInCurrentSegmentation = labelSetImage->GetNumberOfLayers();
}
// auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
auto numLayersInSelectedSegmentation = labelSetImage->GetNumberOfLayers();
// Maybe this has to change.
for (size_t layerID = 0; layerID < numLayersInSelectedSegmentation; ++layerID)
{
this->AddLabelSetConnection(layerID);
}
}
catch (const std::exception &e)
{
MITK_ERROR << "Unable to cast image as LabelSetImage";
}
auto it2 = m_ListOfInterpolationSessions.find(currentSegmentationImage.GetPointer());
if (it2 == m_ListOfInterpolationSessions.end())
{
ContourPositionInformationVec2D newList;
m_ListOfInterpolationSessions[m_SelectedSegmentation] = newList;
m_InterpolationResult = nullptr;
m_CurrentNumberOfReducedContours = 0;
}
this->ReinitializeInterpolation();
}
bool mitk::SurfaceInterpolationController::ReplaceInterpolationSession(mitk::Image::Pointer oldSession,
mitk::Image::Pointer newSession)
{
if (oldSession.IsNull() || newSession.IsNull())
return false;
if (oldSession.GetPointer() == newSession.GetPointer())
return false;
if (!mitk::Equal(*(oldSession->GetGeometry()), *(newSession->GetGeometry()), mitk::eps, false))
return false;
auto it = m_ListOfInterpolationSessions.find(oldSession.GetPointer());
if (it == m_ListOfInterpolationSessions.end())
return false;
if (!newSession->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
MITK_WARN << "Interpolation session cannot be replaced. Currently selected timepoint is not in the time bounds of the new session. Time point: " << m_CurrentTimePoint;
return false;
}
ContourPositionInformationVec2D oldList = (*it).second;
m_ListOfInterpolationSessions[newSession.GetPointer()] = oldList;
itk::MemberCommand<SurfaceInterpolationController>::Pointer command =
itk::MemberCommand<SurfaceInterpolationController>::New();
command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted);
m_SegmentationObserverTags[newSession] = newSession->AddObserver(itk::DeleteEvent(), command);
if (m_SelectedSegmentation == oldSession)
m_SelectedSegmentation = newSession;
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(m_SelectedSegmentation);
timeSelector->SetTimeNr(currentTimeStep);
timeSelector->SetChannelNr(0);
timeSelector->Update();
mitk::Image::Pointer refSegImage = timeSelector->GetOutput();
m_NormalsFilter->SetSegmentationBinaryImage(refSegImage);
this->RemoveInterpolationSession(oldSession);
return true;
}
void mitk::SurfaceInterpolationController::RemoveSegmentationFromContourList(mitk::Image *segmentation)
{
this->RemoveInterpolationSession(segmentation);
}
void mitk::SurfaceInterpolationController::RemoveInterpolationSession(mitk::Image::Pointer segmentationImage)
{
if (segmentationImage)
{
if (m_SelectedSegmentation == segmentationImage)
{
m_NormalsFilter->SetSegmentationBinaryImage(nullptr);
m_SelectedSegmentation = nullptr;
}
m_ListOfInterpolationSessions.erase(segmentationImage);
m_ListOfContours.erase(segmentationImage);
// Remove observer
auto pos = m_SegmentationObserverTags.find(segmentationImage);
if (pos != m_SegmentationObserverTags.end())
{
segmentationImage->RemoveObserver((*pos).second);
m_SegmentationObserverTags.erase(pos);
}
}
}
void mitk::SurfaceInterpolationController::RemoveAllInterpolationSessions()
{
// Removing all observers
auto dataIter = m_SegmentationObserverTags.begin();
while (dataIter != m_SegmentationObserverTags.end())
{
mitk::Image *image = (*dataIter).first;
image->RemoveObserver((*dataIter).second);
++dataIter;
}
m_SegmentationObserverTags.clear();
m_SelectedSegmentation = nullptr;
m_ListOfInterpolationSessions.clear();
m_ListOfContours.clear();
}
template <unsigned int VImageDimension = 3>
std::vector<mitk::Label::PixelType> GetPixelValuesPresentInImage(mitk::LabelSetImage* labelSetImage)
{
mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage);
std::vector<mitk::Label::PixelType> pixelsPresent;
std::size_t numberOfPixels = 1;
for (int dim = 0; dim < static_cast<int>(VImageDimension); ++dim)
numberOfPixels *= static_cast<std::size_t>(readAccessor.GetDimension(dim));
auto src = readAccessor.GetData();
for (std::size_t i = 0; i < numberOfPixels; ++i)
{
mitk::Label::PixelType pixelVal = *(src + i);
if ( (std::find(pixelsPresent.begin(), pixelsPresent.end(), pixelVal) == pixelsPresent.end()) && (pixelVal != 0) )
{
pixelsPresent.push_back(pixelVal);
}
}
return pixelsPresent;
}
void mitk::SurfaceInterpolationController::RemoveContours(mitk::Label::PixelType label,
unsigned int timeStep,
unsigned int layerID)
{
auto isContourEqualToLabelValue = [label] (ContourPositionInformation& contour) -> bool
{
return (contour.LabelValue == label);
};
ContourPositionInformationVec3D &currentImageContours = m_ListOfContours.at(m_SelectedSegmentation);
ContourPositionInformationList &currentContourList = currentImageContours.at(timeStep).at(layerID);
unsigned int numContoursBefore = currentContourList.size();
auto it = std::remove_if(currentContourList.begin(), currentContourList.end(), isContourEqualToLabelValue);
currentContourList.erase(it, currentContourList.end());
unsigned int numContoursAfter = currentContourList.size();
unsigned int numContours = numContoursAfter - numContoursBefore;
m_ContourIndex -= numContours;
}
void mitk::SurfaceInterpolationController::OnSegmentationDeleted(const itk::Object *caller,
const itk::EventObject & /*event*/)
{
auto *tempImage = dynamic_cast<mitk::Image *>(const_cast<itk::Object *>(caller));
if (tempImage)
{
if (m_SelectedSegmentation == tempImage)
{
m_NormalsFilter->SetSegmentationBinaryImage(nullptr);
m_SelectedSegmentation = nullptr;
}
m_SegmentationObserverTags.erase(tempImage);
m_ListOfContours.erase(tempImage);
m_ListOfInterpolationSessions.erase(tempImage);
}
}
void mitk::SurfaceInterpolationController::ReinitializeInterpolation()
{
// If session has changed reset the pipeline
m_ReduceFilter->Reset();
m_NormalsFilter->Reset();
m_InterpolateSurfaceFilter->Reset();
// Empty out the listOfInterpolationSessions
m_ListOfInterpolationSessions[m_SelectedSegmentation].clear();
itk::ImageBase<3>::Pointer itkImage = itk::ImageBase<3>::New();
if (m_SelectedSegmentation)
{
if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
{
MITK_WARN << "Interpolation cannot be reinitialized. Currently selected timepoint is not in the time bounds of the currently selected segmentation. Time point: " << m_CurrentTimePoint;
return;
}
const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
// Set reference image for interpolation surface filter
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(m_SelectedSegmentation);
timeSelector->SetTimeNr(currentTimeStep);
timeSelector->SetChannelNr(0);
timeSelector->Update();
mitk::Image::Pointer refSegImage = timeSelector->GetOutput();
AccessFixedDimensionByItk_1(refSegImage, GetImageBase, 3, itkImage);
m_InterpolateSurfaceFilter->SetReferenceImage(itkImage.GetPointer());
// Resize listofinterpolationsessions and listofcontours to numTimeSteps
unsigned int numTimeSteps = m_SelectedSegmentation->GetTimeSteps();
unsigned int size = m_ListOfInterpolationSessions[m_SelectedSegmentation].size();
if (size != numTimeSteps)
{
m_ListOfInterpolationSessions.at(m_SelectedSegmentation).resize(numTimeSteps);
}
}
}
void mitk::SurfaceInterpolationController::AddLabelSetConnection(unsigned int layerID)
{
if (m_SelectedSegmentation != nullptr)
{
try
{
auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
auto previousLayerID = workingImage->GetActiveLayer();
workingImage->SetActiveLayer(layerID);
auto activeLabelSet = workingImage->GetLabelSet(layerID);
+
+ if (activeLabelSet == nullptr)
+ return;
+
activeLabelSet->RemoveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
activeLabelSet->ActiveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
this, &mitk::SurfaceInterpolationController::OnActiveLabel);
workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
this, &mitk::SurfaceInterpolationController::OnLayerChanged);
m_NumberOfConnectionsAdded += 1;
workingImage->SetActiveLayer(previousLayerID);
}
catch(const std::exception& e)
{
MITK_ERROR << e.what() << '\n';
}
}
}
void mitk::SurfaceInterpolationController::AddLabelSetConnection()
{
if (m_SelectedSegmentation != nullptr)
{
try
{
auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
auto activeLabelSet = workingImage->GetActiveLabelSet();
+
+ if (activeLabelSet == nullptr)
+ return;
+
activeLabelSet->RemoveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
this, &mitk::SurfaceInterpolationController::OnActiveLabel);
workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
this, &mitk::SurfaceInterpolationController::OnLayerChanged);
m_NumberOfConnectionsAdded += 1;
}
catch(const std::exception& e)
{
MITK_ERROR << e.what() << '\n';
}
}
}
void mitk::SurfaceInterpolationController::RemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID)
{
labelSetImage->SetActiveLayer(layerID);
labelSetImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
// labelSetImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
// this, &mitk::SurfaceInterpolationController::OnActiveLabel);
labelSetImage->AfterChangeLayerEvent -= mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
this, &mitk::SurfaceInterpolationController::OnLayerChanged);
m_NumberOfConnectionsAdded -= 1;
}
void mitk::SurfaceInterpolationController::RemoveLabelSetConnection()
{
if (m_SelectedSegmentation != nullptr)
{
try
{
auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
this, &mitk::SurfaceInterpolationController::OnActiveLabel);
workingImage->AfterChangeLayerEvent -= mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
this, &mitk::SurfaceInterpolationController::OnLayerChanged);
}
catch (const std::exception& e)
{
std::cerr << e.what() << '\n';
}
}
}
void mitk::SurfaceInterpolationController::OnRemoveLabel(mitk::Label::PixelType /*removedLabelValue*/)
{
if (m_SelectedSegmentation != nullptr)
{
auto numTimeSteps = m_SelectedSegmentation->GetTimeGeometry()->CountTimeSteps();
try
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
auto currentLayerID = labelSetImage->GetActiveLayer();
for(unsigned int t = 0; t < numTimeSteps; ++t)
{
this->RemoveContours(m_PreviousActiveLabelValue,t,currentLayerID);
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
}
}
void mitk::SurfaceInterpolationController::OnActiveLabel(mitk::Label::PixelType newActiveLabelValue)
{
m_PreviousActiveLabelValue = m_CurrentActiveLabelValue;
m_CurrentActiveLabelValue = newActiveLabelValue;
}
unsigned int mitk::SurfaceInterpolationController::GetNumberOfLayersInCurrentSegmentation() const
{
return m_NumberOfLayersInCurrentSegmentation;
}
void mitk::SurfaceInterpolationController::SetNumberOfLayersInCurrentSegmentation(unsigned int numLayers)
{
m_NumberOfLayersInCurrentSegmentation = numLayers;
}
void mitk::SurfaceInterpolationController::OnAddLayer()
{
assert(m_SelectedSegmentation != nullptr);
auto& contoursForSegmentation = m_ListOfContours.at(m_SelectedSegmentation);
// Push an information list for each time step.
for(size_t t = 0; t < contoursForSegmentation.size(); ++t)
{
contoursForSegmentation.at(t).push_back( ContourPositionInformationList() );
}
}
void mitk::SurfaceInterpolationController::OnRemoveLayer()
{
assert(m_SelectedSegmentation != nullptr);
auto& contoursForSegmentation = m_ListOfContours.at(m_SelectedSegmentation);
// Erase the layers in each of the time steps.
// The previous layer is removed
for (size_t t = 0; t < contoursForSegmentation.size(); ++t)
{
assert(m_PreviousLayerIndex < contoursForSegmentation.at(t).size());
auto& contoursAtTimeStep = contoursForSegmentation.at(t);
for (size_t c = m_CurrentLayerIndex+1; c < contoursAtTimeStep.size(); ++c)
{
auto& contoursInCurrentLayer = contoursAtTimeStep.at(c);
for (auto& contour : contoursInCurrentLayer)
{
contour.LayerValue = contour.LayerValue - 1;
}
}
}
for (size_t t = 0; t < contoursForSegmentation.size(); ++t)
{
assert (m_CurrentLayerIndex < contoursForSegmentation.at(t).size());
contoursForSegmentation.at(t).erase(contoursForSegmentation.at(t).begin() + m_PreviousLayerIndex);
}
-
this->Modified();
}
void mitk::SurfaceInterpolationController::OnLayerChanged()
{
auto currentLayer = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
m_PreviousLayerIndex = m_CurrentLayerIndex;
m_CurrentLayerIndex = currentLayer;
}
-mitk::SurfaceInterpolationController::ContourPositionInformationList& mitk::SurfaceInterpolationController::GetContours(unsigned int timeStep, unsigned int layerID)
+mitk::SurfaceInterpolationController::ContourPositionInformationList* mitk::SurfaceInterpolationController::GetContours(unsigned int timeStep, unsigned int layerID)
{
if (m_SelectedSegmentation == nullptr)
- {
- MITK_ERROR << "Invalid segmentation from mitk::SurfaceInterpolationController::GetContours";
- }
+ return nullptr;
+
if (timeStep >= m_ListOfContours.at(m_SelectedSegmentation).size())
- {
- MITK_ERROR << "Invalid timeStep from mitk::SurfaceInterpolationController::GetContours";
- }
+ return nullptr;
+
if (layerID >= m_ListOfContours.at(m_SelectedSegmentation).at(timeStep).size())
- {
- MITK_ERROR << "Invalid timeStep from mitk::SurfaceInterpolationController::GetContours";
- }
- return m_ListOfContours.at(m_SelectedSegmentation).at(timeStep).at(layerID);
+ return nullptr;
+
+ return &m_ListOfContours[m_SelectedSegmentation][timeStep][layerID];
}
void mitk::SurfaceInterpolationController::CompleteReinitialization(const std::vector<mitk::Surface::Pointer>& contourList,
std::vector<const mitk::PlaneGeometry *>& contourPlanes)
{
this->ClearInterpolationSession();
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
auto numLayers = labelSetImage->GetNumberOfLayers();
// Add layers to the m_ListOfContours
for (size_t layer = 0; layer < numLayers; ++layer)
{
this->OnAddLayer();
}
// Now the layers should be empty and the new layers can be added.
this->AddNewContours(contourList, contourPlanes, true);
}
void mitk::SurfaceInterpolationController::ClearInterpolationSession()
{
if (m_SelectedSegmentation != nullptr)
{
auto it = m_ListOfContours.find(m_SelectedSegmentation);
if (it != m_ListOfContours.end())
{
auto timeSteps = m_ListOfContours[m_SelectedSegmentation].size();
try
{
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
auto labelSetImageTimeSteps = labelSetImage->GetTimeGeometry()->CountTimeSteps();
if (timeSteps != labelSetImageTimeSteps)
{
MITK_ERROR << "Time steps are not the same.";
}
for (size_t t = 0; t < timeSteps; ++t)
{
m_ListOfContours[m_SelectedSegmentation][t].clear();
}
}
catch(std::bad_cast& e)
{
MITK_ERROR << "Unable to cast m_SelectedSegmentation to labelSetImage in ClearInterpolationSession";
}
}
}
}
std::vector< mitk::Point3D > mitk::ContourExt::GetBoundingBoxGridPoints(
size_t planeDimension,
double startDim1,
size_t numPointsToSampleDim1,
double deltaDim1,
double startDim2,
size_t numPointsToSampleDim2,
double deltaDim2,
double valuePlaneDim)
{
std::vector< mitk::Point3D > gridPoints;
for (size_t i = 0; i < numPointsToSampleDim1; ++i)
{
for (size_t j = 0; j < numPointsToSampleDim2; ++j)
{
mitk::ScalarType *ptVec = new mitk::ScalarType[3];
if (planeDimension == 0)
{
ptVec[0] = valuePlaneDim;
ptVec[1] = startDim1 + deltaDim1 * i;
ptVec[2] = startDim2 + deltaDim2 * j;
}
else if (planeDimension == 1)
{
ptVec[0] = startDim1 + deltaDim1 * i;
ptVec[1] = valuePlaneDim;
ptVec[2] = startDim2 + deltaDim2 * j;
}
else if (planeDimension == 2)
{
ptVec[0] = startDim1 + deltaDim1 * i;
ptVec[1] = startDim2 + deltaDim2 * j;
ptVec[2] = valuePlaneDim;
}
mitk::Point3D pt3D;
pt3D.FillPoint(ptVec);
gridPoints.push_back(pt3D);
}
}
return gridPoints;
}
mitk::Point3D mitk::SurfaceInterpolationController::ComputeInteriorPointOfContour(
const mitk::SurfaceInterpolationController::ContourPositionInformation& contour,
mitk::LabelSetImage * labelSetImage)
{
if (labelSetImage->GetDimension() == 4)
{
return mitk::ContourExt::ComputeInteriorPointOfContour<4>(contour, labelSetImage, m_CurrentTimePoint);
}
else
{
return mitk::ContourExt::ComputeInteriorPointOfContour<3>(contour, labelSetImage, m_CurrentTimePoint);
}
}
template<unsigned int VImageDimension>
mitk::Point3D mitk::ContourExt::ComputeInteriorPointOfContour(
const mitk::SurfaceInterpolationController::ContourPositionInformation& contour,
mitk::LabelSetImage * labelSetImage,
mitk::TimePointType currentTimePoint)
{
mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage);
if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(currentTimePoint))
{
MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
mitk::Point3D pt;
return pt;
}
std::vector<mitk::Label::PixelType> pixelsPresent;
const auto currentTimeStep = labelSetImage->GetTimeGeometry()->TimePointToTimeStep(currentTimePoint);
auto polyData = contour.Contour->GetVtkPolyData();
polyData->ComputeCellsBounds();
mitk::ScalarType cellBounds[6];
polyData->GetCellsBounds(cellBounds);
size_t numPointsToSample = 10;
mitk::ScalarType StartX = cellBounds[0];
mitk::ScalarType StartY = cellBounds[2];
mitk::ScalarType StartZ = cellBounds[4];
size_t deltaX = (cellBounds[1] - cellBounds[0]) / numPointsToSample;
size_t deltaY = (cellBounds[3] - cellBounds[2]) / numPointsToSample;
size_t deltaZ = (cellBounds[5] - cellBounds[4]) / numPointsToSample;
auto planeOrientation = mitk::ContourExt::GetContourOrientation(contour.ContourNormal);
std::vector<mitk::Point3D> points;
if (planeOrientation == 0)
{
points = mitk::ContourExt::GetBoundingBoxGridPoints(planeOrientation,
StartY, numPointsToSample, deltaY,
StartZ, numPointsToSample, deltaZ,
StartX);
}
else if (planeOrientation == 1)
{
points = mitk::ContourExt::GetBoundingBoxGridPoints(planeOrientation,
StartX, numPointsToSample, deltaX,
StartZ, numPointsToSample, deltaZ,
StartY);
}
else if (planeOrientation == 2)
{
points = mitk::ContourExt::GetBoundingBoxGridPoints(planeOrientation,
StartX, numPointsToSample, deltaX,
StartY, numPointsToSample, deltaY,
StartZ);
}
mitk::Label::PixelType pixelVal;
mitk::Point3D pt3D;
std::vector<mitk::Label::PixelType> pixelVals;
for (size_t i = 0; i < points.size(); ++i)
{
pt3D = points[i];
itk::Index<3> itkIndex;
labelSetImage->GetGeometry()->WorldToIndex(pt3D, itkIndex);
if (VImageDimension == 4)
{
itk::Index<VImageDimension> time3DIndex;
for (size_t i = 0; i < itkIndex.size(); ++i)
time3DIndex[i] = itkIndex[i];
time3DIndex[3] = currentTimeStep;
pixelVal = readAccessor.GetPixelByIndexSafe(time3DIndex);
}
else if (VImageDimension == 3)
{
itk::Index<VImageDimension> geomIndex;
for (size_t i=0;i<itkIndex.size();++i)
geomIndex[i] = itkIndex[i];
pixelVal = readAccessor.GetPixelByIndexSafe(geomIndex);
}
if (pixelVal == contour.LabelValue)
break;
}
return pt3D;
}
size_t mitk::ContourExt::GetContourOrientation(const mitk::Vector3D& ContourNormal)
{
double n[3];
n[0] = ContourNormal[0];
n[1] = ContourNormal[1];
n[2] = ContourNormal[2];
double XVec[3];
XVec[0] = 1.0; XVec[1] = 0.0; XVec[2] = 0.0;
double dotX = vtkMath::Dot(n, XVec);
double YVec[3];
YVec[0] = 0.0; YVec[1] = 1.0; YVec[2] = 0.0;
double dotY = vtkMath::Dot(n, YVec);
double ZVec[3];
ZVec[0] = 0.0; ZVec[1] = 0.0; ZVec[2] = 1.0;
double dotZ = vtkMath::Dot(n, ZVec);
size_t planeOrientation = 0;
if (fabs(dotZ) > mitk::eps)
{
planeOrientation = 2;
}
else if (fabs(dotY) > mitk::eps)
{
planeOrientation = 1;
}
else if(fabs(dotX) > mitk::eps)
{
planeOrientation = 0;
}
return planeOrientation;
}
diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h
index 5137c3a5ee..3a2ea6eccc 100644
--- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h
+++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h
@@ -1,468 +1,468 @@
/*============================================================================
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 mitkSurfaceInterpolationController_h
#define mitkSurfaceInterpolationController_h
#include <mitkDataStorage.h>
#include <mitkImage.h>
#include <mitkLabel.h>
#include <mitkSurface.h>
#include <MitkSurfaceInterpolationExports.h>
namespace mitk
{
class ComputeContourSetNormalsFilter;
class CreateDistanceImageFromSurfaceFilter;
class LabelSetImage;
class ReduceContourSetFilter;
class MITKSURFACEINTERPOLATION_EXPORT SurfaceInterpolationController : public itk::Object
{
public:
mitkClassMacroItkParent(SurfaceInterpolationController, itk::Object);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
itkGetMacro(DistanceImageSpacing, double);
struct MITKSURFACEINTERPOLATION_EXPORT ContourPositionInformation
{
int Pos;
unsigned int SliceIndex;
Surface::Pointer Contour;
Vector3D ContourNormal;
Point3D ContourPoint;
mitk::PlaneGeometry* Plane;
mitk::Label::PixelType LabelValue;
unsigned int LayerValue;
size_t TimeStep;
ContourPositionInformation()
: Pos(-1),
SliceIndex(0),
Plane(nullptr),
LabelValue(std::numeric_limits<mitk::Label::PixelType>::max()),
LayerValue(std::numeric_limits<unsigned int>::max()),
TimeStep(std::numeric_limits<size_t>::max())
{
}
};
typedef std::vector<ContourPositionInformation> ContourPositionInformationList;
typedef std::vector<ContourPositionInformationList> ContourPositionInformationVec2D;
// first index is the current time step. second index is the layerID. third index is the contour index.
typedef std::vector<ContourPositionInformationVec2D> ContourPositionInformationVec3D;
typedef std::map<mitk::Image *, ContourPositionInformationVec3D> ContourListMap;
typedef std::map<mitk::Image *, ContourPositionInformationVec2D> ContourContainer;
static SurfaceInterpolationController *GetInstance();
void SetCurrentTimePoint(TimePointType tp)
{
if (m_CurrentTimePoint != tp)
{
m_CurrentTimePoint = tp;
if (m_SelectedSegmentation)
{
this->ReinitializeInterpolation();
}
}
};
TimePointType GetCurrentTimePoint() const { return m_CurrentTimePoint; };
/**
* @brief Adds a new extracted contour to the list
* @param newContour the contour to be added. If a contour at that position
* already exists the related contour will be updated
*/
void AddNewContour(Surface::Pointer newContour);
/**
* @brief Adds new extracted contours to the list. If one or more contours at a given position
* already exist they will be updated respectively
*/
void AddNewContours(const std::vector<Surface::Pointer>& newContours, std::vector<const mitk::PlaneGeometry*>& contourPlanes, bool reinitializeAction = false);
/**
* @brief Returns the contour for a given plane for the current selected segmenation
* @param contourInfo the contour which should be returned
* @return the contour as an mitk::Surface. If no contour is available at the give position nullptr is returned
*/
const mitk::Surface *GetContour(const ContourPositionInformation& contourInfo);
/**
* @brief Computes an interior point of the input contour. It's used to detect merge and erase operations.
*
* @param contour Contour for which to compute the contour
* @param labelSetImage LabelSetImage used input to check contour Label.
* @return mitk::Point3D 3D Interior point of the contour returned.
*/
mitk::Point3D ComputeInteriorPointOfContour(const ContourPositionInformation& contour,
mitk::LabelSetImage * labelSetImage);
/**
* @brief Make the surface interpolator responsive to the segmentation image by subscribing to events from the image.
*
*/
void AddLabelSetConnection();
/**
* @brief Make the surface interpolator responsive to the segmentation image by stopping subscription to events from the image.
*
*/
void RemoveLabelSetConnection();
void RemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID);
/**
* @brief Resets the pipeline for interpolation. The various filters used are reset.
*
*/
void ReinitializeInterpolation();
void RemoveObservers();
void AddLabelSetConnection(unsigned int layerID);
void UnsetSelectedImage()
{
m_SelectedSegmentation = nullptr;
}
/**
* @brief Returns the number of layers in the current segmentation image.
*
*/
unsigned int GetNumberOfLayersInCurrentSegmentation() const;
/**
* @brief Set the number of layers in the current segmentation image.
*
*/
void SetNumberOfLayersInCurrentSegmentation(unsigned int);
/**
* @brief Function that does the data management when a layer is removed.
*
*/
void OnRemoveLayer();
/**
* @brief Function that does the data management when a layer is added.
*
*/
void OnAddLayer();
/**
* @brief Returns the number of available contours for the current selected segmentation
* @return the number of contours
*/
unsigned int GetNumberOfContours();
/**
* @brief Performs the interpolation.
*
*/
void Interpolate();
/**
* @brief Get the Result of the interpolation operation.
*
* @return mitk::Surface::Pointer
*/
mitk::Surface::Pointer GetInterpolationResult();
/**
* @brief Sets the minimum spacing of the current selected segmentation
* This is needed since the contour points we reduced before they are used to interpolate the surface.
*
* @param minSpacing Paramter to set
*/
void SetMinSpacing(double minSpacing);
/**
* @brief Sets the minimum spacing of the current selected segmentation
* This is needed since the contour points we reduced before they are used to interpolate the surface
* @param maxSpacing Set the max Spacing for interpolation
*/
void SetMaxSpacing(double maxSpacing);
/**
* Sets the volume i.e. the number of pixels that the distance image should have
* By evaluation we found out that 50.000 pixel delivers a good result
*/
void SetDistanceImageVolume(unsigned int distImageVolume);
/**
* @brief Get the current selected segmentation for which the interpolation is performed
* @return the current segmentation image
*/
mitk::Image::Pointer GetCurrentSegmentation();
Surface *GetContoursAsSurface();
void SetDataStorage(DataStorage::Pointer ds);
/**
* Sets the current list of contourpoints which is used for the surface interpolation
* @param segmentation The current selected segmentation
* \deprecatedSince{2014_03}
*/
DEPRECATED(void SetCurrentSegmentationInterpolationList(mitk::Image::Pointer segmentation));
/**
* Sets the current list of contourpoints which is used for the surface interpolation
* @param currentSegmentationImage The current selected segmentation
*/
void SetCurrentInterpolationSession(mitk::Image::Pointer currentSegmentationImage);
/**
* Removes the segmentation and all its contours from the list
* @param segmentation The segmentation to be removed
* \deprecatedSince{2014_03}
*/
DEPRECATED(void RemoveSegmentationFromContourList(mitk::Image *segmentation));
/**
* @brief Remove interpolation session
* @param segmentationImage the session to be removed
*/
void RemoveInterpolationSession(mitk::Image::Pointer segmentationImage);
/**
* Replaces the current interpolation session with a new one. All contours form the old
* session will be applied to the new session. This only works if the two images have the
* geometry
* @param oldSession the session which should be replaced
* @param newSession the new session which replaces the old one
* @return true it the the replacement was successful, false if not (e.g. the image's geometry differs)
*/
bool ReplaceInterpolationSession(mitk::Image::Pointer oldSession, mitk::Image::Pointer newSession);
/**
* @brief Removes all sessions
*/
void RemoveAllInterpolationSessions();
mitk::Image *GetImage();
/**
* @brief Get the Contours at a certain timeStep and layerID.
*
* @param timeStep Time Step from which to get the contours.
* @param layerID Layer from which to get the contours.
* @return std::vector<ContourPositionInformation> Returns contours.
*/
- ContourPositionInformationList& GetContours(unsigned int timeStep, unsigned int layerID);
+ ContourPositionInformationList* GetContours(unsigned int timeStep, unsigned int layerID);
/**
* @brief Trigerred with the "Reinit Interpolation" action. The contours are used to repopulate the
* surfaceInterpolator data structures so that interpolation can be performed after reloading data.
*
* @param contourList List of contours extracted
* @param contourPlanes List of planes at which the contours were extracted
*/
void CompleteReinitialization(const std::vector<mitk::Surface::Pointer>& contourList,
std::vector<const mitk::PlaneGeometry *>& contourPlanes);
/**
* @brief Removes contours of a particular label, at a given time step and layerID.
*
* @param label Label of contour to remove.
* @param timeStep Time step in which to remove the contours.
* @param layerID Layer in which the contour should be removed.
*/
void RemoveContours(mitk::Label::PixelType label, unsigned int timeStep, unsigned int layerID);
/**
* Estimates the memory which is needed to build up the equationsystem for the interpolation.
* \returns The percentage of the real memory which will be used by the interpolation
*/
double EstimatePortionOfNeededMemory();
/**
* Adds Contours from the active Label to the interpolation pipeline
*/
void AddActiveLabelContoursForInterpolation(mitk::Label::PixelType activeLabel);
unsigned int GetNumberOfInterpolationSessions();
/**
* @brief Removes the contour for a given plane for the current selected segmenation
* @param contourInfo the contour which should be removed
* @return true if a contour was found and removed, false if no contour was found
*/
bool RemoveContour(ContourPositionInformation contourInfo);
/**
* @brief Get the Segmentation Image Node object
*
* @return DataNode* returns the DataNode containing the segmentation image.
*/
mitk::DataNode* GetSegmentationImageNode();
protected:
SurfaceInterpolationController();
~SurfaceInterpolationController() override;
template <typename TPixel, unsigned int VImageDimension>
void GetImageBase(itk::Image<TPixel, VImageDimension> *input, itk::ImageBase<3>::Pointer &result);
private:
/**
* @brief
*
* @param caller
* @param event
*/
void OnSegmentationDeleted(const itk::Object *caller, const itk::EventObject &event);
/**
* @brief Function that removes contours of a particular label when the "Remove Label" event is trigerred in the labelSetImage.
*
*/
void OnRemoveLabel(mitk::Label::PixelType removedLabelValue);
/**
* @brief When a new contour is added to the pipeline or an existing contour is replaced,
* the plane geometry information of that contour is added as a child node to the
* current node of the segmentation image. This is useful in the retrieval of contour information
* when data is reloaded after saving.
*
* @param contourInfo contourInfo struct to add to data storage.
*/
void AddPlaneGeometryNodeToDataStorage(const ContourPositionInformation& contourInfo);
/**
* @brief Function that toggles active label, when the active label is changed.
*
*/
void OnActiveLabel(mitk::Label::PixelType);
/**
* @brief Clears the interpolation data structures. Called from CompleteReinitialization().
*
*/
void ClearInterpolationSession();
/**
* @brief Add contour to the interpolation pipeline
*
* @param contourInfo Contour information to be added
* @param reinitializationAction If the contour is coming from a reinitialization process or not
*/
void AddToInterpolationPipeline(ContourPositionInformation& contourInfo, bool reinitializationAction = false);
/**
* @brief Function to respond to layer changed
*
*/
void OnLayerChanged();
itk::SmartPointer<ReduceContourSetFilter> m_ReduceFilter;
itk::SmartPointer<ComputeContourSetNormalsFilter> m_NormalsFilter;
itk::SmartPointer<CreateDistanceImageFromSurfaceFilter> m_InterpolateSurfaceFilter;
mitk::Surface::Pointer m_Contours;
double m_DistanceImageSpacing;
vtkSmartPointer<vtkPolyData> m_PolyData;
mitk::DataStorage::Pointer m_DataStorage;
ContourContainer m_ListOfInterpolationSessions;
ContourListMap m_ListOfContours;
mitk::Surface::Pointer m_InterpolationResult;
unsigned int m_CurrentNumberOfReducedContours;
unsigned int m_NumberOfConnectionsAdded;
mitk::Image *m_SelectedSegmentation;
std::map<mitk::Image *, unsigned long> m_SegmentationObserverTags;
mitk::TimePointType m_CurrentTimePoint;
unsigned int m_ContourIndex;
unsigned int m_ContourPosIndex;
unsigned int m_NumberOfLayersInCurrentSegmentation;
mitk::Label::PixelType m_PreviousActiveLabelValue;
mitk::Label::PixelType m_CurrentActiveLabelValue;
unsigned int m_PreviousLayerIndex;
unsigned int m_CurrentLayerIndex;
};
namespace ContourExt
{
/**
* @brief Returns the plane the contour belongs to.
*
* @param ContourNormal
* @return size_t
*/
size_t GetContourOrientation(const mitk::Vector3D& ContourNormal);
/**
* @brief Function used to compute an interior point of the contour.
* Used to react to the merge label and erase label actions.
*
*
* @tparam VImageDimension Dimension of the image
* @param contour Contour for which to compute the interior point
* @param labelSetImage Label Set Image For which to find the contour
* @param currentTimePoint Current Time Point of the Image
* @return mitk::Point3D The returned point in the interior of the contour.s
*/
template<unsigned int VImageDimension>
mitk::Point3D ComputeInteriorPointOfContour(const mitk::SurfaceInterpolationController::ContourPositionInformation& contour,
mitk::LabelSetImage * labelSetImage,
mitk::TimePointType currentTimePoint);
/**
* @brief Get a Grid points within the bounding box of the contour at a certain spacing.
*
* @param planeDimension Plane orientation (Sagittal, Coronal, Axial)
* @param startDim1 Starting coordinate along dimension 1 to start the grid point sampling from
* @param numPointsToSampleDim1 Number of points to sample along dimension 1
* @param deltaDim1 Spacing for dimension 1 at which points should be sampled
* @param startDim2 Starting coordinate along dimension 2 to start the grid point sampling from
* @param numPointsToSampleDim2 Number of points to sample along dimension 2
* @param deltaDim2 Spacing for dimension 1 at which points should be sampled
* @param valuePlaneDim Slice index of the plane in the volume
* @return std::vector< mitk::Point3D > The computed grid points are returned by the function.
*/
std::vector< mitk::Point3D > GetBoundingBoxGridPoints(size_t planeDimension,
double startDim1,
size_t numPointsToSampleDim1,
double deltaDim1,
double startDim2,
size_t numPointsToSampleDim2,
double deltaDim2,
double valuePlaneDim);
};
}
#endif
diff --git a/Modules/ToFProcessing/Testing/mitkToFProcessingCommonTest.cpp b/Modules/ToFProcessing/Testing/mitkToFProcessingCommonTest.cpp
index 92801d6e70..bc69bfe3f6 100644
--- a/Modules/ToFProcessing/Testing/mitkToFProcessingCommonTest.cpp
+++ b/Modules/ToFProcessing/Testing/mitkToFProcessingCommonTest.cpp
@@ -1,87 +1,87 @@
/*============================================================================
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 <mitkToFProcessingCommon.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
/**Documentation
* test for the class "ToFProcessingCommon".
*/
int mitkToFProcessingCommonTest(int /* argc */, char* /*argv*/[])
{
MITK_TEST_BEGIN("ToFProcessingCommon");
unsigned int i = 10;
unsigned int j = 50;
float distance = 1000;
float focalLength = 10;
mitk::Point2D focalLength_XY;
focalLength_XY[0] = 200;
focalLength_XY[1] = 200;
mitk::Point2D interPixelDistance;
interPixelDistance[0] = 0.05;
interPixelDistance[1] = 0.05;
mitk::Point2D principalPoint;
principalPoint[0] = 100;
principalPoint[1] = 100;
// expected coordinate
mitk::ToFProcessingCommon::ToFPoint3D expectedCoordinate;
expectedCoordinate[0] = -400.0988;
expectedCoordinate[1] = -222.2771;
expectedCoordinate[2] = 889.1084;
// resulting coordinate without using the interpixeldistance
mitk::ToFProcessingCommon::ToFPoint3D resultingCoordinate = mitk::ToFProcessingCommon::IndexToCartesianCoordinates(i,j,distance,focalLength_XY,principalPoint);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(expectedCoordinate,resultingCoordinate,1e-3),"Testing IndexToCartesianCoordinates()");
// resulting coordinate with using the interpixeldistance
mitk::ToFProcessingCommon::ToFPoint3D resultingCoordinateInterpix = mitk::ToFProcessingCommon::IndexToCartesianCoordinatesWithInterpixdist(i,j,distance,focalLength,interPixelDistance,principalPoint);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(expectedCoordinate,resultingCoordinateInterpix,1e-3),"Testing IndexToCartesianCoordinatesWithInterpixdist()");
// expected index
mitk::ToFProcessingCommon::ToFPoint3D expectedIndex;
expectedIndex[0] = i;
expectedIndex[1] = j;
expectedIndex[2] = 1000;
mitk::ToFProcessingCommon::ToFPoint3D resultingIndex = mitk::ToFProcessingCommon::CartesianToIndexCoordinates(expectedCoordinate,focalLength_XY,principalPoint);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(expectedIndex,resultingIndex,1e-3),"Testing CartesianToIndexCoordinates()");
mitk::ToFProcessingCommon::ToFPoint3D resultingIndexInterpix = mitk::ToFProcessingCommon::CartesianToIndexCoordinatesWithInterpixdist(expectedCoordinate,focalLength,interPixelDistance,principalPoint);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(expectedIndex,resultingIndexInterpix,1e-3),"Testing CartesianToIndexCoordinatesWithInterpixdist()");
//########## Kinect Reconstruction #############
mitk::ToFProcessingCommon::ToFPoint3D expectedKinectCoordinate;
expectedKinectCoordinate[0] = -450.0;
expectedKinectCoordinate[1] = -250.0;
expectedKinectCoordinate[2] = 1000.0;
itk::Index<3> index;
index[0] = i;
index[1] = j;
index[2] = 0;
mitk::ToFProcessingCommon::ToFPoint3D kinectReconstructionResult = mitk::ToFProcessingCommon::KinectIndexToCartesianCoordinates(index,distance, focalLength_XY,principalPoint);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(expectedKinectCoordinate,kinectReconstructionResult),"Compare the expected result with the result of reconstruction from KinectIndexToCartesianCoordinates()");
mitk::ToFProcessingCommon::ToFPoint3D kinectReconstructionResultBackward = mitk::ToFProcessingCommon::CartesianToKinectIndexCoordinates(kinectReconstructionResult, focalLength_XY, principalPoint);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(expectedIndex,kinectReconstructionResultBackward),"Transform everything back to distance image and compare it to the original input");
mitk::Point2D continuousIndex;
continuousIndex[0] = i;
continuousIndex[1] = j;
mitk::ToFProcessingCommon::ToFPoint3D continuousKinectReconstructionResult = mitk::ToFProcessingCommon::ContinuousKinectIndexToCartesianCoordinates(continuousIndex,distance, focalLength_XY[0], focalLength_XY[1], principalPoint[0], principalPoint[1]);
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(expectedKinectCoordinate,continuousKinectReconstructionResult),"Compare the expected result with the result of reconstruction from ContinuousKinectIndexToCartesianCoordinates(). Since the index is not continuous, the result has to be the same like for KinectIndexToCartesianCoordinates().");
//########## End Kinect Reconstruction #############
MITK_TEST_END();
}
diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake
index 8b336a0d7e..4b71a33320 100644
--- a/Plugins/PluginList.cmake
+++ b/Plugins/PluginList.cmake
@@ -1,89 +1,86 @@
# Plug-ins must be ordered according to their dependencies
set(MITK_PLUGINS
org.blueberry.core.runtime:ON
org.blueberry.core.expressions:OFF
org.blueberry.core.commands:OFF
org.blueberry.core.jobs:OFF
org.blueberry.ui.qt:OFF
org.blueberry.ui.qt.help:ON
org.blueberry.ui.qt.log:ON
org.blueberry.ui.qt.objectinspector:OFF
org.mitk.core.services:ON
org.mitk.gui.common:ON
org.mitk.planarfigure:ON
- org.mitk.core.ext:OFF
org.mitk.core.jobs:OFF
org.mitk.gui.qt.application:ON
org.mitk.gui.qt.ext:OFF
org.mitk.gui.qt.extapplication:OFF
org.mitk.gui.qt.mitkworkbench.intro:OFF
org.mitk.gui.qt.common:ON
org.mitk.gui.qt.stdmultiwidgeteditor:ON
org.mitk.gui.qt.mxnmultiwidgeteditor:OFF
org.mitk.gui.qt.cmdlinemodules:OFF
org.mitk.gui.qt.chartExample:OFF
org.mitk.gui.qt.datamanager:ON
org.mitk.gui.qt.datamanagerlight:OFF
org.mitk.gui.qt.datastorageviewertest:OFF
org.mitk.gui.qt.properties:ON
org.mitk.gui.qt.basicimageprocessing:OFF
org.mitk.gui.qt.dicombrowser:OFF
org.mitk.gui.qt.dicominspector:OFF
org.mitk.gui.qt.dosevisualization:OFF
org.mitk.gui.qt.geometrytools:OFF
org.mitk.gui.qt.igtexamples:OFF
org.mitk.gui.qt.igttracking:OFF
org.mitk.gui.qt.openigtlink:OFF
org.mitk.gui.qt.imagecropper:OFF
org.mitk.gui.qt.imagenavigator:ON
org.mitk.gui.qt.viewnavigator:OFF
org.mitk.gui.qt.materialeditor:OFF
org.mitk.gui.qt.measurementtoolbox:OFF
org.mitk.gui.qt.moviemaker:OFF
org.mitk.gui.qt.pointsetinteraction:OFF
org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF
org.mitk.gui.qt.python:OFF
org.mitk.gui.qt.remeshing:OFF
org.mitk.gui.qt.segmentation:OFF
org.mitk.gui.qt.deformableclippingplane:OFF
org.mitk.gui.qt.aicpregistration:OFF
org.mitk.gui.qt.renderwindowmanager:OFF
org.mitk.gui.qt.semanticrelations:OFF
org.mitk.gui.qt.toftutorial:OFF
org.mitk.gui.qt.tofutil:OFF
org.mitk.gui.qt.tubegraph:OFF
org.mitk.gui.qt.ugvisualization:OFF
org.mitk.gui.qt.ultrasound:OFF
org.mitk.gui.qt.volumevisualization:OFF
org.mitk.gui.qt.eventrecorder:OFF
org.mitk.gui.qt.xnat:OFF
org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation:OFF
- org.mitk.gui.qt.classificationsegmentation:OFF
org.mitk.gui.qt.overlaymanager:OFF
org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF
org.mitk.matchpoint.core.helper:OFF
org.mitk.gui.qt.matchpoint.algorithm.browser:OFF
org.mitk.gui.qt.matchpoint.algorithm.control:OFF
org.mitk.gui.qt.matchpoint.mapper:OFF
org.mitk.gui.qt.matchpoint.framereg:OFF
org.mitk.gui.qt.matchpoint.visualizer:OFF
org.mitk.gui.qt.matchpoint.evaluator:OFF
org.mitk.gui.qt.matchpoint.manipulator:OFF
org.mitk.gui.qt.preprocessing.resampling:OFF
- org.mitk.gui.qt.radiomics:OFF
org.mitk.gui.qt.cest:OFF
org.mitk.gui.qt.fit.demo:OFF
org.mitk.gui.qt.fit.inspector:OFF
org.mitk.gui.qt.fit.genericfitting:OFF
org.mitk.gui.qt.pharmacokinetics.mri:OFF
org.mitk.gui.qt.pharmacokinetics.pet:OFF
org.mitk.gui.qt.pharmacokinetics.simulation:OFF
org.mitk.gui.qt.pharmacokinetics.curvedescriptor:OFF
org.mitk.gui.qt.pharmacokinetics.concentration.mri:OFF
org.mitk.gui.qt.flowapplication:OFF
org.mitk.gui.qt.flow.segmentation:OFF
org.mitk.gui.qt.pixelvalue:ON
)
diff --git a/Plugins/org.blueberry.core.runtime/src/berryIAdapterFactory.h b/Plugins/org.blueberry.core.runtime/src/berryIAdapterFactory.h
index 013c9f32bf..fc4746e7e0 100644
--- a/Plugins/org.blueberry.core.runtime/src/berryIAdapterFactory.h
+++ b/Plugins/org.blueberry.core.runtime/src/berryIAdapterFactory.h
@@ -1,86 +1,86 @@
/*============================================================================
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 BERRYIADAPTERFACTORY_H_
#define BERRYIADAPTERFACTORY_H_
#include <org_blueberry_core_runtime_Export.h>
#include <vector>
#include <typeinfo>
namespace berry {
/**
* An adapter factory defines behavioral extensions for
* one or more classes that implements the <code>IAdaptable</code>
* interface. Adapter factories are registered with an
* adapter manager.
* <p>
* This interface can be used without OSGi running.
* </p><p>
* Clients may implement this interface.
* </p>
* @see IAdapterManager
* @see IAdaptable
*/
struct org_blueberry_core_runtime_EXPORT IAdapterFactory {
virtual ~IAdapterFactory() {};
/**
* Returns an object which can be cast to the given adapter type and which is
* associated with the given adaptable object. Returns <code>0</code> if
* no such object can be found.
*
* A typical implementation would look like this:
*
* <code>
* void* GetAdapter(void* adaptableObject, const std::type_info& adaptableType, const std::string& adapterType)
* {
* if (Image* img = CastHelper<Image>(adaptableObject, adaptableType))
* {
* if (adapterType == "berry::IResource")
* {
* return new IResource(img->GetPath());
* }
* }
* return 0;
* }
* </code>
*
* @param adaptableObject the adaptable object being queried
* (usually an instance of <code>IAdaptable</code>)
* @param adapterType the type of adapter to look up
* @return a object castable to the given adapter type,
* or <code>0</code> if this adapter factory
* does not have an adapter of the given type for the
* given object
*/
virtual Object* GetAdapter(IAdaptable* adaptableObject, const std::string& adapterType) = 0;
/**
* Returns the collection of adapter types handled by this
* factory.
* <p>
* This method is generally used by an adapter manager
* to discover which adapter types are supported, in advance
* of dispatching any actual <code>getAdapter</code> requests.
* </p>
*
- * @return the collection of adapter types
+ * @param[out] adapters the collection of adapter types
*/
virtual void GetAdapterList(std::vector<const std::type_info&>& adapters) = 0;
};
}
#endif /*BERRYIADAPTERFACTORY_H_*/
diff --git a/Plugins/org.blueberry.core.runtime/src/berryLog.h b/Plugins/org.blueberry.core.runtime/src/berryLog.h
index bb89526a10..74791cb7d7 100644
--- a/Plugins/org.blueberry.core.runtime/src/berryLog.h
+++ b/Plugins/org.blueberry.core.runtime/src/berryLog.h
@@ -1,29 +1,29 @@
/*============================================================================
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 __BERRY_LOG_H__
#define __BERRY_LOG_H__
-#include <mbilog.h>
+#include <mitkLog.h>
#include <org_blueberry_core_runtime_Export.h>
-#define BERRY_INFO MBI_INFO("BlueBerry")
-#define BERRY_WARN MBI_WARN("BlueBerry")
-#define BERRY_ERROR MBI_ERROR("BlueBerry")
-#define BERRY_FATAL MBI_FATAL("BlueBerry")
+#define BERRY_INFO MITK_INFO("BlueBerry")
+#define BERRY_WARN MITK_WARN("BlueBerry")
+#define BERRY_ERROR MITK_ERROR("BlueBerry")
+#define BERRY_FATAL MITK_FATAL("BlueBerry")
-#define BERRY_DEBUG MBI_DEBUG("BlueBerry")
+#define BERRY_DEBUG MITK_DEBUG("BlueBerry")
org_blueberry_core_runtime_EXPORT std::ostream& operator<<(std::ostream& os, const QString& str);
#endif /*__BERRY_LOG_H__*/
diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryLogImpl.cpp b/Plugins/org.blueberry.core.runtime/src/internal/berryLogImpl.cpp
index b261b3001a..ed5ab994dd 100644
--- a/Plugins/org.blueberry.core.runtime/src/internal/berryLogImpl.cpp
+++ b/Plugins/org.blueberry.core.runtime/src/internal/berryLogImpl.cpp
@@ -1,72 +1,72 @@
/*============================================================================
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 "berryLogImpl.h"
#include "berryIStatus.h"
#include <ctkPlugin.h>
-#include <mbilog.h>
+#include <mitkLog.h>
namespace berry {
LogImpl::LogImpl(const QSharedPointer<ctkPlugin>& plugin)
: plugin(plugin)
{
}
LogImpl::~LogImpl()
{
}
void LogImpl::AddLogListener(ILogListener* /*listener*/)
{
}
QSharedPointer<ctkPlugin> LogImpl::GetBundle() const
{
return plugin;
}
void LogImpl::Log(const SmartPointer<IStatus>& status)
{
switch (status->GetSeverity())
{
case IStatus::WARNING_TYPE:
- mbilog::PseudoStream(mbilog::Warn,
+ mitk::PseudoLogStream(mitk::LogLevel::Warn,
qPrintable(status->GetFileName()),
status->GetLineNumber(),
qPrintable(status->GetMethodName()))(qPrintable(plugin->getSymbolicName()))
<< status->ToString().toStdString();
break;
case IStatus::ERROR_TYPE:
- mbilog::PseudoStream(mbilog::Error,
+ mitk::PseudoLogStream(mitk::LogLevel::Error,
qPrintable(status->GetFileName()),
status->GetLineNumber(),
qPrintable(status->GetMethodName()))(qPrintable(plugin->getSymbolicName()))
<< status->ToString().toStdString();
break;
default:
- mbilog::PseudoStream(mbilog::Info,
+ mitk::PseudoLogStream(mitk::LogLevel::Info,
qPrintable(status->GetFileName()),
status->GetLineNumber(),
qPrintable(status->GetMethodName()))(qPrintable(plugin->getSymbolicName()))
<< status->ToString().toStdString();
break;
}
}
void LogImpl::RemoveLogListener(ILogListener* /*listener*/)
{
}
}
diff --git a/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.cpp b/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.cpp
index ec1b20951b..6dd5f99784 100644
--- a/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.cpp
+++ b/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.cpp
@@ -1,333 +1,332 @@
/*============================================================================
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 "berryQtPlatformLogModel.h"
#include "berryQtLogPlugin.h"
-#include "mbilogLoggingTypes.h"
+#include <mitkLogLevel.h>
#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>
#include <QTimer>
#include <QIcon>
#include <QModelIndex>
#include <QDebug>
namespace berry {
const QString QtPlatformLogModel::Error = QString("Error");
const QString QtPlatformLogModel::Warn = QString("Warning");
const QString QtPlatformLogModel::Fatal = QString("Fatal");
const QString QtPlatformLogModel::Info = QString("Info");
const QString QtPlatformLogModel::Debug = QString("Debug");
void QtPlatformLogModel::slotFlushLogEntries()
{
m_Mutex.lock();
QList<ExtendedLogMessage> *tmp=m_Active;
m_Active=m_Pending; m_Pending=tmp;
m_Mutex.unlock();
int num = static_cast<int>(m_Pending->size());
if (num > 0)
{
int row = static_cast<int>(m_Entries.size());
this->beginInsertRows(QModelIndex(), row, row+num-1);
do {
m_Entries.push_back(m_Pending->front());
m_Pending->pop_front();
} while(--num);
this->endInsertRows();
}
}
-void QtPlatformLogModel::addLogEntry(const mbilog::LogMessage &msg)
+void QtPlatformLogModel::addLogEntry(const mitk::LogMessage &msg)
{
m_Mutex.lock();
- //mbilog::BackendCout::FormatSmart(msg); FormatSmart is not static any more. So commented out this statement. Todo: fix
+ //mitk::LogBackendCout::FormatSmart(msg); FormatSmart is not static any more. So commented out this statement. Todo: fix
m_Active->push_back(ExtendedLogMessage(msg));
m_Mutex.unlock();
emit signalFlushLogEntries();
-
}
void
QtPlatformLogModel::SetShowAdvancedFiels( bool showAdvancedFiels )
{
if( m_ShowAdvancedFiels != showAdvancedFiels )
{
m_ShowAdvancedFiels = showAdvancedFiels;
this->beginResetModel();
this->endResetModel();
}
}
void QtPlatformLogModel::SetShowCategory( bool showCategory )
{
if( m_ShowCategory != showCategory )
{
m_ShowCategory = showCategory;
this->beginResetModel();
this->endResetModel();
}
}
void
QtPlatformLogModel::addLogEntry(const ctkPluginFrameworkEvent& event)
{
- int level = mbilog::Info;
+ auto level = mitk::LogLevel::Info;
if (event.getType() == ctkPluginFrameworkEvent::PLUGIN_ERROR)
{
- level = mbilog::Error;
+ level = mitk::LogLevel::Error;
}
else if (event.getType() == ctkPluginFrameworkEvent::FRAMEWORK_WAIT_TIMEDOUT ||
event.getType() == ctkPluginFrameworkEvent::PLUGIN_WARNING)
{
- level = mbilog::Warn;
+ level = mitk::LogLevel::Warn;
}
- mbilog::LogMessage msg(level,"n/a",-1,"n/a");
+ mitk::LogMessage msg(level,"n/a",-1,"n/a");
QString str;
QDebug dbg(&str);
dbg << event;
- msg.message = str.toStdString();
+ msg.Message = str.toStdString();
//msg.moduleName = event.getPlugin()->getSymbolicName().toStdString();
addLogEntry(msg);
}
QtPlatformLogModel::QtPlatformLogModel(QObject* parent) : QAbstractTableModel(parent),
m_ShowAdvancedFiels(false),
m_ShowCategory(true)
{
m_Active=new QList<ExtendedLogMessage>;
m_Pending=new QList<ExtendedLogMessage>;
connect(this, SIGNAL(signalFlushLogEntries()), this, SLOT( slotFlushLogEntries() ), Qt::QueuedConnection );
QtLogPlugin::GetInstance()->GetContext()->connectFrameworkListener(this, SLOT(addLogEntry(ctkPluginFrameworkEvent)));
myBackend = new QtLogBackend(this);
}
QtPlatformLogModel::~QtPlatformLogModel()
{
disconnect(this, SIGNAL(signalFlushLogEntries()), this, SLOT( slotFlushLogEntries() ));
QtLogPlugin::GetInstance()->GetContext()->disconnectFrameworkListener(this);
- // dont delete and unregister backend, only deactivate it to avoid thread syncronization issues cause mbilog::UnregisterBackend is not threadsafe
+ // dont delete and unregister backend, only deactivate it to avoid thread syncronization issues cause mitk::UnregisterBackend is not threadsafe
// will be fixed.
// delete myBackend;
// delete m_Active;
// delete m_Pending;
m_Mutex.lock();
myBackend->Deactivate();
m_Mutex.unlock();
}
// QT Binding
int
QtPlatformLogModel::rowCount(const QModelIndex&) const
{
return static_cast<int>(m_Entries.size());
}
int
QtPlatformLogModel::columnCount(const QModelIndex&) const
{
int returnValue = 2;
if( m_ShowAdvancedFiels ) returnValue += 7;
if( m_ShowCategory ) returnValue += 1;
return returnValue;
}
/*
struct LogEntry {
LogEntry(const std::string& msg, const std::string& src, std::time_t t)
: message(msg.c_str()), moduleName(src.c_str()),time(std::clock())
{
}
QString message;
clock_t time;
QString level;
QString filePath;
QString lineNumber;
QString moduleName;
QString category;
QString function;
- LogEntry(const mbilog::LogMessage &msg)
+ LogEntry(const mitk::LogMessage &msg)
{
- message = msg.message.c_str();
+ message = msg.Message.c_str();
filePath = msg.filePath;
std::stringstream out;
- out << msg.lineNumber;
+ out << msg.LineNumber;
lineNumber = out.str().c_str();
- moduleName = msg.moduleName;
- category = msg.category.c_str();
- function = msg.functionName;
+ moduleName = msg.ModuleName;
+ category = msg.Category.c_str();
+ function = msg.FunctionName;
time=std::clock();
}
}; */
QVariant QtPlatformLogModel::data(const QModelIndex& index, int role) const
{
const ExtendedLogMessage *msg = &m_Entries[index.row()];
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case 0:
if (m_ShowAdvancedFiels) return msg->getTime();
else return msg->getLevel();
case 1:
if (m_ShowAdvancedFiels) return msg->getLevel();
else return msg->getMessage();
case 2:
if (m_ShowAdvancedFiels) return msg->getMessage();
else return msg->getCategory();
case 3:
if (m_ShowAdvancedFiels && m_ShowCategory) return msg->getCategory();
else if (m_ShowAdvancedFiels && !m_ShowCategory) return msg->getModuleName();
else break;
case 4:
if (m_ShowAdvancedFiels && m_ShowCategory) return msg->getModuleName();
else if (m_ShowAdvancedFiels && !m_ShowCategory) return msg->getFunctionName();
else break;
case 5:
if (m_ShowAdvancedFiels && m_ShowCategory) return msg->getFunctionName();
else if (m_ShowAdvancedFiels && !m_ShowCategory) return msg->getPath();
else break;
case 6:
if (m_ShowAdvancedFiels && m_ShowCategory) return msg->getPath();
else if (m_ShowAdvancedFiels && !m_ShowCategory) return msg->getLine();
else break;
case 7:
if (m_ShowAdvancedFiels && m_ShowCategory) return msg->getLine();
else break;
}
}
else if( role == Qt::DecorationRole )
{
if ( (m_ShowAdvancedFiels && index.column()==1)
|| (!m_ShowAdvancedFiels && index.column()==0) )
{
QString file ( ":/org_blueberry_ui_qt_log/information.png" );
- if( msg->message.level == mbilog::Error )
+ if( msg->message.Level == mitk::LogLevel::Error )
file = ":/org_blueberry_ui_qt_log/error.png";
- else if( msg->message.level == mbilog::Warn )
+ else if( msg->message.Level == mitk::LogLevel::Warn )
file = ":/org_blueberry_ui_qt_log/warning.png";
- else if( msg->message.level == mbilog::Debug )
+ else if( msg->message.Level == mitk::LogLevel::Debug )
file = ":/org_blueberry_ui_qt_log/debug.png";
- else if( msg->message.level == mbilog::Fatal )
+ else if( msg->message.Level == mitk::LogLevel::Fatal )
file = ":/org_blueberry_ui_qt_log/fatal.png";
QIcon icon(file);
return QVariant(icon);
}
}
return QVariant();
}
QVariant
QtPlatformLogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
if( m_ShowAdvancedFiels && m_ShowCategory )
{
switch (section)
{
case 0: return QVariant(" Time ");
case 1: return QVariant(" Level ");
case 2: return QVariant(" Message ");
case 3: return QVariant(" Category ");
case 4: return QVariant(" Module ");
case 5: return QVariant(" Function ");
case 6: return QVariant(" File ");
case 7: return QVariant(" Line ");
}
}
else if (m_ShowAdvancedFiels && !m_ShowCategory)
{
switch (section)
{
case 0: return QVariant(" Time ");
case 1: return QVariant(" Level ");
case 2: return QVariant(" Message ");
case 3: return QVariant(" Module ");
case 4: return QVariant(" Function ");
case 5: return QVariant(" File ");
case 6: return QVariant(" Line ");
}
}
else //!m_ShowAdvancedFiels, m_ShowCategory is not handled seperately because it only activates case 2
{
switch (section)
{
case 0: return QVariant(" Level ");
case 1: return QVariant(" Message ");
case 2: return QVariant(" Category ");
}
}
}
return QVariant();
}
QVariant QtPlatformLogModel::ExtendedLogMessage::getTime() const
{
std::stringstream ss;
std::locale C("C");
ss.imbue(C);
ss << std::setw(7) << std::setprecision(3) << std::fixed << ((double)this->time)/CLOCKS_PER_SEC;
return QVariant(QString(ss.str().c_str()));
}
QString QtPlatformLogModel::GetDataAsString()
{
QString returnValue("");
for (int message=0; message<this->rowCount(QModelIndex()); message++)
{
for (int column=0; column<this->columnCount(QModelIndex()); column++)
{
returnValue += " " + this->data(this->index(message,column),Qt::DisplayRole).toString();
}
returnValue += "\n";
}
return returnValue;
}
}
diff --git a/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.h b/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.h
index 15107a4d31..bd6b7f567e 100644
--- a/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.h
+++ b/Plugins/org.blueberry.ui.qt.log/src/internal/berryQtPlatformLogModel.h
@@ -1,215 +1,211 @@
/*============================================================================
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 BERRYQTPLATFORMLOGMODEL_H_
#define BERRYQTPLATFORMLOGMODEL_H_
#include "berryLog.h"
#include "ctkPluginFrameworkEvent.h"
#include <QtCore/QAbstractTableModel>
#include <QtCore/QDateTime>
#include <ctime>
#include <sstream>
#include "berryLog.h"
#include <QMutex>
namespace berry {
/** Documentation
* @brief An object of this class represents a table of logging data.
* The table presentation can be modified by the methods
* SetShowAdvancedFiels() and SetShowCategory().
*/
class QtPlatformLogModel : public QAbstractTableModel
{
Q_OBJECT
public:
QtPlatformLogModel(QObject* parent = nullptr);
~QtPlatformLogModel() override;
void SetShowAdvancedFiels( bool showAdvancedFiels );
void SetShowCategory( bool showCategory );
int rowCount(const QModelIndex&) const override;
int columnCount(const QModelIndex&) const override;
QVariant data(const QModelIndex& index, int) const override;
/** Documentation
* @return Retruns the complete table data as string representation.
*/
QString GetDataAsString();
QVariant headerData(int section, Qt::Orientation orientation, int) const override;
- void addLogEntry(const mbilog::LogMessage &msg);
+ void addLogEntry(const mitk::LogMessage &msg);
Q_SLOT void addLogEntry(const ctkPluginFrameworkEvent& event);
private:
bool m_ShowAdvancedFiels;
bool m_ShowCategory;
/** Documentation
* @brief An object of this struct internally represents a logging message.
* It offers methods to convert the logging data into QVaraint objects
* and also adds time and threadid as logging data. The struct is
* internally used to store logging data in the table data model.
*/
struct ExtendedLogMessage {
- mbilog::LogMessage message;
+ mitk::LogMessage message;
clock_t time;
int threadid;
ExtendedLogMessage(const ExtendedLogMessage &src):message(src.message),time(src.time),threadid(src.threadid)
{
}
- ExtendedLogMessage(const mbilog::LogMessage &msg):message(msg),time(std::clock()),threadid(0)
+ ExtendedLogMessage(const mitk::LogMessage &msg):message(msg),time(std::clock()),threadid(0)
{
}
ExtendedLogMessage operator = (const ExtendedLogMessage& src)
{
return ExtendedLogMessage(src);
}
QVariant getLevel() const
{
- switch(this->message.level)
+ switch(this->message.Level)
{
default:
- case mbilog::Info:
+ case mitk::LogLevel::Info:
return QVariant(Info);
- case mbilog::Warn:
+ case mitk::LogLevel::Warn:
return QVariant(Warn);
- case mbilog::Error:
+ case mitk::LogLevel::Error:
return QVariant(Error);
- case mbilog::Fatal:
+ case mitk::LogLevel::Fatal:
return QVariant(Fatal);
- case mbilog::Debug:
+ case mitk::LogLevel::Debug:
return QVariant(Debug);
}
}
QVariant getMessage() const
{
- return QVariant(QString(this->message.message.c_str()));
+ return QVariant(QString::fromStdString(this->message.Message));
}
QVariant getCategory() const
{
- return QVariant(QString(this->message.category.c_str()));
+ return QVariant(QString::fromStdString(this->message.Category));
}
QVariant getModuleName() const
{
- return QVariant(QString(this->message.moduleName));
+ return QVariant(QString::fromStdString(this->message.ModuleName));
}
QVariant getFunctionName() const
{
- return QVariant(QString(this->message.functionName));
+ return QVariant(QString::fromStdString(this->message.FunctionName));
}
QVariant getPath() const
{
- return QVariant(QString(this->message.filePath));
+ return QVariant(QString::fromStdString(this->message.FilePath));
}
QVariant getLine() const
{
- std::stringstream out;
- std::locale C("C");
- out.imbue(C);
- out << this->message.lineNumber;
- return QVariant(QString(out.str().c_str()));
+ return QVariant(QString::number(this->message.LineNumber));
}
/** This method is implemented in the cpp file to save includes. */
QVariant getTime() const;
};
- class QtLogBackend : public mbilog::BackendBase
+ class QtLogBackend : public mitk::LogBackendBase
{
public:
QtLogBackend(QtPlatformLogModel *_myModel)
{
myModel=_myModel;
deactivated = false;
- mbilog::RegisterBackend(this);
- BERRY_INFO << "BlueBerry mbilog backend registered";
+ mitk::RegisterBackend(this);
+ BERRY_INFO << "BlueBerry log backend registered";
}
~QtLogBackend() override
{
- mbilog::UnregisterBackend(this);
+ mitk::UnregisterBackend(this);
}
- void ProcessMessage(const mbilog::LogMessage &l ) override
+ void ProcessMessage(const mitk::LogMessage &l ) override
{
if(!deactivated)
myModel->addLogEntry(l);
}
- mbilog::OutputType GetOutputType() const override
+ mitk::LogBackendBase::OutputType GetOutputType() const override
{
- return mbilog::Other;
+ return mitk::LogBackendBase::OutputType::Other;
}
void Deactivate()
{
deactivated=true;
}
private:
QtPlatformLogModel *myModel;
bool deactivated;
} *myBackend;
QList<ExtendedLogMessage> m_Entries;
QList<ExtendedLogMessage> *m_Active,*m_Pending;
static const QString Error;
static const QString Warn;
static const QString Fatal;
static const QString Info;
static const QString Debug;
QMutex m_Mutex;
signals:
void signalFlushLogEntries();
protected slots:
void slotFlushLogEntries();
};
}
#endif /*BERRYQTPLATFORMLOGMODEL_H_*/
diff --git a/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h b/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h
index c14935f48c..1a475db25a 100644
--- a/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h
+++ b/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h
@@ -1,196 +1,196 @@
/*============================================================================
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 BERRYIWORKBENCHWINDOW_H_
#define BERRYIWORKBENCHWINDOW_H_
#include <berryMacros.h>
#include <berryIAdaptable.h>
#include <org_blueberry_ui_qt_Export.h>
#include "berryIPageService.h"
#include "berryShell.h"
#include "services/berryIServiceLocator.h"
namespace berry {
struct IPartService;
struct ISelectionService;
struct IWorkbenchPage;
struct IWorkbench;
/**
* \ingroup org_blueberry_ui_qt
*
* A workbench window is a top level window in a workbench. Visually, a
* workbench window has a menubar, a toolbar, a status bar, and a main area for
* displaying a single page consisting of a collection of views and editors.
* <p>
* Each workbench window has a collection of 0 or more pages; the active page is
* the one that is being presented to the end user; at most one page is active
* in a window at a time.
* </p>
* <p>
* The workbench window supports a few services by default.
* If these services are used to allocate resources, it is important to
* remember to clean up those resources after you are done with them. Otherwise,
* the resources will exist until the workbench window is closed. The supported
* services are:
* </p>
* <ul>
* <li>{@link ICommandService}</li>
* <li>{@link IContextService}</li>
* </ul>
* <p>
* This interface is not intended to be implemented by clients.
* </p>
*
* @see IWorkbenchPage
*
*/
-struct BERRY_UI_QT IWorkbenchWindow : public IPageService, public IServiceLocator, public virtual Object
+struct BERRY_UI_QT IWorkbenchWindow : public IPageService, public IServiceLocator /** \cond */, public virtual Object /** \endcond */
{
berryObjectMacro(berry::IWorkbenchWindow, IPageService, IServiceLocator, Object);
/**
* Closes this workbench window.
* <p>
* If the window has an open editor with unsaved content, the user will be
* given the opportunity to save it.
* </p>
*
* @return <code>true</code> if the window was successfully closed, and
* <code>false</code> if it is still open
*/
virtual bool Close() = 0;
/**
* Returns a list of the pages in this workbench window.
* <p>
* Note that each window has its own pages; pages are never shared between
* different windows.
* </p>
*
* @return a list of pages
*/
virtual QList<SmartPointer<IWorkbenchPage> > GetPages() const = 0;
/**
* Returns the currently active page for this workbench window.
*
* @return the active page, or <code>null</code> if none
*/
SmartPointer<IWorkbenchPage> GetActivePage() const override = 0;
/**
* Sets or clears the currently active page for this workbench window.
*
* @param page
* the new active page
*/
virtual void SetActivePage(SmartPointer<IWorkbenchPage> page) = 0;
/**
* Returns the part service which tracks part activation within this
* workbench window.
*
* @return the part service
*/
virtual IPartService* GetPartService() = 0;
/**
* Returns the selection service which tracks selection within this
* workbench window.
*
* @return the selection service
*/
virtual ISelectionService* GetSelectionService() const = 0;
/**
* Returns this workbench window's shell.
*
* @return the shell containing this window's controls or <code>null</code>
* if the shell has not been created yet or if the window has been closed
*/
virtual Shell::Pointer GetShell() const = 0;
/**
* Returns the workbench for this window.
*
* @return the workbench
*/
virtual IWorkbench* GetWorkbench() const = 0;
/**
* Creates and opens a new workbench page. The perspective of the new page
* is defined by the specified perspective ID. The new page become active.
* <p>
* <b>Note:</b> Since release 2.0, a window is limited to contain at most
* one page. If a page exist in the window when this method is used, then
* another window is created for the new page. Callers are strongly
* recommended to use the <code>IWorkbench.showPerspective</code> APIs to
* programmatically show a perspective.
* </p>
*
* @param perspectiveId
* the perspective id for the window's initial page
* @param input
* the page input, or <code>null</code> if there is no current
* input. This is used to seed the input for the new page's
* views.
* @return the new workbench page
* @exception WorkbenchException
* if a page could not be opened
*
* @see IWorkbench#showPerspective(String, IWorkbenchWindow, IAdaptable)
*/
virtual SmartPointer<IWorkbenchPage> OpenPage(const QString& perspectiveId, IAdaptable* input) = 0;
/**
* Creates and opens a new workbench page. The default perspective is used
* as a template for creating the page. The page becomes active.
* <p>
* <b>Note:</b> Since release 2.0, a window is limited to contain at most
* one page. If a page exist in the window when this method is used, then
* another window is created for the new page. Callers are strongly
* recommended to use the <code>IWorkbench.showPerspective</code> APIs to
* programmatically show a perspective.
* </p>
*
* @param input
* the page input, or <code>null</code> if there is no current
* input. This is used to seed the input for the new page's
* views.
* @return the new workbench window
* @exception WorkbenchException
* if a page could not be opened
*
* @see IWorkbench#showPerspective(String, IWorkbenchWindow, IAdaptable)
*/
virtual SmartPointer<IWorkbenchPage> OpenPage(IAdaptable* input) = 0;
//virtual void SetPerspectiveExcludeList(const QStringList& v) = 0;
//virtual QStringList GetPerspectiveExcludeList() const = 0;
//virtual void SetViewExcludeList(const QStringList& v) = 0;
//virtual QStringList GetViewExcludeList() const = 0;
~IWorkbenchWindow() override;
};
}
#endif /*BERRYIWORKBENCHWINDOW_H_*/
diff --git a/Plugins/org.blueberry.ui.qt/src/berryWorkbenchPart.h b/Plugins/org.blueberry.ui.qt/src/berryWorkbenchPart.h
index 170ebf39d9..69cf519f19 100644
--- a/Plugins/org.blueberry.ui.qt/src/berryWorkbenchPart.h
+++ b/Plugins/org.blueberry.ui.qt/src/berryWorkbenchPart.h
@@ -1,251 +1,241 @@
/*============================================================================
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 __BERRY_WORKBENCH_PART_H__
#define __BERRY_WORKBENCH_PART_H__
#include "berryIWorkbenchPart.h"
#include "berryIWorkbenchPartSite.h"
#include <berryIConfigurationElement.h>
#include <berryIExecutableExtension.h>
#include <QIcon>
namespace berry {
/**
* \ingroup org_blueberry_ui_qt
*
* Abstract base implementation of all workbench parts.
* <p>
* This class is not intended to be subclassed by clients outside this
* package; clients should instead subclass <code>ViewPart</code> or
* <code>EditorPart</code>.
* </p>
*
* @see org.blueberry.ui.part.ViewPart
* @see org.blueberry.ui.part.EditorPart
*/
class BERRY_UI_QT WorkbenchPart : public QObject,
public virtual IWorkbenchPart, public IExecutableExtension
{
Q_OBJECT
Q_INTERFACES(berry::IExecutableExtension);
public:
berryObjectMacro(WorkbenchPart, QObject, IWorkbenchPart, IExecutableExtension);
~WorkbenchPart() override;
private:
QString m_Title;
QIcon m_TitleImage;
QString m_ToolTip;
IConfigurationElement::Pointer m_ConfigElement;
IWorkbenchPartSite::Pointer m_PartSite;
QString m_PartName;
QString m_ContentDescription;
QHash<QString, QString> partProperties;
IPropertyChangeListener::Events partChangeEvents;
void InternalSetContentDescription(const QString& description);
void InternalSetPartName(const QString& partName);
protected:
WorkbenchPart();
/**
* Returns the configuration element for this part. The configuration element
* comes from the plug-in registry entry for the extension defining this part.
*
* @return the configuration element for this part
*/
IConfigurationElement::Pointer GetConfigurationElement() const
{
return m_ConfigElement;
}
- /**
- * Returns the default title image.
- *
- * @return the default image
- */
-// protected Image getDefaultImage() {
-// return PlatformUI.getWorkbench().getSharedImages().getImage(
-// ISharedImages.IMG_DEF_VIEW);
-// }
-
/**
* Sets the part site.
- * <p>
+ *
* Subclasses must invoke this method from <code>IEditorPart.init</code>
* and <code>IViewPart.init</code>.
*
* @param site the workbench part site
*/
void SetSite(IWorkbenchPartSite::Pointer site);
/**
* Checks that the given site is valid for this type of part.
* The default implementation does nothing.
*
* @param site the site to check
*/
virtual void CheckSite(IWorkbenchPartSite::Pointer site);
/**
* Sets or clears the title image of this part.
*
* @param titleImage the title image, or <code>null</code> to clear
*/
virtual void SetTitleImage(const QIcon& titleImage);
/**
* Sets or clears the title tool tip text of this part. Clients should
* call this method instead of overriding <code>getTitleToolTip</code>
*
* @param toolTip the new tool tip text, or <code>null</code> to clear
*/
virtual void SetTitleToolTip(const QString& toolTip);
/**
* Sets the name of this part. The name will be shown in the tab area for
* the part. Clients should call this method instead of overriding getPartName.
* Setting this to the empty string will cause a default part name to be used.
*
* @param partName the part name, as it should be displayed in tabs.
*/
virtual void SetPartName(const QString& partName);
/**
* Sets the content description for this part. The content description is typically
* a short string describing the current contents of the part. Setting this to the
* empty string will cause a default content description to be used. Clients should
* call this method instead of overriding getContentDescription(). For views, the
* content description is shown (by default) in a line near the top of the view. For
* editors, the content description is shown beside the part name when showing a
* list of editors. If the editor is open on a file, this typically contains the path
* to the input file, without the filename or trailing slash.
*
* @param description the content description
*/
virtual void SetContentDescription(const QString& description);
void FirePropertyChanged(const QString& key,
const QString& oldValue, const QString& newValue);
void FirePropertyChange(int propertyId);
public:
/* (non-Javadoc)
* Method declared on IWorkbenchPart.
*/
void AddPropertyListener(IPropertyChangeListener* l) override;
void RemovePropertyListener(IPropertyChangeListener* l) override;
void SetPartProperty(const QString& key, const QString& value) override;
/* (non-Javadoc)
* @see org.blueberry.ui.IWorkbenchPart3#getPartProperty(java.lang.String)
*/
QString GetPartProperty(const QString& key) const override;
/* (non-Javadoc)
* @see org.blueberry.ui.IWorkbenchPart3#getPartProperties()
*/
const QHash<QString, QString>& GetPartProperties() const override;
/**
* {@inheritDoc}
* The <code>WorkbenchPart</code> implementation of this
* <code>IExecutableExtension</code> records the configuration element in
* and internal state variable (accessible via <code>getConfigElement</code>).
* It also loads the title image, if one is specified in the configuration element.
* Subclasses may extend.
*
* Should not be called by clients. It is called by the core plugin when creating
* this executable extension.
*/
void SetInitializationData(const IConfigurationElement::Pointer& cfig,
const QString& propertyName, const Object::Pointer& data) override;
/*
* Creates the controls for this workbench part.
* <p>
* Subclasses must implement this method. For a detailed description of the
* requirements see <code>IWorkbenchPart</code>
* </p>
*
* @param parent the parent control
* @see IWorkbenchPart
*/
void CreatePartControl(QWidget* parent) override = 0;
/* (non-Javadoc)
* Asks this part to take focus within the workbench.
* <p>
* Subclasses must implement this method. For a detailed description of the
* requirements see <code>IWorkbenchPart</code>
* </p>
*
* @see IWorkbenchPart
*/
void SetFocus() override = 0;
/*
* Method declared on IWorkbenchPart.
*/
IWorkbenchPartSite::Pointer GetSite() const override;
/**
* {@inheritDoc}
* <p>
* It is considered bad practise to overload or extend this method.
* Parts should call setPartName to change their part name.
* </p>
*/
QString GetPartName() const override;
/**
* {@inheritDoc}
* <p>
* It is considered bad practise to overload or extend this method.
* Parts should call setContentDescription to change their content description.
* </p>
*/
QString GetContentDescription() const override;
/* (non-Javadoc)
* Method declared on IWorkbenchPart.
*/
QIcon GetTitleImage() const override;
/* (non-Javadoc)
* Gets the title tool tip text of this part.
*
* @return the tool tip text
*/
QString GetTitleToolTip() const override;
};
} // namespace berry
#endif // __BERRY_WORKBENCH_PART_H__
diff --git a/Plugins/org.mitk.core.ext/CMakeLists.txt b/Plugins/org.mitk.core.ext/CMakeLists.txt
deleted file mode 100755
index 1eeffccb13..0000000000
--- a/Plugins/org.mitk.core.ext/CMakeLists.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-project(org_mitk_core_ext)
-
-mitk_create_plugin(
- EXPORT_DIRECTIVE MITKCOREEXT_EXPORT
- EXPORTED_INCLUDE_SUFFIXES src
- MODULE_DEPENDS MitkCore
-)
-
diff --git a/Plugins/org.mitk.core.ext/documentation/doxygen/modules.dox b/Plugins/org.mitk.core.ext/documentation/doxygen/modules.dox
deleted file mode 100755
index 746060c9f1..0000000000
--- a/Plugins/org.mitk.core.ext/documentation/doxygen/modules.dox
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- \defgroup org_mitk_core_ext org.mitk.core.ext
- \ingroup MITKPlugins
-
- \brief This small plug-in is responsible for initializing the MBI CoreExt module.
-
- It is started with an "eager" Bundle-ActivationPolicy, sucht that the plug-ins
- activator is executed before any other (non-eager) plug-ins.
-
-*/
-
-/**
- \defgroup org_mitk_core_ext_internal Internal
- \ingroup org_mitk_core_ext
-
- \brief This subcategory includes the internal classes of the org.mitk.core.ext plugin. Other
- plugins must not rely on these classes. They contain implementation details and their interface
- may change at any time. We mean it.
-*/
diff --git a/Plugins/org.mitk.core.ext/files.cmake b/Plugins/org.mitk.core.ext/files.cmake
deleted file mode 100755
index d16543df69..0000000000
--- a/Plugins/org.mitk.core.ext/files.cmake
+++ /dev/null
@@ -1,33 +0,0 @@
-
-set(SRC_CPP_FILES
- mitkCoreExtConstants.cpp
- mitkIInputDeviceDescriptor.h
- mitkIInputDeviceRegistry.h
- mitkIInputDevice.h
-)
-
-set(INTERNAL_CPP_FILES
- mitkCoreExtActivator.cpp
- mitkInputDeviceRegistry.cpp
- mitkInputDeviceDescriptor.cpp
-)
-
-set(CACHED_RESOURCE_FILES
- plugin.xml
-)
-
-set(MOC_H_FILES
- src/internal/mitkCoreExtActivator.h
- src/internal/mitkInputDeviceRegistry.h
-)
-
-set(CPP_FILES )
-
-foreach(file ${SRC_CPP_FILES})
- set(CPP_FILES ${CPP_FILES} src/${file})
-endforeach(file ${SRC_CPP_FILES})
-
-foreach(file ${INTERNAL_CPP_FILES})
- set(CPP_FILES ${CPP_FILES} src/internal/${file})
-endforeach(file ${INTERNAL_CPP_FILES})
-
diff --git a/Plugins/org.mitk.core.ext/manifest_headers.cmake b/Plugins/org.mitk.core.ext/manifest_headers.cmake
deleted file mode 100644
index 32a48a5359..0000000000
--- a/Plugins/org.mitk.core.ext/manifest_headers.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-set(Plugin-Name "MITK Extensions")
-set(Plugin-Version "0.1")
-set(Plugin-Vendor "German Cancer Research Center (DKFZ)")
-set(Plugin-ContactAddress "https://www.mitk.org")
-set(Require-Plugin org.blueberry.core.runtime)
diff --git a/Plugins/org.mitk.core.ext/plugin.xml b/Plugins/org.mitk.core.ext/plugin.xml
deleted file mode 100644
index 6b6ceeb06f..0000000000
--- a/Plugins/org.mitk.core.ext/plugin.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<plugin>
- <extension-point id="org.mitk.core.ext.inputdevices" name="Input Devices" schema="schema/inputdevice.exsd"/>
-</plugin>
diff --git a/Plugins/org.mitk.core.ext/schema/inputdevice.exsd b/Plugins/org.mitk.core.ext/schema/inputdevice.exsd
deleted file mode 100644
index cc2159a250..0000000000
--- a/Plugins/org.mitk.core.ext/schema/inputdevice.exsd
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<schema targetNamespace="org.mitk.core.ext" xmlns="http://www.w3.org/2001/XMLSchema">
-<annotation>
- <appinfo>
- <meta.schema plugin="org.mitk.core.ext" id="inputdevices" name="Input Devices"/>
- </appinfo>
-
- </annotation>
-
- <element name="extension">
- <annotation>
- <appinfo>
- <meta.element />
- </appinfo>
- </annotation>
- <complexType>
- <sequence>
- <element ref="inputdevice" minOccurs="0" maxOccurs="unbounded"/>
- </sequence>
- <attribute name="point" type="string" use="required">
- <annotation>
-
- </annotation>
- </attribute>
- <attribute name="id" type="string">
- <annotation>
-
- </annotation>
- </attribute>
- <attribute name="name" type="string">
- <annotation>
-
- <appinfo>
- <meta.attribute translatable="true"/>
- </appinfo>
- </annotation>
- </attribute>
- </complexType>
- </element>
-
- <element name="inputdevice">
- <annotation>
- <appinfo>
- <meta.element />
- </appinfo>
- </annotation>
- <complexType>
- <sequence>
- <element ref="description" minOccurs="0" maxOccurs="1"/>
- </sequence>
- <attribute name="id" type="string" use="required">
- <annotation>
-
- </annotation>
- </attribute>
- <attribute name="name" type="string">
- <annotation>
-
- <appinfo>
- <meta.attribute translatable="true"/>
- </appinfo>
- </annotation>
- </attribute>
- <attribute name="class" type="string" use="required">
- <annotation>
-
- <appinfo>
- <meta.attribute kind="java" basedOn="mitk::IInputDevice"/>
- </appinfo>
- </annotation>
- </attribute>
- </complexType>
- </element>
-
- <element name="description" type="string">
- <annotation>
- <appinfo>
- <meta.element translatable="true"/>
- </appinfo>
-
- </annotation>
- </element>
-
- <annotation>
- <appinfo>
- <meta.section type="examples"/>
- </appinfo>
-
- </annotation>
-
- <annotation>
- <appinfo>
- <meta.section type="apiInfo"/>
- </appinfo>
-
- </annotation>
-
-
- <annotation>
- <appinfo>
- <meta.section type="implementation"/>
- </appinfo>
-
- </annotation>
-
- <annotation>
- <appinfo>
- <meta.section type="copyright"/>
- </appinfo>
-
- </annotation>
-
-</schema>
diff --git a/Plugins/org.mitk.core.ext/src/internal/mitkCoreExtActivator.cpp b/Plugins/org.mitk.core.ext/src/internal/mitkCoreExtActivator.cpp
deleted file mode 100644
index 6f00d0b756..0000000000
--- a/Plugins/org.mitk.core.ext/src/internal/mitkCoreExtActivator.cpp
+++ /dev/null
@@ -1,67 +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 "mitkCoreExtActivator.h"
-
-#include "mitkCoreExtConstants.h"
-#include "mitkLogMacros.h"
-
-#include <ctkPluginContext.h>
-
-#include <mitkCoreServices.h>
-#include <mitkIPreferencesService.h>
-#include <mitkIPreferences.h>
-
-#include <usModuleInitialization.h>
-
-US_INITIALIZE_MODULE
-
-namespace mitk
-{
- void CoreExtActivator::start(ctkPluginContext* context)
- {
- Q_UNUSED(context)
-
- this->StartInputDeviceModules(context);
- }
-
- void CoreExtActivator::stop(ctkPluginContext* context)
- {
- Q_UNUSED(context)
- }
-
- void CoreExtActivator::StartInputDeviceModules(ctkPluginContext* context)
- {
- m_InputDeviceRegistry.reset(new InputDeviceRegistry());
- context->registerService<mitk::IInputDeviceRegistry>(m_InputDeviceRegistry.data());
-
- auto* prefService = mitk::CoreServices::GetPreferencesService();
- auto* extPreferencesNode = prefService->GetSystemPreferences()->Node(CoreExtConstants::INPUTDEVICE_PREFERENCES.toStdString());
-
- // Initializes the modules
- QList<IInputDeviceDescriptor::Pointer> descriptors(m_InputDeviceRegistry->GetInputDevices());
- for (QList<IInputDeviceDescriptor::Pointer>::const_iterator it = descriptors.begin();
- it != descriptors.end(); ++it)
- {
- if (extPreferencesNode->GetBool((*it)->GetID().toStdString(), false))
- {
- IInputDevice::Pointer temp = (*it)->CreateInputDevice();
- temp->RegisterInputDevice();
- }
- }
- }
-
- CoreExtActivator::~CoreExtActivator()
- {
- }
-
-} // end namespace mitk
diff --git a/Plugins/org.mitk.core.ext/src/internal/mitkCoreExtActivator.h b/Plugins/org.mitk.core.ext/src/internal/mitkCoreExtActivator.h
deleted file mode 100755
index 42a15fea33..0000000000
--- a/Plugins/org.mitk.core.ext/src/internal/mitkCoreExtActivator.h
+++ /dev/null
@@ -1,64 +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.
-
-============================================================================*/
-
-
-#ifndef mitkCoreExtActivator_h
-#define mitkCoreExtActivator_h
-
-#include <ctkPluginActivator.h>
-
-#include "mitkInputDeviceRegistry.h"
-
-namespace mitk
-{
-
- /**
- * @brief The activator class for the org.mitk.core.ext plug-in.
- * @ingroup org_mitk_core_ext_internal
- *
- * When the plug-in is started by the framework, it calls a global function to initialize
- * the mitkCoreExt module.
- *
- */
- class CoreExtActivator : public QObject, public ctkPluginActivator
- {
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org_mitk_core_ext")
- Q_INTERFACES(ctkPluginActivator)
-
- public:
-
- ~CoreExtActivator() override;
-
- /**
- * Starts this plug-in and registers object factories.
- *
- * @param context
- * The context for the plug-in.
- */
- void start(ctkPluginContext* context) override;
-
- void stop(ctkPluginContext* context) override;
-
- private:
-
- /**
- * Activates the input device modules.
- */
- void StartInputDeviceModules(ctkPluginContext *context);
-
- QScopedPointer<InputDeviceRegistry> m_InputDeviceRegistry;
-
- }; // end class CoreExtActivator
-} //end namespace mitk
-
-#endif
diff --git a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceDescriptor.cpp b/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceDescriptor.cpp
deleted file mode 100644
index d4c056a44a..0000000000
--- a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceDescriptor.cpp
+++ /dev/null
@@ -1,73 +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 "mitkInputDeviceDescriptor.h"
-#include "mitkCoreExtConstants.h"
-
-
-mitk::InputDeviceDescriptor::InputDeviceDescriptor(berry::IConfigurationElement::Pointer inputDeviceExtensionPoint)
-: IInputDeviceDescriptor(), m_InputDeviceExtensionPoint(inputDeviceExtensionPoint)
-{
-}
-
-mitk::InputDeviceDescriptor::~InputDeviceDescriptor()
-{
-}
-
-mitk::IInputDevice::Pointer mitk::InputDeviceDescriptor::CreateInputDevice()
-{
- if(this->m_InputDevice == 0)
- {
- // "class" refers to xml attribute in a xml tag
- this->m_InputDevice = this->m_InputDeviceExtensionPoint
- ->CreateExecutableExtension<mitk::IInputDevice>(mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_CLASS);
- if (this->m_InputDevice == 0)
- {
- // support legacy BlueBerry extensions
- this->m_InputDevice = this->m_InputDeviceExtensionPoint
- ->CreateExecutableExtension<IInputDevice>(mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_CLASS);
- }
- }
- return this->m_InputDevice;
-}
-
-QString mitk::InputDeviceDescriptor::GetID() const
-{
- return this->m_InputDeviceExtensionPoint->GetAttribute(mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_ID);
-}
-
-QString mitk::InputDeviceDescriptor::GetDescription() const
-{
- QList<berry::IConfigurationElement::Pointer>
- descriptions(this->m_InputDeviceExtensionPoint->GetChildren(mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_DESCRIPTION));
-
- if(!descriptions.empty())
- {
- return descriptions[0]->GetValue();
- }
- return QString();
-}
-
-QString mitk::InputDeviceDescriptor::GetName() const
-{
- return this->m_InputDeviceExtensionPoint->GetAttribute(mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_NAME);
-}
-
-bool mitk::InputDeviceDescriptor::operator==(const Object* object) const
-{
- if (const InputDeviceDescriptor* other = dynamic_cast<const InputDeviceDescriptor*>(object))
- {
- return this->GetID() == other->GetID();
- }
- return false;
-}
-
diff --git a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceDescriptor.h b/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceDescriptor.h
deleted file mode 100644
index d04d51aee0..0000000000
--- a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceDescriptor.h
+++ /dev/null
@@ -1,84 +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.
-
-============================================================================*/
-
-#ifndef mitkInputDeviceDescriptor_h
-#define mitkInputDeviceDescriptor_h
-
-#include <berryIConfigurationElement.h>
-
-#include <string>
-
-#include "mitkIInputDeviceDescriptor.h"
-#include "mitkIInputDevice.h"
-
-namespace mitk
-{
-
-/**
- * Documentation in the interface.
- *
- * @see mitk::IInputDeviceDescriptor
- * @ingroup org_mitk_core_ext
- */
-class InputDeviceDescriptor : public IInputDeviceDescriptor
-{
-
-public:
-
- /**
- * Initialize the Input Device Descriptor with the given extension point.
- *
- * @param inputDeviceExtensionPoint
- * element, that refers to a extension point (type, id, name, class)
- */
- InputDeviceDescriptor(berry::IConfigurationElement::Pointer inputDeviceExtensionPoint);
-
- /**
- * Default destructor
- */
- ~InputDeviceDescriptor() override;
-
- /**
- * @see mitk::IInputDeviceDescriptor::CreateInputDevice()
- */
- mitk::IInputDevice::Pointer CreateInputDevice() override;
-
- /**
- * @see mitk::IInputDeviceDescriptor::GetDescription()
- */
- QString GetDescription() const override;
-
- /**
- * @see mitk::IInputDeviceDescriptor::GetID()
- */
- QString GetID() const override;
-
- /**
- * @see mitk::IInputDeviceDescriptor::GetName()
- */
- QString GetName() const override;
-
- /**
- * @see mitk::IInputDeviceDescriptor::operator==(const Object* object)
- */
- bool operator==(const Object* object) const override;
-
-private:
-
- // IConfigurationElements are used to access xml files (here: plugin.xml)
- berry::IConfigurationElement::Pointer m_InputDeviceExtensionPoint;
- mitk::IInputDevice::Pointer m_InputDevice;
-
-}; // end class
-} // end namespace
-
-#endif
diff --git a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceRegistry.cpp b/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceRegistry.cpp
deleted file mode 100644
index c4dd08483d..0000000000
--- a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceRegistry.cpp
+++ /dev/null
@@ -1,65 +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 <berryPlatform.h>
-#include <berryIExtensionRegistry.h>
-#include <berryIConfigurationElement.h>
-
-#include <mitkCoreExtConstants.h>
-
-#include "mitkInputDeviceRegistry.h"
-#include "mitkInputDeviceDescriptor.h"
-
-
-mitk::InputDeviceRegistry::InputDeviceRegistry()
-{
- //initialize the registry by copying all available extension points into a local variable
- berry::IExtensionRegistry* extensionPointService = berry::Platform::GetExtensionRegistry();
- QList<berry::IConfigurationElement::Pointer> allExtensionsInputDevices
- = extensionPointService->GetConfigurationElementsFor(mitk::CoreExtConstants::INPUTDEVICE_EXTENSION_NAME);
-
- for(QList<berry::IConfigurationElement::Pointer>::const_iterator it = allExtensionsInputDevices.begin();
- it != allExtensionsInputDevices.end();++it)
- {
- InputDeviceDescriptorPtr temp(new mitk::InputDeviceDescriptor(*it));
-
- // The equation with the end means, that if there is no such element and
- // the pointer will be at end (not the last element, actually after it)
- if(this->m_ListRegisteredDevices.find(temp->GetID()) == this->m_ListRegisteredDevices.end())
- {
- m_ListRegisteredDevices.insert(temp->GetID(), temp);
- }
- else
- {
- throw ctkRuntimeException("The Input Device ID: " + temp->GetID() + " is already registered.");
- }
- }
-}
-
-mitk::InputDeviceRegistry::~InputDeviceRegistry()
-{
-}
-
-mitk::InputDeviceRegistry::InputDeviceDescriptorPtr mitk::InputDeviceRegistry::Find(const QString &id) const
-{
- QHash<QString,InputDeviceDescriptorPtr>::ConstIterator result = this->m_ListRegisteredDevices.find(id);
-
- // first = key, second = element or vice versa, if inserted different in the hash map
- if(result != this->m_ListRegisteredDevices.end()) return result.value();
-
- return InputDeviceDescriptorPtr(nullptr);
-}
-
-QList<mitk::InputDeviceRegistry::InputDeviceDescriptorPtr> mitk::InputDeviceRegistry::GetInputDevices() const
-{
- return m_ListRegisteredDevices.values();
-}
diff --git a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceRegistry.h b/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceRegistry.h
deleted file mode 100644
index 459c1f5e3a..0000000000
--- a/Plugins/org.mitk.core.ext/src/internal/mitkInputDeviceRegistry.h
+++ /dev/null
@@ -1,60 +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.
-
-============================================================================*/
-
-#ifndef mitkInputDeviceRegistry_h
-#define mitkInputDeviceRegistry_h
-
-#include <mitkIInputDeviceDescriptor.h>
-#include <mitkIInputDeviceRegistry.h>
-
-#include <QHash>
-
-namespace mitk
-{
- /**
- * Documentation in the interface.
- *
- * @see mitk::IInputDeviceRegistry
- * @ingroup org_mitk_core_ext
- */
- class InputDeviceRegistry : public QObject, public IInputDeviceRegistry
- {
- Q_OBJECT
- Q_INTERFACES(mitk::IInputDeviceRegistry)
-
- public:
-
- // easier maintenance
- typedef IInputDeviceDescriptor::Pointer InputDeviceDescriptorPtr;
-
- InputDeviceRegistry();
- ~InputDeviceRegistry() override;
-
- /**
- * @see mitk::IInputDeviceRegistry::Find(const std::string& id)
- */
- InputDeviceDescriptorPtr Find(const QString& id) const override;
-
- /**
- * @see mitk::IInputDeviceRegistry´::GetInputDevices()
- */
- QList<InputDeviceDescriptorPtr> GetInputDevices() const override;
-
- protected:
-
- private:
- QHash<QString, InputDeviceDescriptorPtr> m_ListRegisteredDevices;
-
- }; // end class InputDeviceRegistry
-} // end namespace mitk
-
-#endif
diff --git a/Plugins/org.mitk.core.ext/src/mitkCoreExtConstants.cpp b/Plugins/org.mitk.core.ext/src/mitkCoreExtConstants.cpp
deleted file mode 100644
index b88cd9ec1b..0000000000
--- a/Plugins/org.mitk.core.ext/src/mitkCoreExtConstants.cpp
+++ /dev/null
@@ -1,24 +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 <mitkCoreExtConstants.h>
-
-const QString mitk::CoreExtConstants::INPUTDEVICE_SERVICE = "org.mitk.core.ext.services.inputdeviceregistry";
-const QString mitk::CoreExtConstants::INPUTDEVICE_PREFERENCES = "org.mitk.core.ext.preferences.inputdevices";
-const QString mitk::CoreExtConstants::INPUTDEVICE_EXTENSION_NAME = "org.mitk.core.ext.inputdevices";
-const QString mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_CLASS = "class";
-const QString mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_DESCRIPTION = "description";
-const QString mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_NAME = "name";
-const QString mitk::CoreExtConstants::INPUTDEVICE_XMLATTRIBUTE_ID = "id";
-const QString mitk::CoreExtConstants::WIIMOTE_SURFACEINTERACTION = "Surface Interaction";
-const QString mitk::CoreExtConstants::WIIMOTE_HEADTRACKING = "Headtracking";
-const QString mitk::CoreExtConstants::WIIMOTE_XMLATTRIBUTE_NAME = "org.mitk.inputdevices.wiimote";
diff --git a/Plugins/org.mitk.core.ext/src/mitkCoreExtConstants.h b/Plugins/org.mitk.core.ext/src/mitkCoreExtConstants.h
deleted file mode 100644
index 4971b71e7b..0000000000
--- a/Plugins/org.mitk.core.ext/src/mitkCoreExtConstants.h
+++ /dev/null
@@ -1,49 +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.
-
-============================================================================*/
-
-#ifndef mitkCoreExtConstants_h
-#define mitkCoreExtConstants_h
-
-#include <QString>
-
-#include <org_mitk_core_ext_Export.h>
-
-namespace mitk
-{
- /**
- * The CoreExt Constants contains a list of unique ids in the following form: <br>
- * "org.mitk.mybundle.mytype.propername" <br>
- *
- * This ids have the purpose of connecting the plugin.xml of each bundle to the
- * appropriate classes.
- *
- * Additionally it includes names of tags, which are used in XML files <br>
- * regarding any input device.
- *
- * @ingroup org_mitk_core_ext
- */
- struct MITKCOREEXT_EXPORT CoreExtConstants
- {
- static const QString INPUTDEVICE_SERVICE;
- static const QString INPUTDEVICE_PREFERENCES;
- static const QString INPUTDEVICE_EXTENSION_NAME;
- static const QString INPUTDEVICE_XMLATTRIBUTE_CLASS;
- static const QString INPUTDEVICE_XMLATTRIBUTE_DESCRIPTION;
- static const QString INPUTDEVICE_XMLATTRIBUTE_NAME;
- static const QString INPUTDEVICE_XMLATTRIBUTE_ID;
- static const QString WIIMOTE_SURFACEINTERACTION;
- static const QString WIIMOTE_HEADTRACKING;
- static const QString WIIMOTE_XMLATTRIBUTE_NAME;
- };
-}
-
-#endif
diff --git a/Plugins/org.mitk.core.ext/src/mitkIInputDevice.h b/Plugins/org.mitk.core.ext/src/mitkIInputDevice.h
deleted file mode 100644
index ccb40e8385..0000000000
--- a/Plugins/org.mitk.core.ext/src/mitkIInputDevice.h
+++ /dev/null
@@ -1,52 +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.
-
-============================================================================*/
-
-#ifndef mitkIInputDevice_h
-#define mitkIInputDevice_h
-
-#include <berryObject.h>
-#include <berryMacros.h>
-
-#include <vector>
-
-namespace mitk
-{
- /**
- * An input device provides a method to register and unregister itself. Meaning <br>
- * for example adding listeners and instianciate classes necessary to use the input device.
- *
- * @note This interface is not intended to be implemented by clients.
- * @ingroup org_mitk_core_ext
- */
- struct IInputDevice : public berry::Object
- {
-
- berryObjectMacro(mitk::IInputDevice);
-
- /**
- * Register the input device at one or more instances.
- */
- virtual bool RegisterInputDevice() = 0;
-
- /**
- * Unregister the input device at one or more instances.
- */
- virtual bool UnRegisterInputDevice() = 0;
-
- ~IInputDevice() override {}
-
- }; // end struct IInputDevice
-} // end namespace mitk
-
-Q_DECLARE_INTERFACE(mitk::IInputDevice, "org.mitk.IInputDevice")
-
-#endif
diff --git a/Plugins/org.mitk.core.ext/src/mitkIInputDeviceDescriptor.h b/Plugins/org.mitk.core.ext/src/mitkIInputDeviceDescriptor.h
deleted file mode 100644
index ab24f45834..0000000000
--- a/Plugins/org.mitk.core.ext/src/mitkIInputDeviceDescriptor.h
+++ /dev/null
@@ -1,86 +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.
-
-============================================================================*/
-
-#ifndef mitkIInputDeviceDescriptor_h
-#define mitkIInputDeviceDescriptor_h
-
-#include <berryObject.h>
-#include <berryMacros.h>
-
-#include "mitkIInputDevice.h"
-
-namespace mitk
-{
- /**
- * This is an input device descriptor. It provides a "description" of a given
- * input device, so that the input device can later be constructed and registered.
- * <p>
- * The input device registry provides facilities to map from an extension
- * to a IInputDeviceDescriptor.
- * </p>
- * <p>
- * This interface is not intended to be implemented by clients.
- * </p>
- *
- * @see mitk::IInputDeviceRegistry
- * @ingroup org_mitk_core_ext
- */
- struct IInputDeviceDescriptor : public berry::Object
- {
-
- berryObjectMacro(mitk::IInputDeviceDescriptor);
-
- /**
- * Creates an instance of an input device defined in the descriptor.
- *
- * @return the input device
- */
- virtual IInputDevice::Pointer CreateInputDevice() = 0;
-
- /**
- * Returns the description of this input device.
- *
- * @return the description
- */
- virtual QString GetDescription() const = 0;
-
- /**
- * Returns the id of this input device.
- *
- * @return the id
- */
- virtual QString GetID() const = 0;
-
- /**
- * Returns the name of this input device.
- *
- * @return the name
- */
- virtual QString GetName() const = 0;
-
- // /**
- // * Returns the descriptor for the icon to show for this view.
- // */
- //virtual SmartPointer<ImageDescriptor> GetImageDescriptor() const = 0;
-
- /**
- * Equals this class with the given parameter.
- *
- * @param object the object for the equation
- * @return true, if the objects are equal :: false, if they differ in any way
- */
- bool operator==(const Object* object) const override = 0;
-
- }; // end struct IInputDeviceDescriptor
-} //end namespace mitk
-
-#endif
diff --git a/Plugins/org.mitk.core.ext/src/mitkIInputDeviceRegistry.h b/Plugins/org.mitk.core.ext/src/mitkIInputDeviceRegistry.h
deleted file mode 100644
index 1d59a8505c..0000000000
--- a/Plugins/org.mitk.core.ext/src/mitkIInputDeviceRegistry.h
+++ /dev/null
@@ -1,64 +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.
-
-============================================================================*/
-
-#ifndef mitkIInputDeviceRegistry_h
-#define mitkIInputDeviceRegistry_h
-
-#include <QtPlugin>
-
-#include "mitkIInputDeviceDescriptor.h"
-
-namespace mitk
-{
- /**
- *
- * The input device registry maintains a list of input devices explicitly registered
- * against the view extension point.
- * <p>
- * The description of a given input device is kept in a <code>IInputDeviceDescriptor</code>.
- * </p>
- * <p>
- * This interface is not intended to be implemented by clients.
- * </p>
- *
- * @see mitk::IInputDeviceDescriptor
- * @note This interface is not intended to be implemented by clients.
- * @ingroup org_mitk_core_ext
- */
- struct IInputDeviceRegistry
- {
-
- /**
- * Return an input device descriptor with the given extension id. If no input device exists,
- * with the id return <code>null</code>.
- *
- * @param id
- * the id to search for
- * @return the descriptor or <code>null</code>
- */
- virtual IInputDeviceDescriptor::Pointer Find(const QString& id) const = 0;
-
- /**
- * Return a list of input devices defined in the registry.
- *
- * @return the input devices.
- */
- virtual QList<IInputDeviceDescriptor::Pointer> GetInputDevices() const = 0;
-
- virtual ~IInputDeviceRegistry() {}
-
- }; // end struct IInputDeviceRegistry
-} // end namespace mitk
-
-Q_DECLARE_INTERFACE(mitk::IInputDeviceRegistry, "org.mitk.service.IInputDeviceRegistry")
-
-#endif
diff --git a/Plugins/org.mitk.core.ext/src/mitkInputDeviceDescriptor.h b/Plugins/org.mitk.core.ext/src/mitkInputDeviceDescriptor.h
deleted file mode 100644
index 25e99a8bbb..0000000000
--- a/Plugins/org.mitk.core.ext/src/mitkInputDeviceDescriptor.h
+++ /dev/null
@@ -1,83 +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.
-
-============================================================================*/
-
-#ifndef mitkInputDeviceDescriptor_h
-#define mitkInputDeviceDescriptor_h
-
-#include <berryIConfigurationElement.h>
-
-#include <string>
-
-#include "mitkIInputDeviceDescriptor.h"
-#include "mitkIInputDevice.h"
-
-namespace mitk
-{
- /**
- * Documentation in the interface.
- *
- * @see mitk::IInputDeviceDescriptor
- * @ingroup org_mitk_core_ext
- */
- class InputDeviceDescriptor : public IInputDeviceDescriptor
- {
-
- public:
-
- /**
- * Initialize the Input Device Descriptor with the given extension point.
- *
- * @param inputDeviceExtensionPoint
- * element, that refers to a extension point (type, id, name, class)
- */
- InputDeviceDescriptor(berry::IConfigurationElement::Pointer inputDeviceExtensionPoint);
-
- /**
- * Default destructor
- */
- ~InputDeviceDescriptor();
-
- /**
- * @see mitk::IInputDeviceDescriptor::CreateInputDevice()
- */
- mitk::IInputDevice::Pointer CreateInputDevice();
-
- /**
- * @see mitk::IInputDeviceDescriptor::GetDescription()
- */
- std::string GetDescription() const;
-
- /**
- * @see mitk::IInputDeviceDescriptor::GetID()
- */
- std::string GetID() const;
-
- /**
- * @see mitk::IInputDeviceDescriptor::GetName()
- */
- std::string GetName() const;
-
- /**
- * @see mitk::IInputDeviceDescriptor::operator==(const Object* object)
- */
- bool operator==(const Object* object) const;
-
- private:
-
- // IConfigurationElements are used to access xml files (here: plugin.xml)
- berry::IConfigurationElement::Pointer m_InputDeviceExtensionPoint;
- mitk::IInputDevice::Pointer m_InputDevice;
-
- }; // end class
-} // end namespace
-
-#endif
diff --git a/Plugins/org.mitk.core.services/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.core.services/src/internal/mitkPluginActivator.cpp
index fb3e6f8aec..8451387d1f 100644
--- a/Plugins/org.mitk.core.services/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.core.services/src/internal/mitkPluginActivator.cpp
@@ -1,283 +1,283 @@
/*============================================================================
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 "mitkPluginActivator.h"
-#include "mitkLog.h"
+#include <mitkLogBackend.h>
#include <QString>
#include <QFileInfo>
#include "internal/mitkDataStorageService.h"
#include <usModuleRegistry.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <mitkVtkLoggingAdapter.h>
#include <mitkItkLoggingAdapter.h>
namespace mitk
{
class InterfaceMapToQObjectAdapter : public QObject
{
public:
InterfaceMapToQObjectAdapter(const us::InterfaceMap& im)
: interfaceMap(im)
{}
// This method is called by the Qt meta object system. It is usually
// generated by the moc, but we create it manually to be able to return
// a MITK micro service object (derived from itk::LightObject). It basically
// works as if the micro service class had used the Q_INTERFACES macro in
// its declaration. Now we can successfully do a
// qobject_cast<mitk::SomeMicroServiceInterface>(lightObjectToQObjectAdapter)
void* qt_metacast(const char *_clname) override
{
if (!_clname) return nullptr;
if (!strcmp(_clname, "InterfaceMapToQObjectAdapter"))
return static_cast<void*>(const_cast<InterfaceMapToQObjectAdapter*>(this));
us::InterfaceMap::const_iterator iter = interfaceMap.find(_clname);
if (iter != interfaceMap.end())
return iter->second;
return QObject::qt_metacast(_clname);
}
private:
us::InterfaceMap interfaceMap;
};
const std::string org_mitk_core_services_Activator::PLUGIN_ID = "org.mitk.core.services";
void org_mitk_core_services_Activator::start(ctkPluginContext* context)
{
pluginContext = context;
//initialize logging
- mitk::LoggingBackend::Register();
+ mitk::LogBackend::Register();
QString logFilenamePrefix = "mitk";
QFileInfo path = context->getDataFile(logFilenamePrefix);
try
{
// using local8bit, because ofstream is not unicode aware (at least on windows)
// to use utf-8 with ofstream it's possible to use "nowide.boots" lib
- mitk::LoggingBackend::RotateLogFiles(path.absoluteFilePath().toLocal8Bit().constData());
+ mitk::LogBackend::RotateLogFiles(path.absoluteFilePath().toLocal8Bit().constData());
}
catch(mitk::Exception& e)
{
MITK_ERROR << "Problem during logfile initialization: " << e.GetDescription() << " Caution: Logging to harddisc might be disabled!";
}
mitk::VtkLoggingAdapter::Initialize();
mitk::ItkLoggingAdapter::Initialize();
//initialize data storage service
dataStorageService.reset(new DataStorageService());
context->registerService<mitk::IDataStorageService>(dataStorageService.data());
// Get the MitkCore Module Context
mitkContext = us::ModuleRegistry::GetModule(1)->GetModuleContext();
// Process all already registered services
std::vector<us::ServiceReferenceU> refs = mitkContext->GetServiceReferences("");
for (std::vector<us::ServiceReferenceU>::const_iterator i = refs.begin();
i != refs.end(); ++i)
{
this->AddMitkService(*i);
}
mitkContext->AddServiceListener(this, &org_mitk_core_services_Activator::MitkServiceChanged);
}
void org_mitk_core_services_Activator::stop(ctkPluginContext* /*context*/)
{
mitkContext->RemoveServiceListener(this, &org_mitk_core_services_Activator::MitkServiceChanged);
foreach(ctkServiceRegistration reg, mapMitkIdToRegistration.values())
{
reg.unregister();
}
mapMitkIdToRegistration.clear();
qDeleteAll(mapMitkIdToAdapter);
mapMitkIdToAdapter.clear();
//clean up logging
- mitk::LoggingBackend::Unregister();
+ mitk::LogBackend::Unregister();
dataStorageService.reset();
mitkContext = nullptr;
pluginContext = nullptr;
}
void org_mitk_core_services_Activator::MitkServiceChanged(const us::ServiceEvent event)
{
switch (event.GetType())
{
case us::ServiceEvent::REGISTERED:
{
this->AddMitkService(event.GetServiceReference());
break;
}
case us::ServiceEvent::UNREGISTERING:
{
long mitkServiceId = us::any_cast<long>(event.GetServiceReference().GetProperty(us::ServiceConstants::SERVICE_ID()));
ctkServiceRegistration reg = mapMitkIdToRegistration.take(mitkServiceId);
if (reg)
{
reg.unregister();
}
delete mapMitkIdToAdapter.take(mitkServiceId);
break;
}
case us::ServiceEvent::MODIFIED:
{
long mitkServiceId = us::any_cast<long>(event.GetServiceReference().GetProperty(us::ServiceConstants::SERVICE_ID()));
ctkDictionary newProps = CreateServiceProperties(event.GetServiceReference());
mapMitkIdToRegistration[mitkServiceId].setProperties(newProps);
break;
}
default:
break; // do nothing
}
}
void org_mitk_core_services_Activator::AddMitkService(const us::ServiceReferenceU& ref)
{
// Get the MITK micro service object
us::InterfaceMap mitkService = mitkContext->GetService(ref);
if (mitkService.empty()) return;
// Get the interface names against which the service was registered
QStringList qclazzes;
for(us::InterfaceMap::const_iterator clazz = mitkService.begin();
clazz != mitkService.end(); ++clazz)
{
qclazzes << QString::fromStdString(clazz->first);
}
long mitkServiceId = us::any_cast<long>(ref.GetProperty(us::ServiceConstants::SERVICE_ID()));
QObject* adapter = new InterfaceMapToQObjectAdapter(mitkService);
mapMitkIdToAdapter[mitkServiceId] = adapter;
ctkDictionary props = CreateServiceProperties(ref);
mapMitkIdToRegistration[mitkServiceId] = pluginContext->registerService(qclazzes, adapter, props);
}
ctkDictionary org_mitk_core_services_Activator::CreateServiceProperties(const us::ServiceReferenceU& ref)
{
ctkDictionary props;
long mitkServiceId = us::any_cast<long>(ref.GetProperty(us::ServiceConstants::SERVICE_ID()));
props.insert("mitk.serviceid", QVariant::fromValue(mitkServiceId));
// Add all other properties from the MITK micro service
std::vector<std::string> keys;
ref.GetPropertyKeys(keys);
for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it)
{
QString key = QString::fromStdString(*it);
us::Any value = ref.GetProperty(*it);
// We cannot add any mitk::Any object, we need to query the type
const std::type_info& objType = value.Type();
if (objType == typeid(std::string))
{
props.insert(key, QString::fromStdString(us::ref_any_cast<std::string>(value)));
}
else if (objType == typeid(std::vector<std::string>))
{
const std::vector<std::string>& list = us::ref_any_cast<std::vector<std::string> >(value);
QStringList qlist;
for (std::vector<std::string>::const_iterator str = list.begin();
str != list.end(); ++str)
{
qlist << QString::fromStdString(*str);
}
props.insert(key, qlist);
}
else if (objType == typeid(std::list<std::string>))
{
const std::list<std::string>& list = us::ref_any_cast<std::list<std::string> >(value);
QStringList qlist;
for (std::list<std::string>::const_iterator str = list.begin();
str != list.end(); ++str)
{
qlist << QString::fromStdString(*str);
}
props.insert(key, qlist);
}
else if (objType == typeid(char))
{
props.insert(key, QChar(us::ref_any_cast<char>(value)));
}
else if (objType == typeid(unsigned char))
{
props.insert(key, QChar(us::ref_any_cast<unsigned char>(value)));
}
else if (objType == typeid(bool))
{
props.insert(key, us::any_cast<bool>(value));
}
else if (objType == typeid(short))
{
props.insert(key, us::any_cast<short>(value));
}
else if (objType == typeid(unsigned short))
{
props.insert(key, us::any_cast<unsigned short>(value));
}
else if (objType == typeid(int))
{
props.insert(key, us::any_cast<int>(value));
}
else if (objType == typeid(unsigned int))
{
props.insert(key, us::any_cast<unsigned int>(value));
}
else if (objType == typeid(float))
{
props.insert(key, us::any_cast<float>(value));
}
else if (objType == typeid(double))
{
props.insert(key, us::any_cast<double>(value));
}
else if (objType == typeid(long long int))
{
props.insert(key, us::any_cast<long long int>(value));
}
else if (objType == typeid(unsigned long long int))
{
props.insert(key, us::any_cast<unsigned long long int>(value));
}
}
return props;
}
org_mitk_core_services_Activator::org_mitk_core_services_Activator()
: mitkContext(nullptr), pluginContext(nullptr)
{
}
org_mitk_core_services_Activator::~org_mitk_core_services_Activator()
{
}
}
diff --git a/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h b/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h
index f8726b2183..38bd85cbb5 100644
--- a/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h
+++ b/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h
@@ -1,230 +1,230 @@
/*============================================================================
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 mitkIRenderWindowPart_h
#define mitkIRenderWindowPart_h
#include <QString>
#include <QStringList>
#include <QHash>
#include <QtPlugin>
#include <mitkBaseRenderer.h>
#include <mitkNumericTypes.h>
#include <mitkRenderingManager.h>
#include <org_mitk_gui_common_Export.h>
class QmitkRenderWindow;
namespace mitk {
struct IRenderingManager;
-class SliceNavigationController;
+class TimeNavigationController;
/**
* \ingroup org_mitk_gui_common
*
* \brief Interface for a MITK Workbench Part providing a render window.
*
* This interface allows generic access to Workbench parts which provide some
* kind of render window. The interface is intended to be implemented by
* subclasses of berry::IWorkbenchPart. Usually, the interface is implemented
* by a Workbench editor.
*
* A IRenderWindowPart provides zero or more QmitkRenderWindow instances which can
* be controlled via this interface. QmitkRenderWindow instances have an associated
* \e id, which is implementation specific.
* Additionally the defined values Axial, Sagittal, Coronal and Original from mitk::AnatomicalPlane
* can be used to retrieve a specific QmitkRenderWindow.
*
* \see ILinkedRenderWindowPart
* \see IRenderWindowPartListener
* \see QmitkAbstractRenderEditor
*/
struct MITK_GUI_COMMON_PLUGIN IRenderWindowPart {
static const QString DECORATION_BORDER; // = "border"
static const QString DECORATION_LOGO; // = "logo"
static const QString DECORATION_MENU; // = "menu"
static const QString DECORATION_BACKGROUND; // = "background"
static const QString DECORATION_CORNER_ANNOTATION; // = "corner annotation"
virtual ~IRenderWindowPart();
/**
* Get the currently active (focused) render window.
* Focus handling is implementation specific.
*
* \return The active QmitkRenderWindow instance; <code>nullptr</code>
* if no render window is active.
*/
virtual QmitkRenderWindow* GetActiveQmitkRenderWindow() const = 0;
/**
* Get all render windows with their ids.
*
* \return A hash map mapping the render window id to the QmitkRenderWindow instance.
*/
virtual QHash<QString,QmitkRenderWindow*> GetQmitkRenderWindows() const = 0;
/**
* Get a render window with a specific id.
*
* \param id The render window id.
* \return The QmitkRenderWindow instance for <code>id</code>
*/
virtual QmitkRenderWindow* GetQmitkRenderWindow(const QString& id) const = 0;
/**
* Get a render window with a specific plane orientation.
*
* \param orientation The render window plane orientation.
* \return The QmitkRenderWindow instance for <code>orientation</code>
*/
virtual QmitkRenderWindow* GetQmitkRenderWindow(const mitk::AnatomicalPlane& orientation) const = 0;
/**
* Get the rendering manager used by this render window part.
*
* \return The current IRenderingManager instance or <code>nullptr</code>
* if no rendering manager is used.
*/
virtual mitk::IRenderingManager* GetRenderingManager() const = 0;
/**
* Request an update of all render windows.
*
* \param requestType Specifies the type of render windows for which an update
* will be requested.
*/
virtual void RequestUpdate(mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL) = 0;
/**
* Force an immediate update of all render windows.
*
* \param requestType Specifies the type of render windows for which an immediate update
* will be requested.
*/
virtual void ForceImmediateUpdate(mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL) = 0;
/**
* @brief Initialize the render windows of this render window part to the given geometry.
*
* @param geometry The geometry to be used to initialize / update a
* render window's time and slice navigation controller.
* @param resetCamera If true, the camera and crosshair will be reset to the default view (centered, no zoom).
* If false, the current crosshair position and the camera zoom will be stored and reset
* after the reference geometry has been updated.
*/
virtual void InitializeViews(const mitk::TimeGeometry* geometry, bool resetCamera) = 0;
/**
* @brief Define the reference geometry for interaction withing a render window.
*
* The concrete implementation is subclass-specific, no default implementation is provided here.
* An implementation can be found in 'QmitkAbstractMultiWidgetEditor' and will just
* forward the argument to the contained multi widget.
*
* @param referenceGeometry The interaction reference geometry for the concrete multi widget.
* For more details, see 'BaseRenderer::SetInteractionReferenceGeometry'.
*/
virtual void SetInteractionReferenceGeometry(const mitk::TimeGeometry* referenceGeometry) = 0;
/**
* @brief Returns true if the render windows are coupled; false if not.
*
* Render windows are coupled if the slice navigation controller of the render windows
* are connected which means that always the same geometry is used for the render windows.
*/
virtual bool HasCoupledRenderWindows() const = 0;
/**
- * Get the SliceNavigationController for controlling time positions.
+ * Get the TimeNavigationController for controlling time positions.
*
- * \return A SliceNavigationController if the render window supports this
+ * \return A TimeNavigationController if the render window supports this
* operation; otherwise returns <code>nullptr</code>.
*/
- virtual mitk::SliceNavigationController* GetTimeNavigationController() const = 0;
+ virtual mitk::TimeNavigationController* GetTimeNavigationController() const = 0;
/**
* Get the selected position in the render window with id <code>id</code>
* or in the active render window if <code>id</code> is an empty string.
*
* \param id The render window id.
* \return The currently selected position in world coordinates.
*/
virtual mitk::Point3D GetSelectedPosition(const QString& id = QString()) const = 0;
/**
* Set the selected position in the render window with id <code>id</code>
* or in the active render window if <code>id</code> is nullptr.
*
* \param pos The position in world coordinates which should be selected.
* \param id The render window id in which the selection should take place.
*/
virtual void SetSelectedPosition(const mitk::Point3D& pos, const QString& id = QString()) = 0;
/**
* Get the time point selected in the render window with id <code>id</code>
* or in the active render window if <code>id</code> is an empty string.
*
* \param id The render window id.
* \return The currently selected position in world coordinates.
*/
virtual TimePointType GetSelectedTimePoint(const QString& id = QString()) const = 0;
/**
* Enable \e decorations like colored borders, menu widgets, logos, text annotations, etc.
*
* Decorations are implementation specific. A set of standardized decoration names is listed
* in GetDecorations().
*
* \param enable If <code>true</code> enable the decorations specified in <code>decorations</code>,
* otherwise disable them.
* \param decorations A list of decoration names. If empty, all supported decorations are affected.
*
* \see GetDecorations()
*/
virtual void EnableDecorations(bool enable, const QStringList& decorations = QStringList()) = 0;
/**
* Return if a specific decoration is enabled.
*
* \return <code>true</code> if the decoration is enabled, <code>false</code> if it is disabled
* or unknown.
*
* \see GetDecorations()
*/
virtual bool IsDecorationEnabled(const QString& decoration) const = 0;
/**
* Get a list of supported decorations.
*
* The following decoration names are standardized and should not be used for other decoration types:
* <ul>
* <li>\e DECORATION_BORDER Any border decorations like colored rectangles, etc.
* <li>\e DECORATION_MENU Menus associated with render windows
* <li>\e DECORATION_BACKGROUND All kinds of backgrounds (patterns, gradients, etc.) except for solid colored backgrounds
* <li>\e DECORATION_LOGO Any kind of logo overlayed on the rendered scene
* </ul>
*
* \return A list of supported decoration names.
*/
virtual QStringList GetDecorations() const = 0;
};
}
Q_DECLARE_INTERFACE(mitk::IRenderWindowPart, "org.mitk.ui.IRenderWindowPart")
#endif
diff --git a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp
index f161ae9e2f..78d48b5cf9 100644
--- a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp
+++ b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.cpp
@@ -1,179 +1,179 @@
/*============================================================================
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 "mitkIRenderingManager.h"
namespace mitk {
struct RenderingManagerInterface : public IRenderingManager
{
RenderingManagerInterface(RenderingManager::Pointer manager)
: m_RM(manager)
{}
QList<vtkRenderWindow*> GetAllRegisteredVtkRenderWindows() const override
{
RenderingManager::RenderWindowVector vec(m_RM->GetAllRegisteredRenderWindows());
QList<vtkRenderWindow*> result;
for (auto i = vec.begin();
i != vec.end(); ++i)
{
result.append(*i);
}
return result;
}
void RequestUpdate( vtkRenderWindow *renderWindow ) override
{
m_RM->RequestUpdate(renderWindow);
}
void ForceImmediateUpdate( vtkRenderWindow *renderWindow ) override
{
m_RM->ForceImmediateUpdate(renderWindow);
}
void RequestUpdateAll( RenderingManager::RequestType type ) override
{
m_RM->RequestUpdateAll(type);
}
void ForceImmediateUpdateAll( RenderingManager::RequestType type ) override
{
m_RM->ForceImmediateUpdateAll(type);
}
bool InitializeViews( const BaseGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false ) override
{
return m_RM->InitializeViews( geometry, type, preserveRoughOrientationInWorldSpace);
}
bool InitializeViews( const TimeGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false ) override
{
return m_RM->InitializeViews( geometry, type, preserveRoughOrientationInWorldSpace);
}
bool InitializeViews( RenderingManager::RequestType type ) override
{
return m_RM->InitializeViews(type);
}
bool InitializeView( vtkRenderWindow *renderWindow, const BaseGeometry *geometry,
bool initializeGlobalTimeSNC = false) override
{
return m_RM->InitializeView(renderWindow, geometry, initializeGlobalTimeSNC);
}
bool InitializeView( vtkRenderWindow *renderWindow ) override
{
return m_RM->InitializeView(renderWindow);
}
- const SliceNavigationController *GetTimeNavigationController() const override
+ const TimeNavigationController* GetTimeNavigationController() const override
{
return m_RM->GetTimeNavigationController();
}
- SliceNavigationController *GetTimeNavigationController() override
+ TimeNavigationController* GetTimeNavigationController() override
{
return m_RM->GetTimeNavigationController();
}
bool IsRendering() const override
{
return m_RM->IsRendering();
}
void AbortRendering() override
{
m_RM->AbortRendering();
}
void SetLODIncreaseBlocked(bool blocked) override
{
m_RM->SetLODIncreaseBlocked(blocked);
}
bool GetLODIncreaseBlocked() const override
{
return m_RM->GetLODIncreaseBlocked();
}
void SetLODAbortMechanismEnabled(bool abort) override
{
m_RM->SetLODAbortMechanismEnabled(abort);
}
bool GetLODAbortMechanismEnabled() const override
{
return m_RM->GetLODAbortMechanismEnabled();
}
int GetNextLOD( BaseRenderer* renderer ) const override
{
return m_RM->GetNextLOD(renderer);
}
void SetMaximumLOD( unsigned int max ) override
{
m_RM->SetMaximumLOD(max);
}
void SetShading( bool state, unsigned int lod ) override
{
m_RM->SetShading(state, lod);
}
bool GetShading( unsigned int lod ) override
{
return m_RM->GetShading(lod);
}
void SetClippingPlaneStatus( bool status ) override
{
m_RM->SetClippingPlaneStatus(status);
}
bool GetClippingPlaneStatus() override
{
return m_RM->GetClippingPlaneStatus();
}
void SetShadingValues( float ambient, float diffuse,
float specular, float specpower ) override
{
m_RM->SetShadingValues(ambient, diffuse, specular, specpower);
}
QList<float> GetShadingValues() const override
{
RenderingManager::FloatVector vec(m_RM->GetShadingValues());
QList<float> result;
for (auto i = vec.begin();
i != vec.end(); ++i)
{
result.push_back(*i);
}
return result;
}
const RenderingManager::Pointer m_RM;
};
IRenderingManager* MakeRenderingManagerInterface(RenderingManager::Pointer manager)
{
return new RenderingManagerInterface(manager);
}
}
diff --git a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h
index 38c959f376..34dfd88e42 100644
--- a/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h
+++ b/Plugins/org.mitk.gui.common/src/mitkIRenderingManager.h
@@ -1,144 +1,144 @@
/*============================================================================
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 mitkIRenderingManager_h
#define mitkIRenderingManager_h
#include <mitkRenderingManager.h>
#include <org_mitk_gui_common_Export.h>
#include <QList>
#include <QtPlugin>
namespace mitk {
/**
* \ingroup org_mitk_gui_common
*
* \brief An interface for accessing a mitk::RenderingManager instance.
*
* This interface acts as a wrapper to a mitk::RenderingManager instance, hiding some
* methods from the user.
*
* \see MakeRenderingManagerInterface
*/
struct IRenderingManager {
virtual ~IRenderingManager() {}
/** Get a list of all registered RenderWindows */
virtual QList<vtkRenderWindow*> GetAllRegisteredVtkRenderWindows() const = 0;
/**
* Requests an update for the specified RenderWindow, to be executed as
* soon as the main loop is ready for rendering.
*/
virtual void RequestUpdate( vtkRenderWindow *renderWindow ) = 0;
/** Immediately executes an update of the specified RenderWindow. */
virtual void ForceImmediateUpdate( vtkRenderWindow *renderWindow ) = 0;
/**
* Requests all currently registered RenderWindows to be updated.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType.
*/
virtual void RequestUpdateAll( RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL ) = 0;
/**
* Immediately executes an update of all registered RenderWindows.
* If only 2D or 3D windows should be updated, this can be specified
* via the parameter requestType.
*/
virtual void ForceImmediateUpdateAll( RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL ) = 0;
/** Initializes the windows specified by requestType to the given geometry. */
virtual bool InitializeViews( const BaseGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false ) = 0;
virtual bool InitializeViews( const TimeGeometry *geometry,
RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL,
bool preserveRoughOrientationInWorldSpace = false ) = 0;
/**
* Initializes the windows to the default viewing direction
* (geomtry information is NOT changed).
*/
virtual bool InitializeViews( RenderingManager::RequestType type = RenderingManager::REQUEST_UPDATE_ALL ) = 0;
/**
* Initializes the specified window to the given geometry. Set
* "initializeGlobalTimeSNC" to true in order to use this geometry as
* global TimeGeometry.
*/
virtual bool InitializeView( vtkRenderWindow *renderWindow, const BaseGeometry *geometry,
bool initializeGlobalTimeSNC = false) = 0;
/**
* Initializes the specified window to the default viewing direction
* (geomtry information is NOT changed).
*/
virtual bool InitializeView( vtkRenderWindow *renderWindow ) = 0;
- /** Gets the SliceNavigationController responsible for time-slicing. */
- virtual const SliceNavigationController *GetTimeNavigationController() const = 0;
+ /** Gets the TimeNavigationController responsible for time-slicing. */
+ virtual const TimeNavigationController*GetTimeNavigationController() const = 0;
- /** Gets the SliceNavigationController responsible for time-slicing. */
- virtual SliceNavigationController *GetTimeNavigationController() = 0;
+ /** Gets the TimeNavigationController responsible for time-slicing. */
+ virtual TimeNavigationController*GetTimeNavigationController() = 0;
virtual bool IsRendering() const = 0;
virtual void AbortRendering() = 0;
/** En-/Disable LOD increase globally. */
virtual void SetLODIncreaseBlocked(bool blocked) = 0;
/** Get LOD blocked status. */
virtual bool GetLODIncreaseBlocked() const = 0;
/** En-/Disable LOD abort mechanism. */
virtual void SetLODAbortMechanismEnabled(bool abort) = 0;
/** Get LOD abort mechanism status. */
virtual bool GetLODAbortMechanismEnabled() const = 0;
virtual int GetNextLOD( BaseRenderer* renderer ) const = 0;
/** Set current LOD (nullptr means all renderers)*/
virtual void SetMaximumLOD( unsigned int max ) = 0;
virtual void SetShading( bool state, unsigned int lod ) = 0;
virtual bool GetShading( unsigned int lod ) = 0;
virtual void SetClippingPlaneStatus( bool status ) = 0;
virtual bool GetClippingPlaneStatus() = 0;
virtual void SetShadingValues( float ambient, float diffuse,
float specular, float specpower ) = 0;
virtual QList<float> GetShadingValues() const = 0;
};
}
Q_DECLARE_INTERFACE(mitk::IRenderingManager, "org.mitk.ui.IRenderingManager")
namespace mitk {
/**
* Create a IRenderManager interface for a given RenderingManager. Ownership of the
* returned pointer is transferred to the caller of this function.
*
* \param manager The RenderingManager instance for which to create a interface.
* \return A pointer to the interface object. The caller is responsible for deleting the pointer.
*/
MITK_GUI_COMMON_PLUGIN IRenderingManager* MakeRenderingManagerInterface(RenderingManager::Pointer manager);
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeResetGeometryAction.cpp b/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeResetGeometryAction.cpp
index 25cdf72dc0..49aabdb6f1 100644
--- a/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeResetGeometryAction.cpp
+++ b/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeResetGeometryAction.cpp
@@ -1,113 +1,113 @@
/*============================================================================
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 <QmitkDataNodeResetGeometryAction.h>
// mitk core
#include <mitkImage.h>
#include <mitkRenderingManager.h>
// mitk gui common plugin
#include <mitkWorkbenchUtil.h>
// namespace that contains the concrete action
namespace ResetGeometryAction
{
void Run(berry::IWorkbenchPartSite::Pointer workbenchPartSite, const mitk::TimeGeometry* referenceGeometry, mitk::BaseRenderer* baseRenderer /*= nullptr*/)
{
if (workbenchPartSite.IsNull())
{
return;
}
auto* renderWindowPart = mitk::WorkbenchUtil::GetRenderWindowPart(workbenchPartSite->GetPage(), mitk::WorkbenchUtil::NONE);
if (nullptr == renderWindowPart)
{
renderWindowPart = mitk::WorkbenchUtil::OpenRenderWindowPart(workbenchPartSite->GetPage(), false);
if (nullptr == renderWindowPart)
{
// no render window available
return;
}
}
if (nullptr == referenceGeometry)
{
return;
}
mitk::TimeStepType imageTimeStep = 0;
// store the current position to set it again later, if the camera should not be reset
mitk::Point3D currentPosition = renderWindowPart->GetSelectedPosition();
// store the current time step to set it again later, if the camera should not be reset
auto* renderingManager = mitk::RenderingManager::GetInstance();
- const auto currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
+ const mitk::TimePointType currentTimePoint = renderingManager->GetTimeNavigationController()->GetSelectedTimePoint();
if (referenceGeometry->IsValidTimePoint(currentTimePoint))
{
imageTimeStep = referenceGeometry->TimePointToTimeStep(currentTimePoint);
}
if (nullptr == baseRenderer)
{
renderingManager->InitializeViews(referenceGeometry, mitk::RenderingManager::REQUEST_UPDATE_ALL, false);
}
else
{
renderingManager->InitializeView(baseRenderer->GetRenderWindow(), referenceGeometry, false);
}
renderWindowPart->SetSelectedPosition(currentPosition);
- renderingManager->GetTimeNavigationController()->GetTime()->SetPos(imageTimeStep);
+ renderingManager->GetTimeNavigationController()->GetStepper()->SetPos(imageTimeStep);
}
} // namespace ResetGeometryAction
QmitkDataNodeResetGeometryAction::QmitkDataNodeResetGeometryAction(QWidget* parent, berry::IWorkbenchPartSite::Pointer workbenchpartSite)
: QAction(parent)
, QmitkAbstractDataNodeAction(workbenchpartSite)
{
this->setText(tr("Reset geometry"));
this->InitializeAction();
}
QmitkDataNodeResetGeometryAction::QmitkDataNodeResetGeometryAction(QWidget* parent, berry::IWorkbenchPartSite* workbenchpartSite)
: QmitkDataNodeResetGeometryAction(parent, berry::IWorkbenchPartSite::Pointer(workbenchpartSite))
{
}
void QmitkDataNodeResetGeometryAction::InitializeAction()
{
connect(this, &QmitkDataNodeResetGeometryAction::triggered, this, &QmitkDataNodeResetGeometryAction::OnActionTriggered);
}
void QmitkDataNodeResetGeometryAction::OnActionTriggered(bool /*checked*/)
{
auto workbenchPartSite = m_WorkbenchPartSite.Lock();
if (workbenchPartSite.IsNull())
{
return;
}
auto baseRenderer = this->GetBaseRenderer();
auto selectedNode = this->GetSelectedNode();
mitk::Image::ConstPointer selectedImage = dynamic_cast<mitk::Image*>(selectedNode->GetData());
if (selectedImage.IsNull())
{
return;
}
ResetGeometryAction::Run(workbenchPartSite, selectedImage->GetTimeGeometry(), baseRenderer);
}
diff --git a/Plugins/org.mitk.gui.qt.application/src/QmitkPreferencesDialog.cpp b/Plugins/org.mitk.gui.qt.application/src/QmitkPreferencesDialog.cpp
index 52593cb3cd..8edcdadc91 100644
--- a/Plugins/org.mitk.gui.qt.application/src/QmitkPreferencesDialog.cpp
+++ b/Plugins/org.mitk.gui.qt.application/src/QmitkPreferencesDialog.cpp
@@ -1,385 +1,385 @@
/*============================================================================
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 "QmitkPreferencesDialog.h"
#include "berryPlatform.h"
#include "berryPlatformUI.h"
#include "berryIWorkbench.h"
#include "berryIConfigurationElement.h"
#include "berryIExtensionRegistry.h"
#include "berryIExtension.h"
#include <berryIQtPreferencePage.h>
#include "internal/org_mitk_gui_qt_application_Activator.h"
#include <ui_QmitkPreferencesDialog.h>
#include <QFileDialog>
#include <QMessageBox>
#include <QPushButton>
#include <algorithm>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkCoreServices.h>
#include <mitkIPreferencesService.h>
#include <mitkIPreferences.h>
using namespace std;
static std::vector<std::string> splitString(const std::string &s, char delim=' ')
{
std::vector < std::string > elems;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
class QmitkPreferencesDialogPrivate : public Ui::QmitkPreferencesDialog
{
public:
///
/// Just a stub class for holding information on prefpages (metadata)
///
struct PrefPage
{
PrefPage(QString _id, QString _name, QString _category
, QString _className, QString _keywords, berry::IConfigurationElement::Pointer _confElem)
: id(_id), name(_name), category(_category), className(_className), keywords(_keywords),
prefPage(nullptr), confElem(_confElem), treeWidgetItem(nullptr)
{}
bool operator==(const PrefPage& other)
{ return id == other.id; }
bool operator<(const PrefPage& other)
{ return name < other.name; }
QString id;
QString name;
QString category;
QString className;
QString keywords;
berry::IQtPreferencePage* prefPage;
berry::IConfigurationElement::Pointer confElem;
QTreeWidgetItem* treeWidgetItem;
};
QmitkPreferencesDialogPrivate()
: m_CurrentPage(0)
{
berry::IExtensionRegistry* xpService = berry::Platform::GetExtensionRegistry();
// m_PrefPages
QList<berry::IConfigurationElement::Pointer> prefPages(xpService->GetConfigurationElementsFor("org.blueberry.ui.preferencePages"));
QList<berry::IConfigurationElement::Pointer> keywordExts(xpService->GetConfigurationElementsFor("org.blueberry.ui.keywords"));
QList<berry::IConfigurationElement::Pointer>::iterator prefPagesIt;
QList<berry::IConfigurationElement::Pointer>::iterator keywordRefsIt;
for (prefPagesIt = prefPages.begin(); prefPagesIt != prefPages.end(); ++prefPagesIt)
{
QString id = (*prefPagesIt)->GetAttribute("id");
QString name = (*prefPagesIt)->GetAttribute("name");
QString className = (*prefPagesIt)->GetAttribute("class");
if(!id.isEmpty() && !name.isEmpty() && !className.isEmpty())
{
QString keywordLabels;
QString category = (*prefPagesIt)->GetAttribute("category");
//# collect keywords
QList<berry::IConfigurationElement::Pointer> keywordRefs = (*prefPagesIt)->GetChildren("keywordreference"); // get all keyword references
for (keywordRefsIt = keywordRefs.begin()
; keywordRefsIt != keywordRefs.end(); ++keywordRefsIt) // iterate over all refs
{
QString keywordRefId = (*keywordRefsIt)->GetAttribute("id"); // get referenced id
for (QList<berry::IConfigurationElement::Pointer>::iterator keywordExtsIt = keywordExts.begin();
keywordExtsIt != keywordExts.end(); ++keywordExtsIt) // iterate over all keywords
{
QString keywordId = (*keywordExtsIt)->GetAttribute("id"); // get keyword id
if(keywordId == keywordRefId) // if referenced id is equals the current keyword id
{
//# collect all keywords from label attribute with a tokenizer
QString currLabel = (*keywordExtsIt)->GetAttribute("label");
currLabel = currLabel.toLower();
if (!currLabel.isEmpty()) keywordLabels += QString(" ") + currLabel;
//break; // break here; possibly search for other referenced keywords
}
}
}
// add information as PrefPage
m_PrefPages.push_back(PrefPage(id, name, category, className, keywordLabels, berry::IConfigurationElement::Pointer(*prefPagesIt)));
}
}
}
///
/// Saves all treewidgetitems in a map, the key is the id of the preferencepage.
///
QList<PrefPage> m_PrefPages;
int m_CurrentPage;
};
QmitkPreferencesDialog::QmitkPreferencesDialog(QWidget * parent, Qt::WindowFlags f)
: QDialog(parent, f), d(new QmitkPreferencesDialogPrivate)
{
d->setupUi(this);
QObject::connect(d->m_Keyword, SIGNAL(editingFinished()), this, SLOT(OnKeywordEditingFinished()));
QObject::connect(d->m_Keyword, SIGNAL(textChanged(QString)), this, SLOT(OnKeywordTextChanged(QString)));
QObject::connect(d->m_PreferencesTree, SIGNAL(itemSelectionChanged()), this, SLOT(OnPreferencesTreeItemSelectionChanged()));
QObject::connect(this, SIGNAL(accepted()), this, SLOT(OnDialogAccepted()));
QObject::connect(this, SIGNAL(rejected()), this, SLOT(OnDialogRejected()));
this->UpdateTree();
}
QmitkPreferencesDialog::~QmitkPreferencesDialog()
{
}
void QmitkPreferencesDialog::SetSelectedPage(const QString& id)
{
for(QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin(); it != d->m_PrefPages.end(); ++it)
{
if(it->id == id)
{
d->m_PreferencesTree->setCurrentItem(it->treeWidgetItem);
break;
}
}
}
void QmitkPreferencesDialog::SavePreferences()
{
berry::IQtPreferencePage* prefPage = nullptr;
for(QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin(); it != d->m_PrefPages.end(); ++it)
{
prefPage = it->prefPage;
if(prefPage) {
prefPage->PerformOk();
}
}
/**
* Every preference page has its own preferences, which should stay the same after a system restart. <br>
* Therefore this method flushes all the preferences, every time a change in the preferences is <br>
* performed and confirmed.
*
*/
mitk::CoreServices::GetPreferencesService()->GetSystemPreferences()->Flush();
}
void QmitkPreferencesDialog::OnDialogAccepted()
{
this->SavePreferences();
}
void QmitkPreferencesDialog::OnDialogRejected()
{
berry::IQtPreferencePage* prefPage = d->m_PrefPages[d->m_CurrentPage].prefPage;
if(prefPage)
prefPage->PerformCancel();
}
void QmitkPreferencesDialog::OnKeywordTextChanged(const QString & /*s*/)
{
// search for text
this->UpdateTree();
}
void QmitkPreferencesDialog::OnKeywordEditingFinished()
{
}
void QmitkPreferencesDialog::OnPreferencesTreeItemSelectionChanged()
{
if(d->m_PreferencesTree == nullptr)
return;
// TODO: create page and show it
QList<QTreeWidgetItem *> selectedItems = d->m_PreferencesTree->selectedItems();
if(selectedItems.size()>0)
{
d->m_CurrentPage = 0;
berry::IWorkbench* workbench = berry::PlatformUI::GetWorkbench();
for(QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin(); it != d->m_PrefPages.end(); ++it, ++d->m_CurrentPage)
{
if(it->treeWidgetItem == selectedItems.at(0))
{
d->m_Headline->setText(it->name);
if(it->prefPage == nullptr)
{
berry::IPreferencePage* page = it->confElem->CreateExecutableExtension<berry::IPreferencePage>("class");
it->prefPage = dynamic_cast<berry::IQtPreferencePage*>(page);
it->prefPage->Init(berry::IWorkbench::Pointer(workbench));
it->prefPage->CreateQtControl(d->m_PreferencesPanel);
d->m_PreferencesPanel->addWidget(it->prefPage->GetQtControl());
}
d->m_PreferencesPanel->setCurrentWidget(it->prefPage->GetQtControl());
break;
}
}
}
}
void QmitkPreferencesDialog::UpdateTree()
{
if(d->m_PreferencesTree == nullptr)
return;
d->m_PreferencesTree->sortByColumn(0, Qt::AscendingOrder);
//m_PreferencesTree->clear();
QString keyword = d->m_Keyword->text().toLower();
map<QString, QTreeWidgetItem*> items;
std::list< QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator > deferredItems;
for (QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin();
it != d->m_PrefPages.end(); ++it)
{
if (it->treeWidgetItem == nullptr)
{
if (it->category.isEmpty())
{
it->treeWidgetItem = new QTreeWidgetItem(d->m_PreferencesTree);
it->treeWidgetItem->setText(0, it->name);
items[it->id] = it->treeWidgetItem;
}
else
{
// the parent might not be created yet
deferredItems.push_back(it);
}
}
}
// deal with deferred items. We do not know how many levels
// of parents need to be created
auto currentItem = deferredItems.begin();
while (currentItem != deferredItems.end())
{
auto currentItemContent = *currentItem;
if (items[currentItemContent->category] != nullptr)
{
currentItemContent->treeWidgetItem = new QTreeWidgetItem(items[currentItemContent->category]);
currentItemContent->treeWidgetItem->setText(0, currentItemContent->name);
items[currentItemContent->id] = currentItemContent->treeWidgetItem;
deferredItems.erase(currentItem);
currentItem = deferredItems.begin();
}
else
{
++currentItem;
}
}
if (!deferredItems.empty())
{
MITK_ERROR << "Unknown preference category. They are added top-level.";
for (const auto &currentItemContent : deferredItems)
{
currentItemContent->treeWidgetItem = new QTreeWidgetItem(d->m_PreferencesTree);
currentItemContent->treeWidgetItem->setText(0, currentItemContent->name);
items[currentItemContent->id] = currentItemContent->treeWidgetItem;
}
}
//First, set all pages to hidden to avoid prolems
//when iterating over the child page first which contains a specific keyword
//and sets the parent to visible
//but after this the parent is searched for the keyword. However, the keyword might not be available
//so the parent and all of its children will be set to hidden.
if(!keyword.isEmpty())
{
for (QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin();
it != d->m_PrefPages.end(); ++it)
{
it->treeWidgetItem->setHidden(true);
}
}
// we have to iterate over the list a second time, as only
// now all parents and items are guaranteed to be created
for (QList<QmitkPreferencesDialogPrivate::PrefPage>::iterator it = d->m_PrefPages.begin();
it != d->m_PrefPages.end(); ++it)
{
// hide treeWidgetItem if keyword not matches
if(!keyword.isEmpty())
{
//Split text of search box into multiple single strings
vector<string> keywordsAvailable = splitString(keyword.toUtf8().constData());
bool foundAll = true;
//perform an AND-search
for(unsigned int i = 0; i < keywordsAvailable.size(); i++)
{
if (it->keywords.indexOf(QString::fromStdString(keywordsAvailable[i])) == -1)
{
foundAll = false;
break;
}
}
if(foundAll)
{
//#make the whole branch visible
QTreeWidgetItem* treeWidgetParent = it->treeWidgetItem->parent();
while(treeWidgetParent!=nullptr)
{
treeWidgetParent->setHidden(false);
treeWidgetParent->setExpanded(true);
treeWidgetParent = treeWidgetParent->parent();
}
it->treeWidgetItem->setHidden(false);
QFont f = it->treeWidgetItem->font(0);
f.setBold(true);
it->treeWidgetItem->setFont(0, f);
}
}
else
{
QFont f = it->treeWidgetItem->font(0);
f.setBold(false);
it->treeWidgetItem->setFont(0, f);
it->treeWidgetItem->setHidden(false);
}
}
if(d->m_PrefPages.size()>0)
{
if(d->m_PrefPages.front().treeWidgetItem != nullptr)
d->m_PrefPages.front().treeWidgetItem->setSelected(true);
}
d->m_PreferencesTree->expandAll();
}
diff --git a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp
index 20fc78bccc..69d285a9db 100644
--- a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp
+++ b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp
@@ -1,1345 +1,1342 @@
/*============================================================================
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 "QmitkBasicImageProcessingView.h"
// QT includes (GUI)
#include <qlabel.h>
#include <qspinbox.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qradiobutton.h>
#include <qmessagebox.h>
// MITK includes (general)
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateProperty.h>
#include <mitkImageTimeSelector.h>
#include <mitkVectorImageMapper2D.h>
#include <mitkProperties.h>
#include <mitkLevelWindowProperty.h>
#include <mitkImageStatisticsHolder.h>
+#include <mitkTimeNavigationController.h>
// Includes for image casting between ITK and MITK
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
// ITK includes (general)
#include <itkVectorImage.h>
#include <itkImageFileWriter.h>
// Morphological Operations
#include <itkBinaryBallStructuringElement.h>
#include <itkGrayscaleDilateImageFilter.h>
#include <itkGrayscaleErodeImageFilter.h>
#include <itkGrayscaleMorphologicalOpeningImageFilter.h>
#include <itkGrayscaleMorphologicalClosingImageFilter.h>
// Smoothing
#include <itkMedianImageFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
#include <itkTotalVariationDenoisingImageFilter.h>
// Threshold
#include <itkBinaryThresholdImageFilter.h>
// Inversion
#include <itkInvertIntensityImageFilter.h>
// Derivatives
#include <itkGradientMagnitudeRecursiveGaussianImageFilter.h>
#include <itkLaplacianImageFilter.h>
#include <itkSobelEdgeDetectionImageFilter.h>
// Resampling
#include <itkResampleImageFilter.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkBSplineInterpolateImageFunction.h>
#include <itkCastImageFilter.h>
#include <itkLinearInterpolateImageFunction.h>
// Image Arithmetics
#include <itkAddImageFilter.h>
#include <itkSubtractImageFilter.h>
#include <itkMultiplyImageFilter.h>
#include <itkDivideImageFilter.h>
// Boolean operations
#include <itkOrImageFilter.h>
#include <itkAndImageFilter.h>
#include <itkXorImageFilter.h>
// Flip Image
#include <itkFlipImageFilter.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkShiftScaleImageFilter.h>
// Convenient Definitions
typedef itk::Image<short, 3> ImageType;
typedef itk::Image<unsigned char, 3> SegmentationImageType;
typedef itk::Image<double, 3> DoubleImageType;
typedef itk::Image<itk::Vector<float,3>, 3> VectorImageType;
typedef itk::BinaryBallStructuringElement<ImageType::PixelType, 3> BallType;
typedef itk::GrayscaleDilateImageFilter<ImageType, ImageType, BallType> DilationFilterType;
typedef itk::GrayscaleErodeImageFilter<ImageType, ImageType, BallType> ErosionFilterType;
typedef itk::GrayscaleMorphologicalOpeningImageFilter<ImageType, ImageType, BallType> OpeningFilterType;
typedef itk::GrayscaleMorphologicalClosingImageFilter<ImageType, ImageType, BallType> ClosingFilterType;
typedef itk::MedianImageFilter< ImageType, ImageType > MedianFilterType;
typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType> GaussianFilterType;
typedef itk::TotalVariationDenoisingImageFilter<DoubleImageType, DoubleImageType> TotalVariationFilterType;
typedef itk::TotalVariationDenoisingImageFilter<VectorImageType, VectorImageType> VectorTotalVariationFilterType;
typedef itk::BinaryThresholdImageFilter< ImageType, ImageType > ThresholdFilterType;
typedef itk::InvertIntensityImageFilter< ImageType, ImageType > InversionFilterType;
typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< ImageType, ImageType > GradientFilterType;
typedef itk::LaplacianImageFilter< DoubleImageType, DoubleImageType > LaplacianFilterType;
typedef itk::SobelEdgeDetectionImageFilter< DoubleImageType, DoubleImageType > SobelFilterType;
typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType;
typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType2;
typedef itk::CastImageFilter< ImageType, DoubleImageType > ImagePTypeToFloatPTypeCasterType;
typedef itk::AddImageFilter< ImageType, ImageType, ImageType > AddFilterType;
typedef itk::SubtractImageFilter< ImageType, ImageType, ImageType > SubtractFilterType;
typedef itk::MultiplyImageFilter< ImageType, ImageType, ImageType > MultiplyFilterType;
typedef itk::DivideImageFilter< ImageType, ImageType, DoubleImageType > DivideFilterType;
typedef itk::OrImageFilter< ImageType, ImageType > OrImageFilterType;
typedef itk::AndImageFilter< ImageType, ImageType > AndImageFilterType;
typedef itk::XorImageFilter< ImageType, ImageType > XorImageFilterType;
typedef itk::FlipImageFilter< ImageType > FlipImageFilterType;
typedef itk::LinearInterpolateImageFunction< ImageType, double > LinearInterpolatorType;
typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestInterpolatorType;
const std::string QmitkBasicImageProcessing::VIEW_ID = "org.mitk.views.basicimageprocessing";
QmitkBasicImageProcessing::QmitkBasicImageProcessing()
: QmitkAbstractView()
, m_Controls(new Ui::QmitkBasicImageProcessingViewControls)
, m_TimeStepperAdapter(nullptr)
{
auto isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
auto isNotHelperObject = mitk::NodePredicateNot::New(
mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)));
auto dimensionPredicate = mitk::NodePredicateOr::New(
mitk::NodePredicateDimension::New(3), mitk::NodePredicateDimension::New(4));
m_IsImagePredicate = mitk::NodePredicateAnd::New(
isImage, isNotHelperObject, dimensionPredicate);
}
QmitkBasicImageProcessing::~QmitkBasicImageProcessing()
{
}
void QmitkBasicImageProcessing::CreateQtPartControl(QWidget *parent)
{
m_Controls->setupUi(parent);
m_Controls->selectedImageWidget->SetDataStorage(this->GetDataStorage());
m_Controls->selectedImageWidget->SetNodePredicate(m_IsImagePredicate);
m_Controls->selectedImageWidget->SetSelectionIsOptional(true);
m_Controls->selectedImageWidget->SetAutoSelectNewNodes(true);
m_Controls->selectedImageWidget->SetEmptyInfo(QString("Please select a 3D / 4D image"));
m_Controls->selectedImageWidget->SetPopUpTitel(QString("Select an image"));
m_Controls->selectedImageWidget_2->SetDataStorage(this->GetDataStorage());
m_Controls->selectedImageWidget_2->SetNodePredicate(m_IsImagePredicate);
m_Controls->selectedImageWidget_2->SetSelectionIsOptional(true);
m_Controls->selectedImageWidget_2->SetAutoSelectNewNodes(true);
m_Controls->selectedImageWidget_2->SetEmptyInfo(QString("Please select a 3D / 4D image"));
m_Controls->selectedImageWidget_2->SetPopUpTitel(QString("Select an image"));
m_Controls->gbTwoImageOps->hide();
m_Controls->cbWhat1->clear();
m_Controls->cbWhat1->insertItem(NOACTIONSELECTED, "Please select an operation");
m_Controls->cbWhat1->insertItem(CATEGORY_DENOISING, "--- Denoising ---");
m_Controls->cbWhat1->insertItem(GAUSSIAN, "Gaussian");
m_Controls->cbWhat1->insertItem(MEDIAN, "Median");
m_Controls->cbWhat1->insertItem(TOTALVARIATION, "Total Variation");
m_Controls->cbWhat1->insertItem(CATEGORY_MORPHOLOGICAL, "--- Morphological ---");
m_Controls->cbWhat1->insertItem(DILATION, "Dilation");
m_Controls->cbWhat1->insertItem(EROSION, "Erosion");
m_Controls->cbWhat1->insertItem(OPENING, "Opening");
m_Controls->cbWhat1->insertItem(CLOSING, "Closing");
m_Controls->cbWhat1->insertItem(CATEGORY_EDGE_DETECTION, "--- Edge Detection ---");
m_Controls->cbWhat1->insertItem(GRADIENT, "Gradient");
m_Controls->cbWhat1->insertItem(LAPLACIAN, "Laplacian (2nd Derivative)");
m_Controls->cbWhat1->insertItem(SOBEL, "Sobel Operator");
m_Controls->cbWhat1->insertItem(CATEGORY_MISC, "--- Misc ---");
m_Controls->cbWhat1->insertItem(THRESHOLD, "Threshold");
m_Controls->cbWhat1->insertItem(INVERSION, "Image Inversion");
m_Controls->cbWhat1->insertItem(DOWNSAMPLING, "Downsampling");
m_Controls->cbWhat1->insertItem(FLIPPING, "Flipping");
m_Controls->cbWhat1->insertItem(RESAMPLING, "Resample to");
m_Controls->cbWhat1->insertItem(RESCALE, "Rescale values to interval");
m_Controls->cbWhat1->insertItem(RESCALE2, "Rescale values by scalar");
m_Controls->cbWhat2->clear();
m_Controls->cbWhat2->insertItem(TWOIMAGESNOACTIONSELECTED, "Please select an operation");
m_Controls->cbWhat2->insertItem(CATEGORY_ARITHMETIC, "--- Arithmetric operations ---");
m_Controls->cbWhat2->insertItem(ADD, "Add to Image 1:");
m_Controls->cbWhat2->insertItem(SUBTRACT, "Subtract from Image 1:");
m_Controls->cbWhat2->insertItem(MULTIPLY, "Multiply with Image 1:");
m_Controls->cbWhat2->insertItem(RESAMPLE_TO, "Resample Image 1 to fit geometry:");
m_Controls->cbWhat2->insertItem(DIVIDE, "Divide Image 1 by:");
m_Controls->cbWhat2->insertItem(CATEGORY_BOOLEAN, "--- Boolean operations ---");
m_Controls->cbWhat2->insertItem(AND, "AND");
m_Controls->cbWhat2->insertItem(OR, "OR");
m_Controls->cbWhat2->insertItem(XOR, "XOR");
m_Controls->cbParam4->clear();
m_Controls->cbParam4->insertItem(LINEAR, "Linear");
m_Controls->cbParam4->insertItem(NEAREST, "Nearest neighbor");
m_Controls->dsbParam1->hide();
m_Controls->dsbParam2->hide();
m_Controls->dsbParam3->hide();
m_Controls->tlParam3->hide();
m_Controls->tlParam4->hide();
m_Controls->cbParam4->hide();
this->CreateConnections();
}
void QmitkBasicImageProcessing::CreateConnections()
{
connect(m_Controls->cbWhat1, QOverload<int>::of(&QComboBox::activated), this, &QmitkBasicImageProcessing::SelectAction);
connect(m_Controls->btnDoIt, &QPushButton::clicked, this, &QmitkBasicImageProcessing::StartButtonClicked);
connect(m_Controls->cbWhat2, QOverload<int>::of(&QComboBox::activated), this, &QmitkBasicImageProcessing::SelectAction2);
connect(m_Controls->btnDoIt2, &QPushButton::clicked, this, &QmitkBasicImageProcessing::StartButton2Clicked);
connect(m_Controls->rBOneImOp, &QRadioButton::clicked, this, &QmitkBasicImageProcessing::ChangeGUI);
connect(m_Controls->rBTwoImOp, &QRadioButton::clicked, this, &QmitkBasicImageProcessing::ChangeGUI);
connect(m_Controls->cbParam4, QOverload<int>::of(&QComboBox::activated), this, &QmitkBasicImageProcessing::SelectInterpolator);
connect(m_Controls->selectedImageWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
this, &QmitkBasicImageProcessing::OnCurrentSelectionChanged);
connect(m_Controls->selectedImageWidget_2, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
this, &QmitkBasicImageProcessing::OnCurrentSelectionChanged);
}
void QmitkBasicImageProcessing::InternalGetTimeNavigationController()
{
- auto renwin_part = GetRenderWindowPart();
- if( renwin_part != nullptr )
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ if (nullptr != timeNavigationController)
{
- auto tnc = renwin_part->GetTimeNavigationController();
- if( tnc != nullptr )
- {
- m_TimeStepperAdapter = new QmitkStepperAdapter(m_Controls->timeSliceNavigationWidget, tnc->GetTime());
- }
+ m_TimeStepperAdapter = new QmitkStepperAdapter(m_Controls->timeSliceNavigationWidget, timeNavigationController->GetStepper());
}
}
void QmitkBasicImageProcessing::SetFocus()
{
m_Controls->rBOneImOp->setFocus();
}
void QmitkBasicImageProcessing::OnCurrentSelectionChanged(const QList<mitk::DataNode::Pointer>& nodes)
{
if (nodes.empty() || nodes.front().IsNull())
{
m_Controls->timeSliceNavigationWidget->setEnabled(false);
m_Controls->tlTime->setEnabled(false);
m_Controls->tlWhat1->setEnabled(false);
m_Controls->cbWhat1->setEnabled(false);
m_Controls->tlWhat2->setEnabled(false);
m_Controls->cbWhat2->setEnabled(false);
return;
}
auto selectedImage = dynamic_cast<mitk::Image*>(nodes.front()->GetData());
if (nullptr == selectedImage)
{
return;
}
if (selectedImage->GetDimension() > 3)
{
// try to retrieve the TNC (for 4-D Processing )
this->InternalGetTimeNavigationController();
m_Controls->timeSliceNavigationWidget->setEnabled(true);
m_Controls->tlTime->setEnabled(true);
}
m_Controls->tlWhat1->setEnabled(true);
m_Controls->cbWhat1->setEnabled(true);
m_Controls->tlWhat2->setEnabled(true);
m_Controls->cbWhat2->setEnabled(true);
}
void QmitkBasicImageProcessing::ChangeGUI()
{
if(m_Controls->rBOneImOp->isChecked())
{
m_Controls->gbTwoImageOps->hide();
m_Controls->gbOneImageOps->show();
}
else if(m_Controls->rBTwoImOp->isChecked())
{
m_Controls->gbOneImageOps->hide();
m_Controls->gbTwoImageOps->show();
}
}
void QmitkBasicImageProcessing::ResetParameterPanel()
{
m_Controls->tlParam->setEnabled(false);
m_Controls->tlParam1->setEnabled(false);
m_Controls->tlParam2->setEnabled(false);
m_Controls->tlParam3->setEnabled(false);
m_Controls->tlParam4->setEnabled(false);
m_Controls->sbParam1->setEnabled(false);
m_Controls->sbParam2->setEnabled(false);
m_Controls->dsbParam1->setEnabled(false);
m_Controls->dsbParam2->setEnabled(false);
m_Controls->dsbParam3->setEnabled(false);
m_Controls->cbParam4->setEnabled(false);
m_Controls->sbParam1->setValue(0);
m_Controls->sbParam2->setValue(0);
m_Controls->dsbParam1->setValue(0);
m_Controls->dsbParam2->setValue(0);
m_Controls->dsbParam3->setValue(0);
m_Controls->sbParam1->show();
m_Controls->sbParam2->show();
m_Controls->dsbParam1->hide();
m_Controls->dsbParam2->hide();
m_Controls->dsbParam3->hide();
m_Controls->cbParam4->hide();
m_Controls->tlParam3->hide();
m_Controls->tlParam4->hide();
}
void QmitkBasicImageProcessing::SelectAction(int action)
{
auto selectedImage = m_Controls->selectedImageWidget->GetSelectedNode();
if (selectedImage.IsNull())
{
return;
}
// Prepare GUI
this->ResetParameterPanel();
m_Controls->btnDoIt->setEnabled(false);
m_Controls->cbHideOrig->setEnabled(false);
QString text1 = tr("No Parameters");
QString text2 = text1;
QString text3 = text1;
QString text4 = text1;
if (action != 19)
{
m_Controls->dsbParam1->hide();
m_Controls->dsbParam2->hide();
m_Controls->dsbParam3->hide();
m_Controls->tlParam1->show();
m_Controls->tlParam2->show();
m_Controls->tlParam3->hide();
m_Controls->tlParam4->hide();
m_Controls->sbParam1->show();
m_Controls->sbParam2->show();
m_Controls->cbParam4->hide();
}
switch (action)
{
case 2:
{
m_SelectedAction = GAUSSIAN;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->hide();
m_Controls->dsbParam1->show();
m_Controls->dsbParam1->setEnabled(true);
text1 = tr("&Variance:");
m_Controls->tlParam2->hide();
m_Controls->sbParam2->hide();
m_Controls->dsbParam1->setMinimum( 0 );
m_Controls->dsbParam1->setMaximum( 200 );
m_Controls->dsbParam1->setValue( 2 );
break;
}
case 3:
{
m_SelectedAction = MEDIAN;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
text1 = tr("&Radius:");
m_Controls->sbParam1->setMinimum( 0 );
m_Controls->sbParam1->setMaximum( 200 );
m_Controls->sbParam1->setValue( 3 );
break;
}
case 4:
{
m_SelectedAction = TOTALVARIATION;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
m_Controls->tlParam2->setEnabled(true);
m_Controls->sbParam2->setEnabled(true);
text1 = tr("Number Iterations:");
text2 = tr("Regularization\n(Lambda/1000):");
m_Controls->sbParam1->setMinimum( 1 );
m_Controls->sbParam1->setMaximum( 1000 );
m_Controls->sbParam1->setValue( 40 );
m_Controls->sbParam2->setMinimum( 0 );
m_Controls->sbParam2->setMaximum( 100000 );
m_Controls->sbParam2->setValue( 1 );
break;
}
case 6:
{
m_SelectedAction = DILATION;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
text1 = tr("&Radius:");
m_Controls->sbParam1->setMinimum( 0 );
m_Controls->sbParam1->setMaximum( 200 );
m_Controls->sbParam1->setValue( 3 );
break;
}
case 7:
{
m_SelectedAction = EROSION;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
text1 = tr("&Radius:");
m_Controls->sbParam1->setMinimum( 0 );
m_Controls->sbParam1->setMaximum( 200 );
m_Controls->sbParam1->setValue( 3 );
break;
}
case 8:
{
m_SelectedAction = OPENING;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
text1 = tr("&Radius:");
m_Controls->sbParam1->setMinimum( 0 );
m_Controls->sbParam1->setMaximum( 200 );
m_Controls->sbParam1->setValue( 3 );
break;
}
case 9:
{
m_SelectedAction = CLOSING;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
text1 = tr("&Radius:");
m_Controls->sbParam1->setMinimum( 0 );
m_Controls->sbParam1->setMaximum( 200 );
m_Controls->sbParam1->setValue( 3 );
break;
}
case 11:
{
m_SelectedAction = GRADIENT;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->hide();
m_Controls->dsbParam1->show();
m_Controls->dsbParam1->setEnabled(true);
text1 = tr("Sigma of Gaussian Kernel:\n(in Image Spacing Units)");
m_Controls->tlParam2->hide();
m_Controls->sbParam2->hide();
m_Controls->dsbParam1->setMinimum( 0 );
m_Controls->dsbParam1->setMaximum( 200 );
m_Controls->dsbParam1->setValue( 2 );
break;
}
case 12:
{
m_SelectedAction = LAPLACIAN;
break;
}
case 13:
{
m_SelectedAction = SOBEL;
break;
}
case 15:
{
m_SelectedAction = THRESHOLD;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
m_Controls->tlParam2->setEnabled(true);
m_Controls->sbParam2->setEnabled(true);
text1 = tr("Lower threshold:");
text2 = tr("Upper threshold:");
m_Controls->sbParam1->setMinimum( -100000 );
m_Controls->sbParam1->setMaximum( 100000 );
m_Controls->sbParam1->setValue( 0 );
m_Controls->sbParam2->setMinimum( -100000 );
m_Controls->sbParam2->setMaximum( 100000 );
m_Controls->sbParam2->setValue( 300 );
break;
}
case 16:
{
m_SelectedAction = INVERSION;
break;
}
case 17:
{
m_SelectedAction = DOWNSAMPLING;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
text1 = tr("Downsampling by Factor:");
m_Controls->sbParam1->setMinimum( 1 );
m_Controls->sbParam1->setMaximum( 100 );
m_Controls->sbParam1->setValue( 2 );
break;
}
case 18:
{
m_SelectedAction = FLIPPING;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(true);
text1 = tr("Flip across axis:");
m_Controls->sbParam1->setMinimum( 0 );
m_Controls->sbParam1->setMaximum( 2 );
m_Controls->sbParam1->setValue( 1 );
break;
}
case 19:
{
m_SelectedAction = RESAMPLING;
m_Controls->tlParam1->setEnabled(true);
m_Controls->sbParam1->setEnabled(false);
m_Controls->sbParam1->hide();
m_Controls->dsbParam1->show();
m_Controls->dsbParam1->setEnabled(true);
m_Controls->tlParam2->setEnabled(true);
m_Controls->sbParam2->setEnabled(false);
m_Controls->sbParam2->hide();
m_Controls->dsbParam2->show();
m_Controls->dsbParam2->setEnabled(true);
m_Controls->tlParam3->show();
m_Controls->tlParam3->setEnabled(true);
m_Controls->dsbParam3->show();
m_Controls->dsbParam3->setEnabled(true);
m_Controls->tlParam4->show();
m_Controls->tlParam4->setEnabled(true);
m_Controls->cbParam4->show();
m_Controls->cbParam4->setEnabled(true);
m_Controls->dsbParam1->setMinimum(0.01);
m_Controls->dsbParam1->setMaximum(10.0);
m_Controls->dsbParam1->setSingleStep(0.1);
m_Controls->dsbParam1->setValue(0.3);
m_Controls->dsbParam2->setMinimum(0.01);
m_Controls->dsbParam2->setMaximum(10.0);
m_Controls->dsbParam2->setSingleStep(0.1);
m_Controls->dsbParam2->setValue(0.3);
m_Controls->dsbParam3->setMinimum(0.01);
m_Controls->dsbParam3->setMaximum(10.0);
m_Controls->dsbParam3->setSingleStep(0.1);
m_Controls->dsbParam3->setValue(1.5);
text1 = tr("x-spacing:");
text2 = tr("y-spacing:");
text3 = tr("z-spacing:");
text4 = tr("Interplation:");
break;
}
case 20:
{
m_SelectedAction = RESCALE;
m_Controls->dsbParam1->show();
m_Controls->tlParam1->show();
m_Controls->dsbParam1->setEnabled(true);
m_Controls->tlParam1->setEnabled(true);
m_Controls->dsbParam2->show();
m_Controls->tlParam2->show();
m_Controls->dsbParam2->setEnabled(true);
m_Controls->tlParam2->setEnabled(true);
text1 = tr("Output minimum:");
text2 = tr("Output maximum:");
break;
}
case 21:
{
m_SelectedAction = RESCALE2;
m_Controls->dsbParam1->show();
m_Controls->tlParam1->show();
m_Controls->dsbParam1->setEnabled(true);
m_Controls->tlParam1->setEnabled(true);
text1 = tr("Scaling value:");
break;
}
default:
return;
}
m_Controls->tlParam->setEnabled(true);
m_Controls->tlParam1->setText(text1);
m_Controls->tlParam2->setText(text2);
m_Controls->tlParam3->setText(text3);
m_Controls->tlParam4->setText(text4);
m_Controls->btnDoIt->setEnabled(true);
m_Controls->cbHideOrig->setEnabled(true);
}
void QmitkBasicImageProcessing::StartButtonClicked()
{
auto selectedNode = m_Controls->selectedImageWidget->GetSelectedNode();
if (selectedNode.IsNull())
{
return;
}
this->BusyCursorOn();
mitk::Image::Pointer newImage;
try
{
newImage = dynamic_cast<mitk::Image*>(selectedNode->GetData());
}
catch ( std::exception &e )
{
QString exceptionString = tr("An error occured during image loading:\n");
exceptionString.append( e.what() );
QMessageBox::warning( nullptr, "Basic Image Processing", exceptionString , QMessageBox::Ok, QMessageBox::NoButton );
this->BusyCursorOff();
return;
}
// check if input image is valid, casting does not throw exception when casting from 'nullptr-Object'
if ( (! newImage) || (newImage->IsInitialized() == false) )
{
this->BusyCursorOff();
QMessageBox::warning( nullptr, "Basic Image Processing", tr("Input image is broken or not initialized. Returning."), QMessageBox::Ok, QMessageBox::NoButton );
return;
}
// check if operation is done on 4D a image time step
if(newImage->GetDimension() > 3)
{
auto timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(newImage);
timeSelector->SetTimeNr(m_Controls->timeSliceNavigationWidget->GetPos() );
timeSelector->Update();
newImage = timeSelector->GetOutput();
}
// check if image or vector image
auto itkImage = ImageType::New();
auto itkVecImage = VectorImageType::New();
int isVectorImage = newImage->GetPixelType().GetNumberOfComponents();
if(isVectorImage > 1)
{
CastToItkImage( newImage, itkVecImage );
}
else
{
CastToItkImage( newImage, itkImage );
}
std::stringstream nameAddition("");
int param1 = m_Controls->sbParam1->value();
int param2 = m_Controls->sbParam2->value();
double dparam1 = m_Controls->dsbParam1->value();
double dparam2 = m_Controls->dsbParam2->value();
double dparam3 = m_Controls->dsbParam3->value();
try
{
switch (m_SelectedAction)
{
case GAUSSIAN:
{
GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New();
gaussianFilter->SetInput( itkImage );
gaussianFilter->SetVariance( dparam1 );
gaussianFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(gaussianFilter->GetOutput())->Clone();
nameAddition << "_Gaussian_var_" << dparam1;
std::cout << "Gaussian filtering successful." << std::endl;
break;
}
case MEDIAN:
{
MedianFilterType::Pointer medianFilter = MedianFilterType::New();
MedianFilterType::InputSizeType size;
size.Fill(param1);
medianFilter->SetRadius( size );
medianFilter->SetInput(itkImage);
medianFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(medianFilter->GetOutput())->Clone();
nameAddition << "_Median_radius_" << param1;
std::cout << "Median Filtering successful." << std::endl;
break;
}
case TOTALVARIATION:
{
if(isVectorImage > 1)
{
VectorTotalVariationFilterType::Pointer TVFilter
= VectorTotalVariationFilterType::New();
TVFilter->SetInput( itkVecImage.GetPointer() );
TVFilter->SetNumberIterations(param1);
TVFilter->SetLambda(double(param2)/1000.);
TVFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(TVFilter->GetOutput())->Clone();
}
else
{
ImagePTypeToFloatPTypeCasterType::Pointer floatCaster = ImagePTypeToFloatPTypeCasterType::New();
floatCaster->SetInput( itkImage );
floatCaster->Update();
DoubleImageType::Pointer fImage = floatCaster->GetOutput();
TotalVariationFilterType::Pointer TVFilter
= TotalVariationFilterType::New();
TVFilter->SetInput( fImage.GetPointer() );
TVFilter->SetNumberIterations(param1);
TVFilter->SetLambda(double(param2)/1000.);
TVFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(TVFilter->GetOutput())->Clone();
}
nameAddition << "_TV_Iter_" << param1 << "_L_" << param2;
std::cout << "Total Variation Filtering successful." << std::endl;
break;
}
case DILATION:
{
BallType binaryBall;
binaryBall.SetRadius( param1 );
binaryBall.CreateStructuringElement();
DilationFilterType::Pointer dilationFilter = DilationFilterType::New();
dilationFilter->SetInput( itkImage );
dilationFilter->SetKernel( binaryBall );
dilationFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(dilationFilter->GetOutput())->Clone();
nameAddition << "_Dilated_by_" << param1;
std::cout << "Dilation successful." << std::endl;
break;
}
case EROSION:
{
BallType binaryBall;
binaryBall.SetRadius( param1 );
binaryBall.CreateStructuringElement();
ErosionFilterType::Pointer erosionFilter = ErosionFilterType::New();
erosionFilter->SetInput( itkImage );
erosionFilter->SetKernel( binaryBall );
erosionFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(erosionFilter->GetOutput())->Clone();
nameAddition << "_Eroded_by_" << param1;
std::cout << "Erosion successful." << std::endl;
break;
}
case OPENING:
{
BallType binaryBall;
binaryBall.SetRadius( param1 );
binaryBall.CreateStructuringElement();
OpeningFilterType::Pointer openFilter = OpeningFilterType::New();
openFilter->SetInput( itkImage );
openFilter->SetKernel( binaryBall );
openFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(openFilter->GetOutput())->Clone();
nameAddition << "_Opened_by_" << param1;
std::cout << "Opening successful." << std::endl;
break;
}
case CLOSING:
{
BallType binaryBall;
binaryBall.SetRadius( param1 );
binaryBall.CreateStructuringElement();
ClosingFilterType::Pointer closeFilter = ClosingFilterType::New();
closeFilter->SetInput( itkImage );
closeFilter->SetKernel( binaryBall );
closeFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(closeFilter->GetOutput())->Clone();
nameAddition << "_Closed_by_" << param1;
std::cout << "Closing successful." << std::endl;
break;
}
case GRADIENT:
{
GradientFilterType::Pointer gradientFilter = GradientFilterType::New();
gradientFilter->SetInput( itkImage );
gradientFilter->SetSigma( dparam1 );
gradientFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(gradientFilter->GetOutput())->Clone();
nameAddition << "_Gradient_sigma_" << dparam1;
std::cout << "Gradient calculation successful." << std::endl;
break;
}
case LAPLACIAN:
{
// the laplace filter requires a float type image as input, we need to cast the itkImage
// to correct type
ImagePTypeToFloatPTypeCasterType::Pointer caster = ImagePTypeToFloatPTypeCasterType::New();
caster->SetInput( itkImage );
caster->Update();
DoubleImageType::Pointer fImage = caster->GetOutput();
LaplacianFilterType::Pointer laplacianFilter = LaplacianFilterType::New();
laplacianFilter->SetInput( fImage );
laplacianFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(laplacianFilter->GetOutput())->Clone();
nameAddition << "_Second_Derivative";
std::cout << "Laplacian filtering successful." << std::endl;
break;
}
case SOBEL:
{
// the sobel filter requires a float type image as input, we need to cast the itkImage
// to correct type
ImagePTypeToFloatPTypeCasterType::Pointer caster = ImagePTypeToFloatPTypeCasterType::New();
caster->SetInput( itkImage );
caster->Update();
DoubleImageType::Pointer fImage = caster->GetOutput();
SobelFilterType::Pointer sobelFilter = SobelFilterType::New();
sobelFilter->SetInput( fImage );
sobelFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(sobelFilter->GetOutput())->Clone();
nameAddition << "_Sobel";
std::cout << "Edge Detection successful." << std::endl;
break;
}
case THRESHOLD:
{
ThresholdFilterType::Pointer thFilter = ThresholdFilterType::New();
thFilter->SetLowerThreshold(param1 < param2 ? param1 : param2);
thFilter->SetUpperThreshold(param2 > param1 ? param2 : param1);
thFilter->SetInsideValue(1);
thFilter->SetOutsideValue(0);
thFilter->SetInput(itkImage);
thFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(thFilter->GetOutput())->Clone();
nameAddition << "_Threshold";
std::cout << "Thresholding successful." << std::endl;
break;
}
case INVERSION:
{
InversionFilterType::Pointer invFilter = InversionFilterType::New();
mitk::ScalarType min = newImage->GetStatistics()->GetScalarValueMin();
mitk::ScalarType max = newImage->GetStatistics()->GetScalarValueMax();
invFilter->SetMaximum( max + min );
invFilter->SetInput(itkImage);
invFilter->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(invFilter->GetOutput())->Clone();
nameAddition << "_Inverted";
std::cout << "Image inversion successful." << std::endl;
break;
}
case DOWNSAMPLING:
{
ResampleImageFilterType::Pointer downsampler = ResampleImageFilterType::New();
downsampler->SetInput( itkImage );
NearestInterpolatorType::Pointer interpolator = NearestInterpolatorType::New();
downsampler->SetInterpolator( interpolator );
downsampler->SetDefaultPixelValue( 0 );
ResampleImageFilterType::SpacingType spacing = itkImage->GetSpacing();
spacing *= (double) param1;
downsampler->SetOutputSpacing( spacing );
downsampler->SetOutputOrigin( itkImage->GetOrigin() );
downsampler->SetOutputDirection( itkImage->GetDirection() );
ResampleImageFilterType::SizeType size = itkImage->GetLargestPossibleRegion().GetSize();
for ( int i = 0; i < 3; ++i )
{
size[i] /= param1;
}
downsampler->SetSize( size );
downsampler->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(downsampler->GetOutput())->Clone();
nameAddition << "_Downsampled_by_" << param1;
std::cout << "Downsampling successful." << std::endl;
break;
}
case FLIPPING:
{
FlipImageFilterType::Pointer flipper = FlipImageFilterType::New();
flipper->SetInput( itkImage );
itk::FixedArray<bool, 3> flipAxes;
for(int i=0; i<3; ++i)
{
if(i == param1)
{
flipAxes[i] = true;
}
else
{
flipAxes[i] = false;
}
}
flipper->SetFlipAxes(flipAxes);
flipper->UpdateLargestPossibleRegion();
newImage = mitk::ImportItkImage(flipper->GetOutput())->Clone();
std::cout << "Image flipping successful." << std::endl;
break;
}
case RESAMPLING:
{
std::string selectedInterpolator;
ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New();
switch (m_SelectedInterpolation)
{
case LINEAR:
{
LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New();
resampler->SetInterpolator(interpolator);
selectedInterpolator = "Linear";
break;
}
case NEAREST:
{
NearestInterpolatorType::Pointer interpolator = NearestInterpolatorType::New();
resampler->SetInterpolator(interpolator);
selectedInterpolator = "Nearest";
break;
}
default:
{
LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New();
resampler->SetInterpolator(interpolator);
selectedInterpolator = "Linear";
break;
}
}
resampler->SetInput( itkImage );
resampler->SetOutputOrigin( itkImage->GetOrigin() );
ImageType::SizeType input_size = itkImage->GetLargestPossibleRegion().GetSize();
ImageType::SpacingType input_spacing = itkImage->GetSpacing();
ImageType::SizeType output_size;
ImageType::SpacingType output_spacing;
output_size[0] = input_size[0] * (input_spacing[0] / dparam1);
output_size[1] = input_size[1] * (input_spacing[1] / dparam2);
output_size[2] = input_size[2] * (input_spacing[2] / dparam3);
output_spacing [0] = dparam1;
output_spacing [1] = dparam2;
output_spacing [2] = dparam3;
resampler->SetSize( output_size );
resampler->SetOutputSpacing( output_spacing );
resampler->SetOutputDirection( itkImage->GetDirection() );
resampler->UpdateLargestPossibleRegion();
ImageType::Pointer resampledImage = resampler->GetOutput();
newImage = mitk::ImportItkImage( resampledImage )->Clone();
nameAddition << "_Resampled_" << selectedInterpolator;
std::cout << "Resampling successful." << std::endl;
break;
}
case RESCALE:
{
DoubleImageType::Pointer floatImage = DoubleImageType::New();
CastToItkImage( newImage, floatImage );
itk::RescaleIntensityImageFilter<DoubleImageType,DoubleImageType>::Pointer filter = itk::RescaleIntensityImageFilter<DoubleImageType,DoubleImageType>::New();
filter->SetInput(0, floatImage);
filter->SetOutputMinimum(dparam1);
filter->SetOutputMaximum(dparam2);
filter->Update();
floatImage = filter->GetOutput();
newImage = mitk::Image::New();
newImage->InitializeByItk(floatImage.GetPointer());
newImage->SetVolume(floatImage->GetBufferPointer());
nameAddition << "_Rescaled";
std::cout << "Rescaling successful." << std::endl;
break;
}
case RESCALE2:
{
DoubleImageType::Pointer floatImage = DoubleImageType::New();
CastToItkImage( newImage, floatImage );
itk::ShiftScaleImageFilter<DoubleImageType,DoubleImageType>::Pointer filter = itk::ShiftScaleImageFilter<DoubleImageType,DoubleImageType>::New();
filter->SetInput(0, floatImage);
filter->SetScale(dparam1);
filter->Update();
floatImage = filter->GetOutput();
newImage = mitk::Image::New();
newImage->InitializeByItk(floatImage.GetPointer());
newImage->SetVolume(floatImage->GetBufferPointer());
nameAddition << "_Rescaled";
std::cout << "Rescaling successful." << std::endl;
break;
}
default:
this->BusyCursorOff();
return;
}
}
catch (...)
{
this->BusyCursorOff();
QMessageBox::warning(nullptr, "Warning", "Problem when applying filter operation. Check your input...");
return;
}
newImage->DisconnectPipeline();
// adjust level/window to new image
mitk::LevelWindow levelwindow;
levelwindow.SetAuto( newImage );
auto levWinProp = mitk::LevelWindowProperty::New();
levWinProp->SetLevelWindow( levelwindow );
// compose new image name
std::string name = selectedNode->GetName();
if (name.find(".nrrd") == name.size() -5 )
{
name = name.substr(0,name.size() -5);
}
name.append( nameAddition.str() );
// create final result MITK data storage node
auto result = mitk::DataNode::New();
result->SetProperty( "levelwindow", levWinProp );
result->SetProperty( "name", mitk::StringProperty::New( name.c_str() ) );
result->SetData( newImage );
// for vector images, a different mapper is needed
if(isVectorImage > 1)
{
auto mapper = mitk::VectorImageMapper2D::New();
result->SetMapper(1,mapper);
}
// add new image to data storage and set as active to ease further processing
GetDataStorage()->Add(result, selectedNode);
if (m_Controls->cbHideOrig->isChecked() == true)
{
selectedNode->SetProperty("visible", mitk::BoolProperty::New(false));
}
// show the results
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->BusyCursorOff();
}
void QmitkBasicImageProcessing::SelectAction2(int operation)
{
switch (operation)
{
case 2:
m_SelectedOperation = ADD;
break;
case 3:
m_SelectedOperation = SUBTRACT;
break;
case 4:
m_SelectedOperation = MULTIPLY;
break;
case 5:
m_SelectedOperation = DIVIDE;
break;
case 6:
m_SelectedOperation = RESAMPLE_TO;
break;
case 8:
m_SelectedOperation = AND;
break;
case 9:
m_SelectedOperation = OR;
break;
case 10:
m_SelectedOperation = XOR;
break;
default:
return;
}
m_Controls->selectedImageLabel_2->setEnabled(true);
m_Controls->selectedImageWidget_2->setEnabled(true);
m_Controls->btnDoIt2->setEnabled(true);
}
void QmitkBasicImageProcessing::StartButton2Clicked()
{
auto selectedNode = m_Controls->selectedImageWidget->GetSelectedNode();
if (selectedNode.IsNull())
{
return;
}
auto selectedNode2 = m_Controls->selectedImageWidget_2->GetSelectedNode();
if (selectedNode2.IsNull())
{
return;
}
mitk::Image::Pointer newImage1 = dynamic_cast<mitk::Image*>(selectedNode->GetData());
mitk::Image::Pointer newImage2 = dynamic_cast<mitk::Image*>(selectedNode2->GetData());
// check if images are valid
if(newImage1.IsNull() || newImage2.IsNull() || false == newImage1->IsInitialized() || false == newImage2->IsInitialized())
{
itkGenericExceptionMacro(<< "At least one of the input images is broken or not initialized.");
return;
}
this->BusyCursorOn();
// check if 4D image and use filter on correct time step
if(newImage1->GetDimension() > 3)
{
auto timeSelector = mitk::ImageTimeSelector::New();
auto sn_widget = static_cast<QmitkSliceNavigationWidget*>(m_Controls->timeSliceNavigationWidget);
int time = 0;
if( sn_widget != nullptr )
time = sn_widget->GetPos();
timeSelector->SetInput(newImage1);
timeSelector->SetTimeNr( time );
timeSelector->UpdateLargestPossibleRegion();
newImage1 = timeSelector->GetOutput();
newImage1->DisconnectPipeline();
timeSelector->SetInput(newImage2);
timeSelector->SetTimeNr( time );
timeSelector->UpdateLargestPossibleRegion();
newImage2 = timeSelector->GetOutput();
newImage2->DisconnectPipeline();
}
auto itkImage1 = ImageType::New();
auto itkImage2 = ImageType::New();
CastToItkImage( newImage1, itkImage1 );
CastToItkImage( newImage2, itkImage2 );
std::string nameAddition = "";
try
{
switch (m_SelectedOperation)
{
case ADD:
{
AddFilterType::Pointer addFilter = AddFilterType::New();
addFilter->SetInput1( itkImage1 );
addFilter->SetInput2( itkImage2 );
addFilter->UpdateLargestPossibleRegion();
newImage1 = mitk::ImportItkImage(addFilter->GetOutput())->Clone();
nameAddition = "_Added";
}
break;
case SUBTRACT:
{
SubtractFilterType::Pointer subFilter = SubtractFilterType::New();
subFilter->SetInput1( itkImage1 );
subFilter->SetInput2( itkImage2 );
subFilter->UpdateLargestPossibleRegion();
newImage1 = mitk::ImportItkImage(subFilter->GetOutput())->Clone();
nameAddition = "_Subtracted";
}
break;
case MULTIPLY:
{
MultiplyFilterType::Pointer multFilter = MultiplyFilterType::New();
multFilter->SetInput1( itkImage1 );
multFilter->SetInput2( itkImage2 );
multFilter->UpdateLargestPossibleRegion();
newImage1 = mitk::ImportItkImage(multFilter->GetOutput())->Clone();
nameAddition = "_Multiplied";
}
break;
case DIVIDE:
{
DivideFilterType::Pointer divFilter = DivideFilterType::New();
divFilter->SetInput1( itkImage1 );
divFilter->SetInput2( itkImage2 );
divFilter->UpdateLargestPossibleRegion();
newImage1 = mitk::ImportItkImage<DoubleImageType>(divFilter->GetOutput())->Clone();
nameAddition = "_Divided";
}
break;
case AND:
{
AndImageFilterType::Pointer andFilter = AndImageFilterType::New();
andFilter->SetInput1( itkImage1 );
andFilter->SetInput2( itkImage2 );
andFilter->UpdateLargestPossibleRegion();
newImage1 = mitk::ImportItkImage(andFilter->GetOutput())->Clone();
nameAddition = "_AND";
break;
}
case OR:
{
OrImageFilterType::Pointer orFilter = OrImageFilterType::New();
orFilter->SetInput1( itkImage1 );
orFilter->SetInput2( itkImage2 );
orFilter->UpdateLargestPossibleRegion();
newImage1 = mitk::ImportItkImage(orFilter->GetOutput())->Clone();
nameAddition = "_OR";
break;
}
case XOR:
{
XorImageFilterType::Pointer xorFilter = XorImageFilterType::New();
xorFilter->SetInput1( itkImage1 );
xorFilter->SetInput2( itkImage2 );
xorFilter->UpdateLargestPossibleRegion();
newImage1 = mitk::ImportItkImage(xorFilter->GetOutput())->Clone();
nameAddition = "_XOR";
break;
}
case RESAMPLE_TO:
{
itk::BSplineInterpolateImageFunction<DoubleImageType, double>::Pointer bspl_interpolator
= itk::BSplineInterpolateImageFunction<DoubleImageType, double>::New();
bspl_interpolator->SetSplineOrder( 3 );
itk::NearestNeighborInterpolateImageFunction< DoubleImageType >::Pointer nn_interpolator
= itk::NearestNeighborInterpolateImageFunction< DoubleImageType>::New();
DoubleImageType::Pointer itkImage1 = DoubleImageType::New();
DoubleImageType::Pointer itkImage2 = DoubleImageType::New();
CastToItkImage( newImage1, itkImage1 );
CastToItkImage( newImage2, itkImage2 );
itk::ResampleImageFilter< DoubleImageType, DoubleImageType >::Pointer resampleFilter = itk::ResampleImageFilter< DoubleImageType, DoubleImageType >::New();
resampleFilter->SetInput( itkImage1 );
resampleFilter->SetReferenceImage( itkImage2 );
resampleFilter->SetUseReferenceImage( true );
// use NN interp with binary images
if(selectedNode->GetProperty("binary") )
resampleFilter->SetInterpolator( nn_interpolator );
else
resampleFilter->SetInterpolator( bspl_interpolator );
resampleFilter->SetDefaultPixelValue( 0 );
try
{
resampleFilter->UpdateLargestPossibleRegion();
}
catch( const itk::ExceptionObject &e)
{
MITK_WARN << "Updating resampling filter failed. ";
MITK_WARN << "REASON: " << e.what();
}
DoubleImageType::Pointer resampledImage = resampleFilter->GetOutput();
newImage1 = mitk::ImportItkImage( resampledImage )->Clone();
nameAddition = "_Resampled";
break;
}
default:
std::cout << "Something went wrong..." << std::endl;
this->BusyCursorOff();
return;
}
}
catch (const itk::ExceptionObject& e )
{
this->BusyCursorOff();
QMessageBox::warning(nullptr, "ITK Exception", e.what() );
QMessageBox::warning(nullptr, "Warning", tr("Problem when applying arithmetic operation to two images. Check dimensions of input images."));
return;
}
// disconnect pipeline; images will not be reused
newImage1->DisconnectPipeline();
itkImage1 = nullptr;
itkImage2 = nullptr;
// adjust level/window to new image and compose new image name
mitk::LevelWindow levelwindow;
levelwindow.SetAuto( newImage1 );
auto levWinProp = mitk::LevelWindowProperty::New();
levWinProp->SetLevelWindow( levelwindow );
std::string name = selectedNode->GetName();
if (name.find(".nrrd") == name.size() -5 )
{
name = name.substr(0,name.size() -5);
}
// create final result MITK data storage node
auto result = mitk::DataNode::New();
result->SetProperty( "levelwindow", levWinProp );
result->SetProperty( "name", mitk::StringProperty::New( (name + nameAddition ).c_str() ));
result->SetData( newImage1 );
this->GetDataStorage()->Add(result, selectedNode);
if (m_Controls->cbHideOrig->isChecked() == true)
{
selectedNode->SetProperty("visible", mitk::BoolProperty::New(false));
selectedNode2->SetProperty("visible", mitk::BoolProperty::New(false));
}
// show the newly created image
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->BusyCursorOff();
}
void QmitkBasicImageProcessing::SelectInterpolator(int interpolator)
{
switch (interpolator)
{
case 0:
{
m_SelectedInterpolation = LINEAR;
break;
}
case 1:
{
m_SelectedInterpolation = NEAREST;
break;
}
}
}
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/CMakeLists.txt b/Plugins/org.mitk.gui.qt.classificationsegmentation/CMakeLists.txt
deleted file mode 100644
index 6722ebed14..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-project(org_mitk_gui_qt_classificationsegmentation)
-
-mitk_create_plugin(
- EXPORT_DIRECTIVE CLASSIFICATIONSEGMENTATION_EXPORT
- EXPORTED_INCLUDE_SUFFIXES src
- MODULE_DEPENDS MitkQtWidgetsExt MitkMultilabel MitkCLVigraRandomForest MitkCLUtilities
-)
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/Manual.dox
deleted file mode 100644
index c1a5768584..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/Manual.dox
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
-\page org_mitk_gui_qt_classificationsegmentation The Classificationsegmentation Plugin
-
-\imageMacro{brain.png,"Icon of Classificationsegmentation Plugin",2.00}
-
-\tableofcontents
-
-\section org_mitk_gui_qt_classificationsegmentationOverview Overview
-Segmentation of the classes:
-<ul>
-<li>CSF (value of 1)
-<li>Lesion (value of 2)
-<li>Brain (value of 3)
-</ul>
-
-using a random forest based approach.
-
-
-Credits (from the Noun Project):
-<ul>
-<li> Brain by Santiago Arias
-<li> process by Marek Polakovic
-<li> process by Takao Umehara
-</ul>
-*/
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/brain.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/brain.png
deleted file mode 100644
index 5f6d515d75..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/brain.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/icon.xpm
deleted file mode 100644
index 9057c20bc6..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/UserManual/icon.xpm
+++ /dev/null
@@ -1,21 +0,0 @@
-/* XPM */
-static const char * icon_xpm[] = {
-"16 16 2 1",
-" c #FF0000",
-". c #000000",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/doxygen/modules.dox
deleted file mode 100644
index 96ed2ce012..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/documentation/doxygen/modules.dox
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- \defgroup org_mitk_gui_qt_classificationsegmentation org.mitk.gui.qt.classificationsegmentation
- \ingroup MITKPlugins
-
- \brief Describe your plugin here.
-
-*/
-
-/**
- \defgroup org_mitk_gui_qt_classificationsegmentation_internal Internal
- \ingroup org_mitk_gui_qt_classificationsegmentation
-
- \brief This subcategory includes the internal classes of the org.mitk.gui.qt.classificationsegmentation plugin. Other
- plugins must not rely on these classes. They contain implementation details and their interface
- may change at any time. We mean it.
-*/
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/files.cmake b/Plugins/org.mitk.gui.qt.classificationsegmentation/files.cmake
deleted file mode 100644
index d058df59d8..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/files.cmake
+++ /dev/null
@@ -1,46 +0,0 @@
-set(SRC_CPP_FILES
-
-)
-
-set(INTERNAL_CPP_FILES
- org_mitk_gui_qt_classificationsegmentation_Activator.cpp
- ClassificationSegmentation.cpp
- ClassificationRegionGrow.cpp
-)
-
-set(UI_FILES
- src/internal/ClassificationSegmentationControls.ui
- src/internal/ClassificationRegionGrowControls.ui
-)
-
-set(MOC_H_FILES
- src/internal/org_mitk_gui_qt_classificationsegmentation_Activator.h
- src/internal/ClassificationSegmentation.h
- src/internal/ClassificationRegionGrow.h
-)
-
-# list of resource files which can be used by the plug-in
-# system without loading the plug-ins shared library,
-# for example the icon used in the menu and tabs for the
-# plug-in views in the workbench
-set(CACHED_RESOURCE_FILES
- resources/icon_32.png
- resources/icon.png
- plugin.xml
-)
-
-# list of Qt .qrc files which contain additional resources
-# specific to this plugin
-set(QRC_FILES
- resources/ClassificationSegmentation.qrc
-)
-
-set(CPP_FILES )
-
-foreach(file ${SRC_CPP_FILES})
- set(CPP_FILES ${CPP_FILES} src/${file})
-endforeach(file ${SRC_CPP_FILES})
-
-foreach(file ${INTERNAL_CPP_FILES})
- set(CPP_FILES ${CPP_FILES} src/internal/${file})
-endforeach(file ${INTERNAL_CPP_FILES})
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.classificationsegmentation/manifest_headers.cmake
deleted file mode 100644
index 5e2df456c2..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/manifest_headers.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-set(Plugin-Name "Classificationsegmentation")
-set(Plugin-Version "0.1")
-set(Plugin-Vendor "DKFZ")
-set(Plugin-ContactAddress "")
-set(Require-Plugin org.mitk.gui.qt.common)
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/plugin.xml b/Plugins/org.mitk.gui.qt.classificationsegmentation/plugin.xml
deleted file mode 100644
index 0e79fbf0ac..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/plugin.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<plugin>
-
- <extension point="org.blueberry.ui.views">
- <view id="org.mitk.views.classificationsegmentation"
- name="Classification Segmentation"
- class="ClassificationSegmentation"
- icon="resources/icon_32.png" />
- <view id="org.mitk.views.classificationregiongrow"
- name="Classification Region Grow"
- class="ClassificationRegionGrow"
- icon="resources/icon_32.png" />
- </extension>
-
-</plugin>
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/ClassificationSegmentation.qrc b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/ClassificationSegmentation.qrc
deleted file mode 100644
index 0b1bca7399..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/ClassificationSegmentation.qrc
+++ /dev/null
@@ -1,8 +0,0 @@
-<RCC>
- <qresource prefix="/ClassificationSegmentation">
- <file>button_process.png</file>
- <file>icon_32.png</file>
- <file>icon.png</file>
- <file>button_process_2.png</file>
- </qresource>
-</RCC>
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/button_process.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/button_process.png
deleted file mode 100644
index 5f27242027..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/button_process.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/button_process_2.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/button_process_2.png
deleted file mode 100644
index 04b818a702..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/button_process_2.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon.png
deleted file mode 100644
index 654dd41405..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon.xpm b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon.xpm
deleted file mode 100644
index 9057c20bc6..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon.xpm
+++ /dev/null
@@ -1,21 +0,0 @@
-/* XPM */
-static const char * icon_xpm[] = {
-"16 16 2 1",
-" c #FF0000",
-". c #000000",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon_32.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon_32.png
deleted file mode 100644
index 6a4983c45f..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/icon_32.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_brain.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_brain.png
deleted file mode 100644
index bb1a26025c..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_brain.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_process.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_process.png
deleted file mode 100644
index 60f1ec5813..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_process.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_process_2.png b/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_process_2.png
deleted file mode 100644
index 33f989d1c0..0000000000
Binary files a/Plugins/org.mitk.gui.qt.classificationsegmentation/resources/orig_process_2.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrow.cpp b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrow.cpp
deleted file mode 100644
index 01a7afcf61..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrow.cpp
+++ /dev/null
@@ -1,619 +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.
-
-============================================================================*/
-// STD
-#include <stack>
-
-
-// Blueberry
-#include <berryISelectionService.h>
-#include <berryIWorkbenchWindow.h>
-
-// Qmitk
-#include "ClassificationRegionGrow.h"
-
-// Qt
-#include <QMessageBox>
-#include <qgroupbox.h>
-#include <qsignalmapper.h>
-
-//mitk image
-#include <mitkImage.h>
-#include <QmitkDataStorageComboBox.h>
-#include <mitkNodePredicateDataType.h>
-#include <mitkNodePredicateOr.h>
-#include "mitkVigraRandomForestClassifier.h"
-#include "mitkCLUtil.h"
-#include "qboxlayout.h"
-#include <mitkIOUtil.h>
-
-#include "Eigen/Dense"
-
-#include <mitkImageAccessByItk.h>
-#include <mitkSliceNavigationController.h>
-#include <vnl/vnl_random.h>
-
-#include <itkNeighborhoodFunctorImageFilter.h>
-#include <itkFirstOrderStatisticsFeatureFunctor.h>
-#include <itkNeighborhood.h>
-#include <itkHessianMatrixEigenvalueImageFilter.h>
-#include <itkStructureTensorEigenvalueImageFilter.h>
-#include <itkLineHistogramBasedMassImageFilter.h>
-#include <mitkHistogramGenerator.h>
-
-#include <itkImageRegionConstIteratorWithIndex.h>
-#include <itkImageRegionConstIterator.h>
-
-#include "mitkLabelSetImage.h"
-
-#include <mitkLookupTable.h>
-#include <mitkLookupTableProperty.h>
-
-#include <QFuture>
-#include <QFutureWatcher>
-#include <QtConcurrentRun>
-#include <QmitkIOUtil.h>
-const std::string ClassificationRegionGrow::VIEW_ID = "org.mitk.views.ClassificationRegionGrow";
-
-void ClassificationRegionGrow::SetFocus()
-{
- // m_Controls.buttonPerformImageProcessing->setFocus();
-}
-
-void ClassificationRegionGrow::CreateQtPartControl( QWidget *parent )
-{
- // create GUI widgets from the Qt Designer's .ui file
- m_Controls.setupUi( parent );
- m_CalculateFeatures = true;
- m_BlockManualSegmentation = false;
- m_BlockPostProcessing = false;
-
- m_Controls.groupLearningParameter->setVisible(false);
- m_Controls.groupFeatureSelection->setVisible(false);
-
- QmitkDataStorageComboBox * cb_inputimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- QmitkDataStorageComboBox * cb_maskimage= new QmitkDataStorageComboBox(this->GetDataStorage(),mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
- QmitkDataStorageComboBox * cb_baseimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
-
- m_Controls.m_InputImageLayout->addWidget(cb_inputimage);
- m_Controls.m_MaskImageLayout->addWidget(cb_maskimage);
- m_Controls.StartingPointLayout->addWidget(cb_baseimage);
- m_Controls.addInputButton->setIcon(QIcon::fromTheme("list-add"));
- m_Controls.removeInputButton->setIcon(QIcon::fromTheme("edit-delete"));
-
- connect( cb_inputimage, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnInitializeSession(const mitk::DataNode*)));
- connect( cb_maskimage, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnInitializeSession(const mitk::DataNode*)));
- connect(m_Controls.SelectAdvancedParameter, SIGNAL(toggled(bool)), m_Controls.groupLearningParameter, SLOT(setVisible(bool)));
- connect(m_Controls.SelectAdvancedParameter, SIGNAL(toggled(bool)), m_Controls.groupFeatureSelection, SLOT(setVisible(bool)));
- connect(m_Controls.SelectSimpleParameters, SIGNAL(toggled(bool)), m_Controls.parameterWidget, SLOT(setVisible(bool)));
- connect(m_Controls.m_DoAutomaticSecmentation, SIGNAL( clicked()), this, SLOT(DoAutomSegmentation()));
- connect(m_Controls.removeInputButton, SIGNAL(clicked()), this, SLOT(RemoveItemFromLabelList()));
- connect(m_Controls.addInputButton, SIGNAL(clicked()), this, SLOT(AddInputField()));
-
- connect(m_Controls.UseIntensity, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.Gauss1, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.Gauss2, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.Gauss3, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.Gauss4, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.Gauss5, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.DoG1, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.DoG2, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.DoG3, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.DoG4, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.DoG5, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LoG1, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LoG2, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LoG3, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LoG4, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LoG5, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.HoG1, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.HoG2, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.HoG3, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.HoG4, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.HoG5, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LH1, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LH2, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LH3, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
- connect(m_Controls.LH4, SIGNAL(toggled(bool)), this, SLOT(OnFeatureSettingsChanged()));
-}
-
-void ClassificationRegionGrow::AddInputField()
-{
- QmitkDataStorageComboBox * cb_inputimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- //QPushButton * lockButton = new QPushButton();
- //lockButton->setText("");
- //lockButton->setMinimumWidth(40);
- //lockButton->setCheckable(true);
- //lockButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaStop));
-
- QHBoxLayout *layout = new QHBoxLayout;
- layout->addWidget(cb_inputimage,100);
- //layout->addWidget(lockButton,1);
- m_Controls.m_InputImageLayout->addLayout(layout);
- connect(cb_inputimage, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnInitializeSession(const mitk::DataNode*)));
-}
-
-void ClassificationRegionGrow::RemoveItemFromLabelList()
-{
- auto numberOfElements = m_Controls.m_InputImageLayout->count();
- auto lastItem = m_Controls.m_InputImageLayout->itemAt(numberOfElements-1);
- QHBoxLayout *layout = dynamic_cast<QHBoxLayout *>(lastItem);
- while (QLayoutItem* item = layout->takeAt(0))
- {
- if (QWidget* widget = item->widget())
- widget->deleteLater();
- delete item;
- }
- m_Controls.m_InputImageLayout->removeItem(lastItem);
- delete lastItem;
-
-}
-
-void ClassificationRegionGrow::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/,
- const QList<mitk::DataNode::Pointer>& nodes )
-{
- // iterate all selected objects, adjust warning visibility
- foreach( mitk::DataNode::Pointer node, nodes )
- {
- if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
- {
- return;
- }
- }
-}
-
-void ClassificationRegionGrow::OnInitializeSession(const mitk::DataNode *)
-{
- OnFeatureSettingsChanged();
-}
-
-void ClassificationRegionGrow::ProcessFeatureImages(const mitk::Image::Pointer & raw_image)
-{
- // RAW
- if (m_Controls.UseIntensity->isChecked()) {
- m_FeatureImageVector.push_back(raw_image);
- }
-
- // GAUSS
- if (m_Controls.Gauss1->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::GaussianFilter(raw_image, smoothed, 1);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.Gauss2->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::GaussianFilter(raw_image, smoothed, 2);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.Gauss3->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::GaussianFilter(raw_image, smoothed, 3);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.Gauss4->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::GaussianFilter(raw_image, smoothed, 4);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.Gauss5->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::GaussianFilter(raw_image, smoothed, 5);
- m_FeatureImageVector.push_back(smoothed);
- }
-
- // Difference of Gaussian
- if (m_Controls.DoG1->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::DifferenceOfGaussianFilter(raw_image, smoothed, 1,0.8);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.DoG2->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::DifferenceOfGaussianFilter(raw_image, smoothed, 2, 1.8);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.DoG3->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::DifferenceOfGaussianFilter(raw_image, smoothed, 3, 2.6);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.DoG4->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::DifferenceOfGaussianFilter(raw_image, smoothed, 4, 3.4);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.DoG5->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::DifferenceOfGaussianFilter(raw_image, smoothed, 5, 4.3);
- m_FeatureImageVector.push_back(smoothed);
- }
-
- // Laplacian of Gaussian
- if (m_Controls.LoG1->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::LaplacianOfGaussianFilter(raw_image, smoothed, 1);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.LoG2->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::LaplacianOfGaussianFilter(raw_image, smoothed, 2);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.LoG3->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::LaplacianOfGaussianFilter(raw_image, smoothed, 3);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.LoG4->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::LaplacianOfGaussianFilter(raw_image, smoothed, 4);
- m_FeatureImageVector.push_back(smoothed);
- }
- if (m_Controls.LoG5->isChecked())
- {
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::LaplacianOfGaussianFilter(raw_image, smoothed, 5);
- m_FeatureImageVector.push_back(smoothed);
- }
-
- // Hessian of Gaussian
- if (m_Controls.HoG1->isChecked())
- {
- mitk::CLUtil::HessianOfGaussianFilter(raw_image, m_FeatureImageVector, 1);
- }
- if (m_Controls.HoG2->isChecked())
- {
- mitk::CLUtil::HessianOfGaussianFilter(raw_image, m_FeatureImageVector, 2);
- }
- if (m_Controls.HoG3->isChecked())
- {
- mitk::CLUtil::HessianOfGaussianFilter(raw_image, m_FeatureImageVector, 3);
- }
- if (m_Controls.HoG4->isChecked())
- {
- mitk::CLUtil::HessianOfGaussianFilter(raw_image, m_FeatureImageVector, 4);
- }
- if (m_Controls.HoG5->isChecked())
- {
- mitk::CLUtil::HessianOfGaussianFilter(raw_image, m_FeatureImageVector, 5);
- }
-
- // LocalHistogram
- if (m_Controls.LH1->isChecked())
- {
- mitk::CLUtil::LocalHistogram(raw_image, m_FeatureImageVector, 5,3);
- }
- if (m_Controls.LH2->isChecked())
- {
- mitk::CLUtil::LocalHistogram(raw_image, m_FeatureImageVector, 5, 5);
- }
- if (m_Controls.LH3->isChecked())
- {
- mitk::CLUtil::LocalHistogram(raw_image, m_FeatureImageVector, 10, 3);
- }
- if (m_Controls.LH4->isChecked())
- {
- mitk::CLUtil::LocalHistogram(raw_image, m_FeatureImageVector, 10, 5);
- }
-}
-
-void ClassificationRegionGrow::OnFeatureSettingsChanged()
-{
- MITK_INFO << "FeatureSettingsChanged";
- m_CalculateFeatures = true;
-}
-
-void ClassificationRegionGrow::DoAutomSegmentation()
-{
- MITK_INFO << "Start Automatic Segmentation ...";
- // Load Images from registration process
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_InputImageLayout->itemAt(1)->widget());
- QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_MaskImageLayout->itemAt(1)->widget());
- mitk::Image::Pointer raw_image;
- mitk::Image::Pointer mask_image;
- if ((cb_image != nullptr) || (cb_maskimage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(cb_image->GetSelectedNode()->GetData());
- mask_image = dynamic_cast<mitk::Image *>(cb_maskimage->GetSelectedNode()->GetData());
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
-
- if (raw_image.IsNull() || mask_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- std::vector<mitk::Image::Pointer> imageList;
- imageList.push_back(raw_image);
- for (int i = 2; i < m_Controls.m_InputImageLayout->count(); ++i)
- {
- QLayout* layout = dynamic_cast<QLayout*>(m_Controls.m_InputImageLayout->itemAt(i));
- MITK_INFO << layout;
- QmitkDataStorageComboBox * tmp_cb_image = dynamic_cast<QmitkDataStorageComboBox *>(layout->itemAt(0)->widget());
- MITK_INFO << tmp_cb_image;
- if (tmp_cb_image)
- {
- mitk::Image::Pointer tmp_image = dynamic_cast<mitk::Image *>(tmp_cb_image);
- if (tmp_image.IsNotNull())
- {
- MITK_INFO << "Adding Image...";
- imageList.push_back(tmp_image);
- }
- }
- }
-
- MITK_INFO << "Start Feature Calculation ...";
- if(m_CalculateFeatures)
- {
- m_FeatureImageVector.clear();
- for (auto img : imageList)
- {
- ProcessFeatureImages(img);
- }
- m_CalculateFeatures = false;
- if (m_Controls.checkAddFeaturesToDataManager->isChecked())
- {
- for (std::size_t i = 0; i < m_FeatureImageVector.size(); ++i)
- {
- auto newName = "Feature_" + std::to_string(i);
- AddAsDataNode(m_FeatureImageVector[i].GetPointer(), newName);
- }
- }
- }
-
- MITK_INFO << "Start Classifier Training ...";
- TrainClassifier(raw_image, mask_image);
-
- MITK_INFO << "Predict extended Segmentation ...";
- PredictSegmentation(raw_image, mask_image);
-}
-
-
-void ClassificationRegionGrow::TrainClassifier(const mitk::Image::Pointer & raw_image, const mitk::Image::Pointer & mask_image)
-{
- typedef itk::Image<double, 3> DoubleImageType;
- typedef itk::Image<short, 3> ShortImageType;
-
- DoubleImageType::Pointer input;
- ShortImageType::Pointer mask;
- mitk::CastToItkImage(raw_image, input);
- mitk::CastToItkImage(mask_image, mask);
-
- int numberOfSegmentedVoxel = 0;
- int numberOfFeatures = m_FeatureImageVector.size();
-
- auto maskIter = itk::ImageRegionConstIteratorWithIndex<ShortImageType>(mask, mask->GetLargestPossibleRegion());
- m_SegmentedLocations.clear();
- m_SegmentedOrganLocations.clear();
-
- MITK_INFO << "Count Segmentation Size ...";
- while ( ! maskIter.IsAtEnd())
- {
- if (maskIter.Value() > 0)
- {
- m_SegmentedLocations.push_back(maskIter.GetIndex());
- numberOfSegmentedVoxel++;
- if (maskIter.Value() > 1)
- {
- m_SegmentedOrganLocations.push_back(maskIter.GetIndex());
- }
- }
- ++maskIter;
- }
- MITK_INFO << "Sizes: " << numberOfSegmentedVoxel << " " << m_SegmentedOrganLocations.size();
-
- Eigen::MatrixXi Y_train = mitk::CLUtil::Transform<int>(mask_image, mask_image);
- Eigen::MatrixXd X_train = Eigen::MatrixXd(numberOfSegmentedVoxel, numberOfFeatures);
- unsigned int index = 0;
-
- MITK_INFO << "Convert Training Data to Eigen Matrix ...";
- for (const auto & image : m_FeatureImageVector)
- {
- X_train.col(index) = mitk::CLUtil::Transform<double>(image, mask_image);
- ++index;
- }
-
- MITK_INFO << "Classifier Training ...";
- m_Classifier = mitk::VigraRandomForestClassifier::New();
- //this->m_Controls.Maximum
- m_Classifier->SetTreeCount(m_Controls.NumberOfTrees->value());
- m_Classifier->SetSamplesPerTree(m_Controls.SamplesPerTree->value());
- m_Classifier->SetMinimumSplitNodeSize(m_Controls.MinimumSamplesPerNode->value());
- m_Classifier->SetMaximumTreeDepth(m_Controls.MaximumTreeDepth->value());
- m_Classifier->Train(X_train, Y_train);
-}
-
-static void addNeighbours(std::stack<itk::Index<3> > &stack, itk::Index<3> idx)
-{
- idx[0] -= 1;
- stack.push(idx);
- idx[0] += 2;
- stack.push(idx);
- idx[0] -= 1;
- idx[1] -= 1;
- stack.push(idx);
- idx[1] += 2;
- stack.push(idx);
- idx[1] -= 1;
- idx[2] -= 1;
- stack.push(idx);
- idx[2] += 2;
- stack.push(idx);
-}
-
-void ClassificationRegionGrow::PredictSegmentation(const mitk::Image::Pointer & raw_image, const mitk::Image::Pointer & mask_image)
-{
- typedef itk::Image<double, 3> DoubleImageType;
- typedef itk::Image<unsigned short, 3> ShortImageType;
-
- DoubleImageType::Pointer input;
- ShortImageType::Pointer mask;
- mitk::CastToItkImage(raw_image, input);
- mitk::CastToItkImage(mask_image, mask);
-
- std::vector<DoubleImageType::Pointer > featureImages;
- for (auto fimage : m_FeatureImageVector)
- {
- DoubleImageType::Pointer feature;
- mitk::CastToItkImage(fimage, feature);
- featureImages.push_back(feature);
- }
-
- ShortImageType::Pointer usedLocation = ShortImageType::New();
- usedLocation->SetRegions(mask->GetLargestPossibleRegion());
- usedLocation->Allocate();
- usedLocation->FillBuffer(0);
-
- ShortImageType::Pointer resultSegmentation = ShortImageType::New();
- if (m_Controls.UpdateImage->isChecked()) {
- QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.StartingPointLayout->itemAt(2)->widget());
- mitk::Image::Pointer base_image = dynamic_cast<mitk::Image *>(cb_maskimage->GetSelectedNode()->GetData());
- mitk::CastToItkImage(base_image, resultSegmentation);
- }
- else {
-
- resultSegmentation->SetRegions(mask->GetLargestPossibleRegion());
- resultSegmentation->Allocate();
- if (m_Controls.SegmentBackground->isChecked())
- {
- resultSegmentation->FillBuffer(1);
- }
- else {
- resultSegmentation->FillBuffer(0);
- }
- }
-
- // Fill list of Stacks
- std::vector<std::stack<itk::Index<3> > > listOfStacks;
- while (m_SegmentedOrganLocations.size() > 0)
- {
- auto currentLocation = m_SegmentedOrganLocations.back();
- m_SegmentedOrganLocations.pop_back();
- std::size_t cValue = mask->GetPixel(currentLocation);
- resultSegmentation->SetPixel(currentLocation, cValue);
- usedLocation->SetPixel(currentLocation, 1000);
- while (listOfStacks.size() < cValue+1)
- {
- listOfStacks.push_back(std::stack<itk::Index<3> >());
- }
- addNeighbours(listOfStacks[cValue],currentLocation);
- }
-
-
- int countPredicted = 0;
- bool connectAllLabels = m_Controls.localGrowing->isChecked();
- //m_SegmentedOrganLocations.reserve(10000);
-
- Eigen::MatrixXd currentX = Eigen::MatrixXd(1, featureImages.size());
- vigra::MultiArrayView<2, double> X(vigra::Shape2(currentX.rows(), currentX.cols()), currentX.data());
- auto outLabel = Eigen::MatrixXi(currentX.rows(), 1);
- vigra::MultiArrayView<2, int> Y(vigra::Shape2(currentX.rows(), 1), outLabel.data());
- for (std::size_t i = 2; i < listOfStacks.size(); ++i)
- {
- while (listOfStacks[i].size() > 0)
- {
- auto currentLocation = listOfStacks[i].top();
- listOfStacks[i].pop();
- if (!mask->GetLargestPossibleRegion().IsInside(currentLocation))
- {
- continue;
- }
- if (usedLocation->GetPixel(currentLocation) > i)
- {
- continue;
- }
- usedLocation->SetPixel(currentLocation, i+1);
-
-
- for (std::size_t f = 0; f < featureImages.size(); ++f)
- {
- currentX(0, f) = featureImages[f]->GetPixel(currentLocation);
- }
-
- m_Classifier->GetRandomForest().predictLabels(X, Y);
- ++countPredicted;
- if ((static_cast<unsigned int>(Y(0, 0)) == i ) ||
- ((Y(0, 0) > 1) && (connectAllLabels)))
- {
- resultSegmentation->SetPixel(currentLocation, std::abs(Y(0, 0)));
- addNeighbours(listOfStacks[i], currentLocation);
- }
- }
- }
- MITK_INFO << "Number of Predictions: " << countPredicted;
-
- MITK_INFO << "Finished Segmentation...";
- mitk::Image::Pointer result;
- mitk::CastToMitkImage(resultSegmentation, result);
- result->SetOrigin(raw_image->GetGeometry()->GetOrigin());
- result->SetSpacing(raw_image->GetGeometry()->GetSpacing());
- mitk::LabelSetImage::Pointer labelResult = mitk::LabelSetImage::New();
- labelResult->InitializeByLabeledImage(result);
- mitk::LabelSetImage::Pointer oldLabelSet = dynamic_cast<mitk::LabelSetImage *>(mask_image.GetPointer());
- labelResult->AddLabelSetToLayer(labelResult->GetActiveLayer(),oldLabelSet->GetLabelSet());
- MITK_INFO << "Passing Back...";
- AddAsDataNode(labelResult.GetPointer(), "ResultSegmentation");
-}
-
-mitk::DataNode::Pointer ClassificationRegionGrow::AddAsDataNode(const mitk::BaseData::Pointer & data_, const std::string & name )
-{
- mitk::DataNode::Pointer node = nullptr;
- node = this->GetDataStorage()->GetNamedNode(name);
-
- if(node.IsNull())
- {
- node = mitk::DataNode::New();
- node->SetData(data_);
- node->SetName(name);
- this->GetDataStorage()->Add(node);
- }else{
-
- if(dynamic_cast<mitk::Image*>(node->GetData()) && dynamic_cast<mitk::Image*>(data_.GetPointer()))
- {
- mitk::Image::Pointer target_image = dynamic_cast<mitk::Image*>(node->GetData());
- mitk::Image::Pointer source_image = dynamic_cast<mitk::Image*>(data_.GetPointer());
- mitk::ImageReadAccessor ra(source_image);
- target_image->SetImportVolume(const_cast<void *>(ra.GetData()));
- this->RequestRenderWindowUpdate();
- }
-
- if(dynamic_cast<mitk::VigraRandomForestClassifier*>(node->GetData()) && dynamic_cast<mitk::VigraRandomForestClassifier*>(data_.GetPointer()))
- {
- node->SetData(data_);
- node->Modified();
- }
-
- }
-
- return node;
-}
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrow.h b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrow.h
deleted file mode 100644
index 04987f3a46..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrow.h
+++ /dev/null
@@ -1,99 +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.
-
-============================================================================*/
-
-#ifndef ClassificationRegionGrow_h
-#define ClassificationRegionGrow_h
-
-#include <berryISelectionListener.h>
-
-#include <QmitkAbstractView.h>
-
-#include "ui_ClassificationRegionGrowControls.h"
-#include <mitkImage.h>
-#include <itkConstNeighborhoodIterator.h>
-#include <itkNeighborhoodFunctorImageFilter.h>
-#include <itkFirstOrderStatisticsFeatureFunctor.h>
-
-#include <mitkImageCast.h>
-#include <itkHistogram.h>
-#include <QFutureWatcher>
-
-#include <mitkVigraRandomForestClassifier.h>
-/**
-\brief ClassificationRegionGrow
-
-\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation.
-
-\sa QmitkAbstractView
-\ingroup ${plugin_target}_internal
-*/
-
-class ctkSliderWidget;
-class ClassificationRegionGrow : public QmitkAbstractView
-{
- Q_OBJECT
-
-public:
-
- static const std::string VIEW_ID;
-
- bool m_CalculateFeatures;
-
- std::vector<mitk::Image::Pointer> m_FeatureImageVector;
- std::vector<mitk::Image::Pointer> m_ResultImageVector;
-
- bool m_BlockManualSegmentation;
- QFutureWatcher<std::vector<mitk::Image::Pointer>> m_ManualSegmentationFutureWatcher;
-
- bool m_BlockPostProcessing;
- QFutureWatcher<std::vector<mitk::Image::Pointer>> m_PostProcessingFutureWatcher;
-
- public slots:
-
- /// \brief Called when the user clicks the GUI button
- void DoAutomSegmentation();
- void AddInputField();
-
- void RemoveItemFromLabelList();
-
- void OnFeatureSettingsChanged();
- void OnInitializeSession(const mitk::DataNode*);
-
-protected:
- std::vector<itk::Index<3> > m_SegmentedLocations;
- std::vector<itk::Index<3> > m_SegmentedOrganLocations;
-
-
-
- typedef float MeasurementType;
- typedef itk::Statistics::Histogram< MeasurementType,
- itk::Statistics::DenseFrequencyContainer2 > HistogramType;
-
-
- void CreateQtPartControl(QWidget *parent) override;
- void SetFocus() override;
-
- mitk::DataNode::Pointer AddAsDataNode(const mitk::BaseData::Pointer & data_, const std::string & name );
-
- void ProcessFeatureImages(const mitk::Image::Pointer & raw_image);
- void TrainClassifier(const mitk::Image::Pointer & raw_image, const mitk::Image::Pointer & mask_image);
- void PredictSegmentation(const mitk::Image::Pointer & raw_image, const mitk::Image::Pointer & mask_image);
-
- void OnSelectionChanged( berry::IWorkbenchPart::Pointer source,
- const QList<mitk::DataNode::Pointer>& nodes ) override;
-
- Ui::ClassificationRegionGrowControls m_Controls;
-
- mitk::VigraRandomForestClassifier::Pointer m_Classifier;
-};
-
-#endif // ClassificationRegionGrow_h
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrowControls.ui b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrowControls.ui
deleted file mode 100644
index ad002f99b0..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationRegionGrowControls.ui
+++ /dev/null
@@ -1,593 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ClassificationRegionGrowControls</class>
- <widget class="QWidget" name="ClassificationRegionGrowControls">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>352</width>
- <height>979</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="windowTitle">
- <string>QmitkTemplate</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="label_2">
- <property name="font">
- <font>
- <pointsize>17</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- <underline>false</underline>
- <strikeout>false</strikeout>
- <stylestrategy>PreferAntialias</stylestrategy>
- <kerning>true</kerning>
- </font>
- </property>
- <property name="text">
- <string>Classifier Region Growing</string>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="m_InputImageLayout">
- <item>
- <widget class="QLabel" name="m_InputImageLabel">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Basic Image</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="addInputButton">
- <property name="text">
- <string/>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="removeInputButton">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="m_MaskImageLayout">
- <item>
- <widget class="QLabel" name="m_MaskImageLabel">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Segmentation Image</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="Line" name="line_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="m_DoAutomaticSecmentation">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>64</height>
- </size>
- </property>
- <property name="font">
- <font>
- <family>Segoe UI</family>
- <pointsize>14</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Update Segmentation</string>
- </property>
- <property name="icon">
- <iconset resource="../../resources/ClassificationSegmentation.qrc">
- <normaloff>:/ClassificationSegmentation/button_process_2.png</normaloff>:/ClassificationSegmentation/button_process_2.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>32</width>
- <height>32</height>
- </size>
- </property>
- <property name="shortcut">
- <string>Ctrl+A</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="SelectSimpleParameters">
- <property name="title">
- <string>Parameters</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <widget class="QWidget" name="parameterWidget" native="true">
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <widget class="QCheckBox" name="SegmentBackground">
- <property name="text">
- <string>Segment Background (First Label)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="localGrowing">
- <property name="text">
- <string>Connectness for all labels</string>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QFormLayout" name="StartingPointLayout">
- <item row="0" column="0">
- <widget class="QCheckBox" name="UpdateImage">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Use existing segmentation as starting point</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="SelectAdvancedParameter">
- <property name="title">
- <string>Advanced Parameter</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QGroupBox" name="groupLearningParameter">
- <property name="title">
- <string>Learning Parameters</string>
- </property>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Samples per Tree: </string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QDoubleSpinBox" name="SamplesPerTree">
- <property name="minimum">
- <double>0.010000000000000</double>
- </property>
- <property name="maximum">
- <double>1.000000000000000</double>
- </property>
- <property name="singleStep">
- <double>0.100000000000000</double>
- </property>
- <property name="value">
- <double>0.660000000000000</double>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Number of Trees: </string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="NumberOfTrees">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>2000</number>
- </property>
- <property name="value">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Minimum Samples per Node: </string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QSpinBox" name="MinimumSamplesPerNode">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>200000</number>
- </property>
- <property name="value">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Maximum Tree depth:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QSpinBox" name="MaximumTreeDepth">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>2000000</number>
- </property>
- <property name="value">
- <number>100</number>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupFeatureSelection">
- <property name="title">
- <string>Feature Selection</string>
- </property>
- <property name="flat">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="5" column="4">
- <widget class="QCheckBox" name="LoG4">
- <property name="text">
- <string>4</string>
- </property>
- </widget>
- </item>
- <item row="5" column="3">
- <widget class="QCheckBox" name="LoG3">
- <property name="text">
- <string>3</string>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Laplacian of Gauss:</string>
- </property>
- </widget>
- </item>
- <item row="6" column="5">
- <widget class="QCheckBox" name="HoG5">
- <property name="text">
- <string>5</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>Intensity Value:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="4">
- <widget class="QCheckBox" name="Gauss4">
- <property name="text">
- <string>4</string>
- </property>
- </widget>
- </item>
- <item row="8" column="0">
- <widget class="QLabel" name="label_13">
- <property name="text">
- <string> ( Neigh. Size / Bins)</string>
- </property>
- </widget>
- </item>
- <item row="6" column="3">
- <widget class="QCheckBox" name="HoG3">
- <property name="text">
- <string>3</string>
- </property>
- </widget>
- </item>
- <item row="5" column="2">
- <widget class="QCheckBox" name="LoG2">
- <property name="text">
- <string>2</string>
- </property>
- </widget>
- </item>
- <item row="9" column="0" colspan="5">
- <widget class="QCheckBox" name="checkAddFeaturesToDataManager">
- <property name="text">
- <string>Add Feature Images to DataManager</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>Diff. of Gauss: </string>
- </property>
- </widget>
- </item>
- <item row="6" column="4">
- <widget class="QCheckBox" name="HoG4">
- <property name="text">
- <string>4</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QCheckBox" name="DoG1">
- <property name="text">
- <string>1</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QCheckBox" name="Gauss1">
- <property name="text">
- <string>1 </string>
- </property>
- </widget>
- </item>
- <item row="1" column="5">
- <widget class="QCheckBox" name="Gauss5">
- <property name="text">
- <string>5</string>
- </property>
- </widget>
- </item>
- <item row="1" column="3">
- <widget class="QCheckBox" name="Gauss3">
- <property name="text">
- <string>3</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QCheckBox" name="UseIntensity">
- <property name="text">
- <string/>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="5" column="5">
- <widget class="QCheckBox" name="LoG5">
- <property name="text">
- <string>5</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QCheckBox" name="HoG1">
- <property name="text">
- <string>1</string>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>Hessian of Gaussian:</string>
- </property>
- </widget>
- </item>
- <item row="6" column="2">
- <widget class="QCheckBox" name="HoG2">
- <property name="text">
- <string>2</string>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
- <widget class="QLabel" name="label_12">
- <property name="text">
- <string>Local Histogram</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QCheckBox" name="Gauss2">
- <property name="text">
- <string>2</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>Gaussian smoothed:</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QCheckBox" name="LoG1">
- <property name="text">
- <string>1</string>
- </property>
- </widget>
- </item>
- <item row="4" column="2">
- <widget class="QCheckBox" name="DoG2">
- <property name="text">
- <string>2</string>
- </property>
- </widget>
- </item>
- <item row="4" column="4">
- <widget class="QCheckBox" name="DoG4">
- <property name="text">
- <string>4</string>
- </property>
- </widget>
- </item>
- <item row="4" column="3">
- <widget class="QCheckBox" name="DoG3">
- <property name="text">
- <string>3</string>
- </property>
- </widget>
- </item>
- <item row="4" column="5">
- <widget class="QCheckBox" name="DoG5">
- <property name="text">
- <string>5</string>
- </property>
- </widget>
- </item>
- <item row="7" column="1" colspan="2">
- <widget class="QCheckBox" name="LH1">
- <property name="text">
- <string>3/5</string>
- </property>
- </widget>
- </item>
- <item row="8" column="1" colspan="2">
- <widget class="QCheckBox" name="LH2">
- <property name="text">
- <string>5/5</string>
- </property>
- </widget>
- </item>
- <item row="7" column="3" colspan="2">
- <widget class="QCheckBox" name="LH3">
- <property name="text">
- <string>3/10</string>
- </property>
- </widget>
- </item>
- <item row="8" column="3" colspan="2">
- <widget class="QCheckBox" name="LH4">
- <property name="text">
- <string>5/10</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QFrame" name="frame">
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <resources>
- <include location="../../resources/ClassificationSegmentation.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentation.cpp b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentation.cpp
deleted file mode 100644
index 3c593e5c3c..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentation.cpp
+++ /dev/null
@@ -1,969 +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.
-
-============================================================================*/
-
-// Blueberry
-#include <berryISelectionService.h>
-#include <berryIWorkbenchWindow.h>
-
-// Qmitk
-#include "ClassificationSegmentation.h"
-
-// Qt
-#include <QMessageBox>
-
-//mitk image
-#include <mitkImage.h>
-#include <QmitkDataStorageComboBox.h>
-#include <ctkSliderWidget.h>
-#include <mitkPointSet.h>
-#include <mitkNodePredicateDataType.h>
-#include <mitkNodePredicateOr.h>
-#include "mitkVigraRandomForestClassifier.h"
-#include "mitkCLUtil.h"
-#include "qboxlayout.h"
-#include <mitkIOUtil.h>
-
-#include "Eigen/Dense"
-
-#include <mitkImageAccessByItk.h>
-#include <mitkSliceNavigationController.h>
-#include <vnl/vnl_random.h>
-
-#include <itkNeighborhoodFunctorImageFilter.h>
-#include <itkFirstOrderStatisticsFeatureFunctor.h>
-#include <itkNeighborhood.h>
-#include <itkHessianMatrixEigenvalueImageFilter.h>
-#include <itkStructureTensorEigenvalueImageFilter.h>
-#include <itkLineHistogramBasedMassImageFilter.h>
-#include <mitkHistogramGenerator.h>
-
-#include <itkImageRegionConstIteratorWithIndex.h>
-#include <itkImageRegionConstIterator.h>
-
-#include <mitkLookupTable.h>
-#include <mitkLookupTableProperty.h>
-
-#include <QFuture>
-#include <QFutureWatcher>
-#include <QtConcurrentRun>
-#include <QmitkIOUtil.h>
-const std::string ClassificationSegmentation::VIEW_ID = "org.mitk.views.classificationsegmentation";
-
-void ClassificationSegmentation::SetFocus()
-{
- // m_Controls.buttonPerformImageProcessing->setFocus();
-}
-
-void ClassificationSegmentation::OnButtonCSFToggle(bool checked)
-{
- if(checked)
- m_PointSetDataInteractor->SetDataNode(m_PointSetList[0]);
- else
- m_PointSetDataInteractor->SetDataNode(nullptr);
-}
-
-void ClassificationSegmentation::OnButtonLESToggle(bool checked)
-{
- if(checked)
- m_PointSetDataInteractor->SetDataNode(m_PointSetList[1]);
- else
- m_PointSetDataInteractor->SetDataNode(nullptr);
-}
-
-void ClassificationSegmentation::OnButtonBRAToggle(bool checked)
-{
- if(checked)
- m_PointSetDataInteractor->SetDataNode(m_PointSetList[2]);
- else
- m_PointSetDataInteractor->SetDataNode(nullptr);
-}
-
-void ClassificationSegmentation::OnButtonNoInteractionToggle(bool checked)
-{
- if(checked)
- m_PointSetDataInteractor->SetDataNode(nullptr);
-}
-
-void ClassificationSegmentation::CreateQtPartControl( QWidget *parent )
-{
- // create GUI widgets from the Qt Designer's .ui file
- m_Controls.setupUi( parent );
- m_CalculateFeatures = true;
- m_BlockManualSegmentation = false;
- m_BlockPostProcessing = false;
-
- QmitkDataStorageComboBox * cb_inputimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- QmitkDataStorageComboBox * cb_maskimage= new QmitkDataStorageComboBox(this->GetDataStorage(),mitk::TNodePredicateDataType<mitk::Image>::New());
- QmitkDataStorageComboBox * cb_classifer= new QmitkDataStorageComboBox(this->GetDataStorage(),mitk::TNodePredicateDataType<mitk::VigraRandomForestClassifier>::New());
-
- m_Controls.m_InputImageLayout->addWidget(cb_inputimage);
- m_Controls.m_MaskImageLayout->addWidget(cb_maskimage);
- m_Controls.m_ClassifierLayout->addWidget(cb_classifer);
-
- m_Controls.m_ParameterLayout->layout()->addWidget(new QLabel("Gauss Sigma"));
- m_GaussSlider = new ctkSliderWidget();
- m_GaussSlider->setMinimum(0);
- m_GaussSlider->setMaximum(10);
- m_GaussSlider->setValue(1);
- m_Controls.m_ParameterLayout->layout()->addWidget(m_GaussSlider);
-
- m_Controls.m_ParameterLayout->layout()->addWidget(new QLabel("Hessian Sigma"));
- m_HessianSlider = new ctkSliderWidget();
- m_HessianSlider->setMinimum(0);
- m_HessianSlider->setMaximum(10);
- m_HessianSlider->setValue(3);
- m_Controls.m_ParameterLayout->layout()->addWidget(m_HessianSlider);
-
- m_Controls.m_ParameterLayout->layout()->addWidget(new QLabel("Structure Tensor Inner and Outer Scale"));
- m_STInnerSlider = new ctkSliderWidget();
- m_STInnerSlider->setMinimum(0);
- m_STInnerSlider->setMaximum(10);
- m_STInnerSlider->setValue(1.5);
- m_Controls.m_ParameterLayout->layout()->addWidget(m_STInnerSlider);
-
- m_STOuterSlider = new ctkSliderWidget();
- m_STOuterSlider->setMinimum(0);
- m_STOuterSlider->setMaximum(10);
- m_STOuterSlider->setValue(3);
- m_Controls.m_ParameterLayout->layout()->addWidget(m_STOuterSlider);
-
- m_Controls.m_PostProcessingLayout->layout()->addWidget(new QLabel("Probability map smoothing"));
- m_GaussCSFSlider = new ctkSliderWidget;
- m_GaussCSFSlider->setMinimum(0);
- m_GaussCSFSlider->setMaximum(10);
- m_GaussCSFSlider->setValue(1.5);
- m_Controls.m_PostProcessingLayout->layout()->addWidget(m_GaussCSFSlider);
-
- m_GaussLESSlider = new ctkSliderWidget;
- m_GaussLESSlider->setMinimum(0);
- m_GaussLESSlider->setMaximum(10);
- m_GaussLESSlider->setValue(3);
- m_Controls.m_PostProcessingLayout->layout()->addWidget(m_GaussLESSlider);
-
- m_GaussBRASlider = new ctkSliderWidget;
- m_GaussBRASlider->setMinimum(0);
- m_GaussBRASlider->setMaximum(10);
- m_GaussBRASlider->setValue(0.5);
- m_Controls.m_PostProcessingLayout->layout()->addWidget(m_GaussBRASlider);
-
- m_Controls.m_PostProcessingLayout->layout()->addWidget(new QLabel("Probability map weighting"));
- m_WeightCSFSlider = new ctkSliderWidget;
- m_WeightCSFSlider->setMinimum(0.0);
- m_WeightCSFSlider->setMaximum(2.0);
- m_WeightCSFSlider->setValue(1.0);
- m_WeightCSFSlider->setSingleStep(0.1);
- m_Controls.m_PostProcessingLayout->layout()->addWidget(m_WeightCSFSlider);
-
- m_WeightLESSlider = new ctkSliderWidget;
- m_WeightLESSlider->setMinimum(0.0);
- m_WeightLESSlider->setMaximum(2.0);
- m_WeightLESSlider->setValue(1.0);
- m_WeightLESSlider->setSingleStep(0.1);
- m_Controls.m_PostProcessingLayout->layout()->addWidget(m_WeightLESSlider);
-
- m_WeightBRASlider = new ctkSliderWidget;
- m_WeightBRASlider->setMinimum(0.0);
- m_WeightBRASlider->setMaximum(2.0);
- m_WeightBRASlider->setValue(1.0);
- m_WeightBRASlider->setSingleStep(0.1);
- m_Controls.m_PostProcessingLayout->layout()->addWidget(m_WeightBRASlider);
-
- m_PointSetDataInteractor = mitk::PointSetDataInteractor::New();
- m_PointSetDataInteractor->LoadStateMachine("PointSet.xml");
- m_PointSetDataInteractor->SetEventConfig("PointSetConfig.xml");
-
- connect( cb_inputimage, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnInitializeSession(const mitk::DataNode*)));
- connect( cb_maskimage, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnInitializeSession(const mitk::DataNode*)));
-
- connect( m_Controls.m_SavePointsButton, SIGNAL(clicked(bool)), this, SLOT(DoSavePointsAsMask()));
-
- connect( m_Controls.m_ButtonCSFToggle, SIGNAL(toggled(bool)), this, SLOT(OnButtonCSFToggle(bool)));
- connect( m_Controls.m_ButtonLESToggle, SIGNAL(toggled(bool)), this, SLOT(OnButtonLESToggle(bool)));
- connect( m_Controls.m_ButtonBRAToggle, SIGNAL(toggled(bool)), this, SLOT(OnButtonBRAToggle(bool)));
- connect( m_Controls.m_ButtonNoInteraction, SIGNAL(toggled(bool)), this, SLOT(OnButtonNoInteractionToggle(bool)));
- connect( &m_ManualSegmentationFutureWatcher, SIGNAL(finished()), this, SLOT(ManualSegmentationFinished()));
- connect( &m_PostProcessingFutureWatcher, SIGNAL(finished()), this, SLOT(PostProcessingFinished()));
-
- //connect( m_Controls.m_AddPointSets, SIGNAL(clicked()),this, SLOT(OnAddPointSets()) );
- connect( m_GaussSlider, SIGNAL(valueChanged(double)), this, SLOT(OnFeatureSettingsChanged()));
- connect( m_HessianSlider, SIGNAL(valueChanged(double)), this, SLOT(OnFeatureSettingsChanged()));
- connect( m_STInnerSlider, SIGNAL(valueChanged(double)), this, SLOT(OnFeatureSettingsChanged()));
- connect( m_STOuterSlider, SIGNAL(valueChanged(double)), this, SLOT(OnFeatureSettingsChanged()));
-
- connect( m_GaussCSFSlider, SIGNAL(valueChanged(double)), this, SLOT(OnPostProcessingSettingsChanged()));
- connect( m_GaussLESSlider, SIGNAL(valueChanged(double)), this, SLOT(OnPostProcessingSettingsChanged()));
- connect( m_GaussBRASlider, SIGNAL(valueChanged(double)), this, SLOT(OnPostProcessingSettingsChanged()));
- connect( m_WeightCSFSlider, SIGNAL(valueChanged(double)), this, SLOT(OnPostProcessingSettingsChanged()));
- connect( m_WeightLESSlider, SIGNAL(valueChanged(double)), this, SLOT(OnPostProcessingSettingsChanged()));
- connect( m_WeightBRASlider, SIGNAL(valueChanged(double)), this, SLOT(OnPostProcessingSettingsChanged()));
-
- connect(m_Controls.m_DoAutomaticSecmentation, SIGNAL(clicked(bool)), this, SLOT(DoAutomSegmentation()));
- connect(m_Controls.m_AddForestToDataManager, SIGNAL(clicked(bool)), this, SLOT(OnAddForestToDataManager()));
-
- mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New();
- pointSetNode->SetName("CSF_Points.");
- pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true));
- pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024));
- pointSetNode->SetColor(0,1.0,0);
- pointSetNode->SetDataInteractor(m_PointSetDataInteractor.GetPointer());
- m_PointSetList.push_back(pointSetNode);
- GetDataStorage()->Add(pointSetNode);
-
- pointSetNode = mitk::DataNode::New();
- pointSetNode->SetName("LES_Points.");
- pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true));
- pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024));
- pointSetNode->SetColor(1.0,0,0);
- pointSetNode->SetDataInteractor(m_PointSetDataInteractor.GetPointer());
- m_PointSetList.push_back(pointSetNode);
- GetDataStorage()->Add(pointSetNode);
-
- pointSetNode = mitk::DataNode::New();
- pointSetNode->SetName("BRA_Points.");
- pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true));
- pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024));
- pointSetNode->SetColor(0,0,1.0);
- pointSetNode->SetDataInteractor(m_PointSetDataInteractor.GetPointer());
- m_PointSetList.push_back(pointSetNode);
- GetDataStorage()->Add(pointSetNode);
-
-
- m_Controls.m_PostProcessingLayout->hide();
- m_Controls.m_ParameterLayout->hide();
-}
-
-void ClassificationSegmentation::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/,
- const QList<mitk::DataNode::Pointer>& nodes )
-{
- // iterate all selected objects, adjust warning visibility
- foreach( mitk::DataNode::Pointer node, nodes )
- {
- if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
- {
- // m_Controls.labelWarning->setVisible( false );
- // m_Controls.buttonPerformImageProcessing->setEnabled( true );
- return;
- }
- }
-
- // m_Controls.labelWarning->setVisible( true );
- // m_Controls.buttonPerformImageProcessing->setEnabled( false );
-}
-
-void ClassificationSegmentation::OnAddForestToDataManager()
-{
- AddAsDataNode(m_TempClassifier.GetPointer(),"ManualSegmentation_Classifier");
-}
-
-void ClassificationSegmentation::OnInitializeSession(const mitk::DataNode *)
-{
- MITK_WARN << "Data selection changed! New session initialized.";
-
- m_PointSetDataInteractor->SetDataNode(nullptr);
-
- /// CSF POINTSET
- mitk::PointSet::Pointer pntset = mitk::PointSet::New();
- m_PointSetList[0]->SetData(pntset);
-
- itk::SimpleMemberCommand<ClassificationSegmentation>::Pointer command = itk::SimpleMemberCommand<ClassificationSegmentation>::New();
- command->SetCallbackFunction(this, &ClassificationSegmentation::ManualSegmentationTrigger);
- pntset->AddObserver( mitk::PointSetAddEvent(), command );
- pntset->AddObserver( mitk::PointSetRemoveEvent(), command );
- pntset->AddObserver( mitk::PointSetMoveEvent(), command );
-
- /// LES POINTSET
- pntset = mitk::PointSet::New();
- m_PointSetList[1]->SetData(pntset);
-
- command = itk::SimpleMemberCommand<ClassificationSegmentation>::New();
- command->SetCallbackFunction(this, &ClassificationSegmentation::ManualSegmentationTrigger);
- pntset->AddObserver( mitk::PointSetAddEvent(), command );
- pntset->AddObserver( mitk::PointSetRemoveEvent(), command );
- pntset->AddObserver( mitk::PointSetMoveEvent(), command );
-
- /// BRA POINTSET
- pntset = mitk::PointSet::New();
- m_PointSetList[2]->SetData(pntset);
-
- command = itk::SimpleMemberCommand<ClassificationSegmentation>::New();
- command->SetCallbackFunction(this, &ClassificationSegmentation::ManualSegmentationTrigger);
- pntset->AddObserver( mitk::PointSetAddEvent(), command );
- pntset->AddObserver( mitk::PointSetRemoveEvent(), command );
- pntset->AddObserver( mitk::PointSetMoveEvent(), command );
-
-}
-
-void ClassificationSegmentation::DoSavePointsAsMask()
-{
- mitk::Image::Pointer sampled_image = nullptr;
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_InputImageLayout->itemAt(1)->widget());
- mitk::Image::Pointer raw_image = dynamic_cast<mitk::Image *>(cb_image->GetSelectedNode()->GetData());
-
- int label = 1;
- for( auto datanode : m_PointSetList)
- {
- mitk::PointSet::Pointer point_set = dynamic_cast<mitk::PointSet *>(datanode->GetData());
- mitk::Image::Pointer temp_img;
- SampleClassMaskByPointSet(raw_image, point_set,temp_img);
- mitk::CLUtil::InsertLabel(temp_img,sampled_image,label++);
- QmitkIOUtil::Save(datanode->GetData(),QString("PointSet.mps"));
- }
-
- QmitkIOUtil::Save(sampled_image,QString("PointSetMask.nrrd"));
-}
-void ClassificationSegmentation::ProcessFeatureImages(const mitk::Image::Pointer & raw_image, const mitk::Image::Pointer & brain_mask)
-{
- typedef itk::Image<double,3> DoubleImageType;
- typedef itk::Image<short,3> ShortImageType;
- typedef itk::ConstNeighborhoodIterator<DoubleImageType> NeighborhoodType; // Neighborhood iterator to access image
- typedef itk::Functor::NeighborhoodFirstOrderStatistics<NeighborhoodType, double> FunctorType;
- typedef itk::NeighborhoodFunctorImageFilter<DoubleImageType, DoubleImageType, FunctorType> FOSFilerType;
-
- m_FeatureImageVector.clear();
-
- // RAW
- m_FeatureImageVector.push_back(raw_image);
-
- // GAUSS
- mitk::Image::Pointer smoothed;
- mitk::CLUtil::GaussianFilter(raw_image,smoothed,m_GaussSlider->value());
- m_FeatureImageVector.push_back(smoothed);
-
- // Calculate Probability maps (parameters used from literatur)
- // CSF
- mitk::Image::Pointer csf_prob = mitk::Image::New();
- mitk::CLUtil::ProbabilityMap(smoothed,13.9, 8.3,csf_prob);
- m_FeatureImageVector.push_back(csf_prob);
-
- // Lesion
-
- mitk::Image::Pointer les_prob = mitk::Image::New();
- mitk::CLUtil::ProbabilityMap(smoothed,59, 11.6,les_prob);
- m_FeatureImageVector.push_back(les_prob);
-
- // Barin (GM/WM)
-
- mitk::Image::Pointer brain_prob = mitk::Image::New();
- mitk::CLUtil::ProbabilityMap(smoothed,32, 5.6,brain_prob);
- m_FeatureImageVector.push_back(brain_prob);
-
- std::vector<unsigned int> FOS_sizes;
- FOS_sizes.push_back(1);
-
- DoubleImageType::Pointer input;
- ShortImageType::Pointer mask;
- mitk::CastToItkImage(smoothed, input);
- mitk::CastToItkImage(brain_mask, mask);
-
- for(unsigned int i = 0 ; i < FOS_sizes.size(); i++)
- {
- FOSFilerType::Pointer filter = FOSFilerType::New();
- filter->SetNeighborhoodSize(FOS_sizes[i]);
- filter->SetInput(input);
- filter->SetMask(mask);
-
- filter->Update();
- FOSFilerType::DataObjectPointerArray array = filter->GetOutputs();
-
- for( unsigned int i = 0; i < FunctorType::OutputCount; i++)
- {
- mitk::Image::Pointer featureimage;
- mitk::CastToMitkImage(dynamic_cast<DoubleImageType *>(array[i].GetPointer()),featureimage);
- m_FeatureImageVector.push_back(featureimage);
- // AddImageAsDataNode(featureimage,FunctorType::GetFeatureName(i))->SetVisibility(show_nodes);
- }
- }
-
- {
- itk::HessianMatrixEigenvalueImageFilter< DoubleImageType >::Pointer filter = itk::HessianMatrixEigenvalueImageFilter< DoubleImageType >::New();
- filter->SetInput(input);
- filter->SetImageMask(mask);
- filter->SetSigma(m_HessianSlider->value());
- filter->Update();
-
- mitk::Image::Pointer o1,o2,o3;
- mitk::CastToMitkImage(filter->GetOutput(0),o1);
- mitk::CastToMitkImage(filter->GetOutput(1),o2);
- mitk::CastToMitkImage(filter->GetOutput(2),o3);
-
- m_FeatureImageVector.push_back(o1);
- m_FeatureImageVector.push_back(o2);
- m_FeatureImageVector.push_back(o3);
-
- // AddImageAsDataNode(o1,"HE_1")->SetVisibility(show_nodes);
- // AddImageAsDataNode(o2,"HE_2")->SetVisibility(show_nodes);
- // AddImageAsDataNode(o3,"HE_3")->SetVisibility(show_nodes);
- }
-
- {
- itk::StructureTensorEigenvalueImageFilter< DoubleImageType >::Pointer filter = itk::StructureTensorEigenvalueImageFilter< DoubleImageType >::New();
- filter->SetInput(input);
- filter->SetImageMask(mask);
- filter->SetInnerScale(m_STInnerSlider->value());
- filter->SetOuterScale(m_STOuterSlider->value());
- filter->Update();
-
- mitk::Image::Pointer o1,o2,o3;
- mitk::CastToMitkImage(filter->GetOutput(0),o1);
- mitk::CastToMitkImage(filter->GetOutput(1),o2);
- mitk::CastToMitkImage(filter->GetOutput(2),o3);
-
- m_FeatureImageVector.push_back(o1);
- m_FeatureImageVector.push_back(o2);
- m_FeatureImageVector.push_back(o3);
-
- // AddImageAsDataNode(o1,"ST_1")->SetVisibility(show_nodes);
- // AddImageAsDataNode(o2,"ST_2")->SetVisibility(show_nodes);
- // AddImageAsDataNode(o3,"ST_3")->SetVisibility(show_nodes);
- }
-
- {
- itk::LineHistogramBasedMassImageFilter< DoubleImageType >::Pointer filter = itk::LineHistogramBasedMassImageFilter< DoubleImageType >::New();
- filter->SetInput(input);
- filter->SetImageMask(mask);
- filter->Update();
-
- mitk::Image::Pointer o1;
- mitk::CastToMitkImage(filter->GetOutput(0),o1);
-
- m_FeatureImageVector.push_back(o1);
- }
-}
-
-void ClassificationSegmentation::OnFeatureSettingsChanged()
-{
- MITK_INFO << "FeatureSettingsChanged";
- m_CalculateFeatures = true;
- ManualSegmentationTrigger();
-}
-
-void ClassificationSegmentation::OnPostProcessingSettingsChanged()
-{
- MITK_INFO << "PostProcessingSettigsChanged";
- PostProcessingTrigger();
-}
-
-void ClassificationSegmentation::DoAutomSegmentation()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_InputImageLayout->itemAt(1)->widget());
- mitk::Image::Pointer raw_image = dynamic_cast<mitk::Image *>(cb_image->GetSelectedNode()->GetData());
- QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_MaskImageLayout->itemAt(1)->widget());
- QmitkDataStorageComboBox * cb_rf = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_ClassifierLayout->itemAt(1)->widget());
-
- mitk::Image::Pointer mask_image = dynamic_cast<mitk::Image *>(cb_maskimage->GetSelectedNode()->GetData());
- mitk::VigraRandomForestClassifier::Pointer classifier = dynamic_cast<mitk::VigraRandomForestClassifier *>(cb_rf->GetSelectedNode()->GetData());
-
- if(m_CalculateFeatures)
- {
- ProcessFeatureImages(raw_image,mask_image);
- m_CalculateFeatures = false;
- }
-
- Eigen::MatrixXd X_test;
-
- unsigned int count_test = 0;
- mitk::CLUtil::CountVoxel(mask_image, count_test);
- X_test = Eigen::MatrixXd(count_test, m_FeatureImageVector.size());
-
- unsigned int index = 0;
- for( const auto & image : m_FeatureImageVector)
- {
- X_test.col(index) = mitk::CLUtil::Transform<double>(image,mask_image);
- ++index;
- }
-
- Eigen::MatrixXi Y_test = classifier->Predict(X_test);
- mitk::Image::Pointer result_mask = mitk::CLUtil::Transform<int>(Y_test,mask_image);
-
- auto node = AddAsDataNode(result_mask.GetPointer(),"Autom-ResultMask");
-
- auto lut = mitk::LookupTable::New();
- lut->SetType(mitk::LookupTable::PET_20);
- auto * lut_prop = dynamic_cast<mitk::LookupTableProperty *>(node->GetProperty("LookupTable"));
- lut_prop->SetLookupTable(lut);
-
- mitk::LevelWindow lw(1,3);
- node->SetLevelWindow(lw);
- node->SetOpacity(0.3);
-
- std::map<unsigned int, unsigned int> perlabelvoxelcount;
- mitk::CLUtil::CountVoxel(result_mask, perlabelvoxelcount);
-
- double voxel_volume = result_mask->GetGeometry()->GetSpacing().GetVnlVector().inf_norm();
- QString newtext;
- newtext += "Name\tVolume\tUnit\n";
- for(const auto & pair: perlabelvoxelcount)
- {
- newtext += "Label" + QString::number(pair.first) + "\t" + QString::number(pair.second*voxel_volume* 0.001) + "\tml\n";
- }
-
- m_Controls.m_ResultTextEdit->setText(newtext);
-}
-
-std::vector<mitk::Image::Pointer> ClassificationSegmentation::ManualSegmentationCallback()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_InputImageLayout->itemAt(1)->widget());
- QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_MaskImageLayout->itemAt(1)->widget());
-
- mitk::Image::Pointer raw_image = dynamic_cast<mitk::Image *>(cb_image->GetSelectedNode()->GetData());
- mitk::Image::Pointer mask_image = dynamic_cast<mitk::Image *>(cb_maskimage->GetSelectedNode()->GetData());
-
- if(raw_image.IsNull() || mask_image.IsNull())
- {
- MITK_WARN << "Please provide input iamge and mask image";
- //return nullptr;
- }
-
- if(m_CalculateFeatures)
- {
- ProcessFeatureImages(raw_image,mask_image);
- m_CalculateFeatures = false;
- }
-
- mitk::Image::Pointer sampled_image = nullptr;
- int label = 1;
- for( auto datanode : m_PointSetList)
- {
- mitk::PointSet::Pointer point_set = dynamic_cast<mitk::PointSet *>(datanode->GetData());
- mitk::Image::Pointer temp_img;
- SampleClassMaskByPointSet(raw_image, point_set,temp_img);
- mitk::CLUtil::InsertLabel(temp_img,sampled_image,label++);
- }
-
- m_TempClassifier = mitk::VigraRandomForestClassifier::New();
- m_TempClassifier->SetTreeCount(50);
- m_TempClassifier->SetSamplesPerTree(0.66);
-
- Eigen::MatrixXd X_train;
- Eigen::MatrixXd X_test;
-
- unsigned int count_train = 0;
- unsigned int count_test = 0;
- mitk::CLUtil::CountVoxel(sampled_image, count_train);
- mitk::CLUtil::CountVoxel(mask_image, count_test);
- X_train = Eigen::MatrixXd(count_train, m_FeatureImageVector.size() );
- X_test = Eigen::MatrixXd(count_test, m_FeatureImageVector.size());
-
- unsigned int index = 0;
- for( const auto & image : m_FeatureImageVector)
- {
- X_train.col(index) = mitk::CLUtil::Transform<double>(image,sampled_image);
- X_test.col(index) = mitk::CLUtil::Transform<double>(image,mask_image);
- ++index;
- }
-
- Eigen::MatrixXi Y = mitk::CLUtil::Transform<int>(sampled_image,sampled_image);
- m_TempClassifier->Train(X_train,Y);
-
- Eigen::MatrixXi Y_test = m_TempClassifier->Predict(X_test);
- Eigen::MatrixXd Yp_test = m_TempClassifier->GetPointWiseProbabilities();
- // mitk::Image::Pointer result_mask = mitk::CLUtil::Transform<int>(Y_test,mask_image);
-
- std::vector<mitk::Image::Pointer> resultvector;
- resultvector.push_back( mitk::CLUtil::Transform<int>(Y_test,mask_image) );
- resultvector.push_back( mitk::CLUtil::Transform<double>(Yp_test.col(0),mask_image) );
- resultvector.push_back( mitk::CLUtil::Transform<double>(Yp_test.col(1),mask_image) );
- resultvector.push_back( mitk::CLUtil::Transform<double>(Yp_test.col(2),mask_image) );
-
- return resultvector;
-}
-
-void ClassificationSegmentation::ManualSegmentationFinished()
-{
- // Receive Future result
- m_ResultImageVector = m_ManualSegmentationFutureWatcher.result();
-
- // Add result to Datastorage
- mitk::DataNode::Pointer node = AddAsDataNode(m_ResultImageVector[0].GetPointer(),"Manual-ResultMask");
- mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
- lut->SetType(mitk::LookupTable::PET_20);
- mitk::LookupTableProperty * lut_prop = dynamic_cast<mitk::LookupTableProperty *>(node->GetProperty("LookupTable"));
- lut_prop->SetLookupTable(lut);
-
- mitk::LevelWindow lw(1,3);
- node->SetLevelWindow(lw);
- node->SetOpacity(0.3);
-
- m_BlockManualSegmentation = false;
- this->PostProcessingTrigger();
-
- // Update Volume data
- std::map<unsigned int, unsigned int> perlabelvoxelcount;
- mitk::CLUtil::CountVoxel(m_ResultImageVector[0], perlabelvoxelcount);
- double voxel_volume = m_ResultImageVector[0]->GetGeometry()->GetSpacing().GetVnlVector().inf_norm();
- QString newtext;
- newtext += "Name\tVolume\tUnit\n";
- for(const auto & pair: perlabelvoxelcount)
- newtext += "Label" + QString::number(pair.first) + "\t" + QString::number(pair.second*voxel_volume* 0.001) + "\tml\n";
- m_Controls.m_ResultTextEdit->setText(newtext);
-
-
-}
-
-void ClassificationSegmentation::ManualSegmentationTrigger()
-{
- unsigned int samplecounter = 0;
- for( auto datanode : m_PointSetList)
- {
- mitk::PointSet::Pointer point_set = dynamic_cast<mitk::PointSet *>(datanode->GetData());
- samplecounter += point_set->GetSize();
- }
- if(samplecounter < 10) return;
-
- if(!m_BlockManualSegmentation){
- // Start GUI Thread
- m_ManualSegmentationFutureWatcher.setFuture(
- QtConcurrent::run(this, &ClassificationSegmentation::ManualSegmentationCallback)); // on finish call OnManualSegmentationFinished();
- m_BlockManualSegmentation = true;
- }
-}
-
-void ClassificationSegmentation::SampleClassMaskByPointSet(const mitk::Image::Pointer & ref_img, mitk::PointSet::Pointer & pointset, mitk::Image::Pointer & outimage)
-{
- outimage = ref_img->Clone();
- itk::Image<unsigned short, 3>::Pointer itk_out;
- mitk::CastToItkImage(outimage,itk_out);
-
- itk_out->FillBuffer(0);
-
- typedef itk::ImageRegionIteratorWithIndex<itk::Image<unsigned short, 3> > IteratorType;
- IteratorType oit(itk_out, itk_out->GetLargestPossibleRegion());
-
- for(int i = 0 ; i < pointset->GetSize(); ++i)
- {
- IteratorType::IndexType index;
- ref_img->GetGeometry()->WorldToIndex(pointset->GetPoint(i), index);
- oit.SetIndex(index);
- oit.Set(1);
- }
-
- mitk::CastToMitkImage(itk_out,outimage);
-}
-
-// old version
-//void ClassificationSegmentation::DoImageProcessing()
-//{
-// QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_InputImageLayout->itemAt(1)->widget());
-// QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_MaskImageLayout->itemAt(1)->widget());
-// QmitkDataStorageComboBox * cb_classifier = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls.m_RandomForestLayout->itemAt(1)->widget());
-
-// if (cb_image == nullptr || cb_classifier == nullptr || cb_maskimage == nullptr)
-// {
-// QMessageBox::information( nullptr, "Template", "Please load and select an image before starting image processing.");
-// return;
-// }
-
-// mitk::VigraRandomForestClassifier::Pointer rf = dynamic_cast<mitk::VigraRandomForestClassifier *>(cb_classifier->GetSelectedNode()->GetData());
-// mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(cb_image->GetSelectedNode()->GetData());
-// mitk::Image::Pointer mask = dynamic_cast<mitk::Image *>(cb_maskimage->GetSelectedNode()->GetData());
-
-// unsigned int n_samples = 0;
-// mitk::CLUtil::CountVoxel(mask, n_samples);
-// unsigned int n_features = 13; // InputImage, PROBA_CSF, PROBA_LES, PROBA_BRA, FOS_MEAN,FOS_VARIANCE,FOS_SKEWNESS, FOS_KURTOSIS, FOS_MIN, FOS_MAX, HE_1, HE_2, HE_3
-
-// Eigen::MatrixXd feature_matrix = Eigen::MatrixXd(n_samples, n_features);
-
-// MITK_INFO << "Remove voxels outside the mask";
-// // mitk::CLUtil::LogicalAndImages(image,brain_mask,image);
-// feature_matrix.block(0,0,n_samples,1) = mitk::CLUtil::Transform<double>(image,mask);
-// AddImageAsDataNode(image, "UI_InputImage");
-
-// mitk::Image::Pointer csf_prob = mitk::Image::New();
-// mitk::CLUtil::ProbabilityMap(image,13.9, 8.3,csf_prob);
-// feature_matrix.block(0,1,n_samples,1) = mitk::CLUtil::Transform<double>(csf_prob,mask);
-// AddImageAsDataNode(csf_prob, "UI_CSFProb");
-
-// mitk::Image::Pointer les_prob = mitk::Image::New();
-// mitk::CLUtil::ProbabilityMap(image,59, 11.6,les_prob);
-// feature_matrix.block(0,2,n_samples,1) = mitk::CLUtil::Transform<double>(les_prob,mask);
-// AddImageAsDataNode(les_prob, "UI_LESProb");
-
-// mitk::Image::Pointer brain_prob = mitk::Image::New();
-// mitk::CLUtil::ProbabilityMap(image,32, 5.6,brain_prob);
-// feature_matrix.block(0,3,n_samples,1) = mitk::CLUtil::Transform<double>(brain_prob,mask);
-// AddImageAsDataNode(brain_prob, "UI_BRAProb");
-
-// int n = 0;
-
-// std::vector<mitk::Image::Pointer> res;
-// DoFirstOrderFeatureCalculation(image, mask, 1, res);
-
-// for( const auto & img: res)
-// {
-// feature_matrix.block(0,3+(++n),n_samples,1) = mitk::CLUtil::Transform<double>(img,mask);
-// std::string name;
-// img->GetPropertyList()->GetStringProperty("name", name);
-// AddImageAsDataNode(img.GetPointer(), name );
-// }
-
-// res.clear();
-// DoHessianEigenvaluesFeatureCalculation(image, mask, 3.0, res);
-// for( const auto & img: res)
-// {
-// feature_matrix.block(0,3+(++n),n_samples,1) = mitk::CLUtil::Transform<double>(img,mask);
-// std::string name;
-// img->GetPropertyList()->GetStringProperty("name", name);
-// AddImageAsDataNode(img.GetPointer(), name );
-// }
-
-// MITK_INFO << "Start Prediction";
-// rf->Predict(feature_matrix);
-// MITK_INFO << "End Prediction";
-
-// mitk::Image::Pointer result_image = mitk::CLUtil::Transform<int>(rf->GetLabels(),mask);
-// mitk::Image::Pointer proba1_image = mitk::CLUtil::Transform<double>(rf->GetPointWiseProbabilities().col(0),mask);
-// mitk::Image::Pointer proba2_image = mitk::CLUtil::Transform<double>(rf->GetPointWiseProbabilities().col(1),mask);
-// mitk::Image::Pointer proba3_image = mitk::CLUtil::Transform<double>(rf->GetPointWiseProbabilities().col(2),mask);
-
-// AddImageAsDataNode(result_image, "ClassificationResult");
-// AddImageAsDataNode(proba1_image, "CSF_Proba_CL");
-// AddImageAsDataNode(proba2_image, "LES_Proba_CL");
-// AddImageAsDataNode(proba3_image, "BRA_Proba_CL");
-
-// PostProcessing(rf,mask);
-
-//}
-
-mitk::DataNode::Pointer ClassificationSegmentation::AddAsDataNode(const mitk::BaseData::Pointer & data_, const std::string & name )
-{
- mitk::DataNode::Pointer node = nullptr;
- node = this->GetDataStorage()->GetNamedNode(name);
-
- if(node.IsNull())
- {
- node = mitk::DataNode::New();
- node->SetData(data_);
- node->SetName(name);
- this->GetDataStorage()->Add(node);
- }else{
-
- if(dynamic_cast<mitk::Image*>(node->GetData()) && dynamic_cast<mitk::Image*>(data_.GetPointer()))
- {
- mitk::Image::Pointer target_image = dynamic_cast<mitk::Image*>(node->GetData());
- mitk::Image::Pointer source_image = dynamic_cast<mitk::Image*>(data_.GetPointer());
- mitk::ImageReadAccessor ra(source_image);
- target_image->SetImportVolume(const_cast<void *>(ra.GetData()));
- this->RequestRenderWindowUpdate();
- }
-
- if(dynamic_cast<mitk::VigraRandomForestClassifier*>(node->GetData()) && dynamic_cast<mitk::VigraRandomForestClassifier*>(data_.GetPointer()))
- {
- node->SetData(data_);
- node->Modified();
- }
-
- }
-
- return node;
-}
-
-void ClassificationSegmentation::PostProcessingTrigger()
-{
- if(m_ResultImageVector.empty() || m_ResultImageVector.size() < 4)
- {
- MITK_ERROR("PostProcessingCallback") << "Result image vector not initialized!";
- return;
- }
-
- if(!m_BlockPostProcessing){
- m_PostProcessingFutureWatcher.setFuture(
- QtConcurrent::run(this, &ClassificationSegmentation::PostProcessingCallback)); // on finish call OnManualSegmentationFinished();
- m_BlockPostProcessing = true;
- }
-}
-
-void ClassificationSegmentation::PostProcessingFinished()
-{
- // Receive Future result
- m_PostProcessingImageVector = m_PostProcessingFutureWatcher.result();
-
- // Add result to Datastorage
- mitk::DataNode::Pointer node = AddAsDataNode(m_PostProcessingImageVector[0].GetPointer(),"Manual-ResultMask-PostProcessing");
- mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
- lut->SetType(mitk::LookupTable::PET_20);
- mitk::LookupTableProperty * lut_prop = dynamic_cast<mitk::LookupTableProperty *>(node->GetProperty("LookupTable"));
- lut_prop->SetLookupTable(lut);
-
- mitk::LevelWindow lw(1,3);
- node->SetLevelWindow(lw);
- node->SetOpacity(0.3);
-
- m_BlockPostProcessing = false;
-}
-
-std::vector<mitk::Image::Pointer> ClassificationSegmentation::PostProcessingCallback()
-{
- std::vector<mitk::Image::Pointer> resultvector;
-
- mitk::Image::Pointer CSF_PMap = m_ResultImageVector[1]->Clone();
- mitk::Image::Pointer LES_PMap = m_ResultImageVector[2]->Clone();
- mitk::Image::Pointer BRA_PMap = m_ResultImageVector[3]->Clone();
- mitk::Image::Pointer mask = m_ResultImageVector[0]->Clone();
-
- MITK_INFO("PostProcessingCallback") << "ProbabilityMap merg strat ...";
-
- {
- mitk::Image::Pointer resultmask = mask->Clone();
- mitk::CLUtil::GaussianFilter(CSF_PMap, CSF_PMap, m_GaussCSFSlider->value());
- mitk::CLUtil::GaussianFilter(LES_PMap, LES_PMap, m_GaussLESSlider->value());
- mitk::CLUtil::GaussianFilter(BRA_PMap, BRA_PMap, m_GaussBRASlider->value());
-
- itk::Image<double, 3>::Pointer itk_csf, itk_les, itk_bra;
- itk::Image<unsigned char, 3>::Pointer itk_result;
-
- mitk::CastToItkImage(CSF_PMap, itk_csf);
- mitk::CastToItkImage(LES_PMap, itk_les);
- mitk::CastToItkImage(BRA_PMap, itk_bra);
- mitk::CastToItkImage(resultmask, itk_result);
-
- itk::ImageRegionIterator<itk::Image<double, 3> > it_csf(itk_csf,itk_csf->GetLargestPossibleRegion());
- itk::ImageRegionIterator<itk::Image<double, 3> > it_les(itk_les,itk_les->GetLargestPossibleRegion());
- itk::ImageRegionIterator<itk::Image<double, 3> > it_bra(itk_bra,itk_bra->GetLargestPossibleRegion());
- itk::ImageRegionIterator<itk::Image<unsigned char, 3> > it_res(itk_result,itk_result->GetLargestPossibleRegion());
-
- while (!it_csf.IsAtEnd()) {
- double csf = it_csf.Value() * m_WeightCSFSlider->value();
- double les = it_les.Value() * m_WeightLESSlider->value();
- double bra = it_bra.Value() * m_WeightBRASlider->value();
-
- if(csf > les && csf > bra) it_res.Set(1);
- if(les > csf && les > bra) it_res.Set(2);
- if(bra > les && bra > csf) it_res.Set(3);
-
- ++it_csf;
- ++it_les;
- ++it_bra;
- ++it_res;
- }
-
- mitk::CastToMitkImage(itk_result, resultmask);
-
- {
- std::map<unsigned int, unsigned int> mergeinstruction ;
- mergeinstruction[1] = 1;
- mergeinstruction[2] = 1;
- mergeinstruction[3] = 1;
- mergeinstruction[4] = 1;
- mergeinstruction[5] = 1;
- mergeinstruction[6] = 1;
-
- // {{1,1},{2,1},{3,1},{4,1},{5,1},{6,1}};
- mitk::Image::Pointer brain_mask = mask->Clone();
- mitk::CLUtil::MergeLabels(brain_mask, mergeinstruction);
- mitk::CLUtil::ClosingBinary(brain_mask,brain_mask,2,mitk::CLUtil::All);
- mitk::CLUtil::LogicalAndImages(resultmask, brain_mask, resultmask);
- }
- MITK_INFO("PostProcessingCallback") << "ProbabilityMap merg end!";
-
- resultvector.push_back(resultmask);
- }
-
- return resultvector;
-
- // {
- // MITK_INFO << "Morphological processing strat ...";
- // mitk::Image::Pointer resultmask = mask->Clone();
-
- // mitk::Image::Pointer csf_mask;
- // mitk::CLUtil::GrabLabel(resultmask, csf_mask, 1);
- // mitk::CLUtil::ClosingBinary(csf_mask,csf_mask,1,mitk::CLUtil::Axial);
-
- // mitk::CLUtil::ErodeBinary(csf_mask, csf_mask, 2, mitk::CLUtil::Axial);
- // mitk::CLUtil::DilateBinary(csf_mask, csf_mask, 1, mitk::CLUtil::Axial);
-
- // std::map<unsigned int, unsigned int> merge_instruction = {{0,0},{1,3},{2,2},{3,3}};
- // mitk::CLUtil::MergeLabels(resultmask, merge_instruction);
-
- // mitk::CLUtil::InsertLabel(resultmask, csf_mask, 1/*as csf mask*/); // add morpological manipulated csf_mask
-
- // // ------------
-
- // mitk::Image::Pointer les_mask;
- // mitk::CLUtil::GrabLabel(resultmask, les_mask, 2);
- // mitk::CLUtil::ClosingBinary(les_mask,les_mask,1,mitk::CLUtil::Axial);
-
- // mitk::Image::Pointer les_cc_mask; unsigned int num = 0;
- // mitk::CLUtil::ConnectedComponentsImage(les_mask, mask, les_cc_mask, num);
- // std::map<unsigned int, unsigned int> map;
- // mitk::CLUtil::CountVoxel(les_cc_mask,map);
- // unsigned int counter = 0;
-
- // while(map.size() > 2)
- // {
- // mitk::CLUtil::ErodeBinary(les_mask, les_mask, 1, mitk::CLUtil::Axial);
- // mitk::CLUtil::LogicalAndImages(les_cc_mask,les_mask,les_cc_mask);
- // map.clear();
- // mitk::CLUtil::CountVoxel(les_cc_mask,map);
- // MITK_INFO("PostProcessing") << map.size();
- // counter++;
- // }
-
- // while(counter != 0)
- // {
- // mitk::CLUtil::DilateBinary(les_mask, les_mask, 1, mitk::CLUtil::Axial);
- // counter--;
- // }
-
- // merge_instruction = {{0,0},{1,1},{2,3},{3,3}};
- // mitk::CLUtil::MergeLabels(resultmask, merge_instruction);
- // mitk::CLUtil::InsertLabel(resultmask, les_mask, 2/*as les mask*/);
-
- // MITK_INFO << "Morphological processing end";
-
- // // ------------
- // mitk::CLUtil::LogicalAndImages(resultmask,mask,resultmask);
-
- // AddImageAsDataNode(resultmask,"SmoothedMaskMorphed");
-
- // }
-}
-
-// mitk::Image::Pointer r= mitk::Image::New(),g= mitk::Image::New(),b = mitk::Image::New();
-
-// unsigned int* m_ImageDimensions;
-// m_ImageDimensions = new unsigned int[3];
-// m_ImageDimensions[0] = raw_image->GetDimensions()[0];
-// m_ImageDimensions[1] = raw_image->GetDimensions()[1];
-// m_ImageDimensions[2] = 1;
-
-// r->Initialize( mitk::MakePixelType<unsigned char,unsigned char,1>() ,3,m_ImageDimensions);
-// g->Initialize( mitk::MakePixelType<unsigned char,unsigned char,1>() ,3,m_ImageDimensions);
-// b->Initialize( mitk::MakePixelType<unsigned char,unsigned char,1>() ,3,m_ImageDimensions);
-
-// mitk::ImageReadAccessor inputAccForRGB(raw_image, raw_image->GetSliceData(0,0,0));
-// unsigned char* rbgSlice = (unsigned char*)inputAccForRGB.GetData();
-
-// mitk::ImageReadAccessor inputAcc(r, r->GetSliceData(0,0,0));
-// unsigned char* rData = (unsigned char*)inputAcc.GetData();
-
-// mitk::ImageReadAccessor inputAcc2(g, g->GetSliceData(0,0,0));
-// unsigned char* gData = (unsigned char*)inputAcc2.GetData();
-
-// mitk::ImageReadAccessor inputAcc3(b, b->GetSliceData(0,0,0));
-// unsigned char*
-// bData = (unsigned char*)inputAcc3.GetData();
-
-// for(int i = 0; i < m_ImageDimensions[0] * m_ImageDimensions[1]*3; i+=3)
-// {
-// rData[i/3] = rbgSlice[i];
-// gData[i/3] = rbgSlice[i+1];
-// bData[i/3] = rbgSlice[i+2];
-
-// }
-
-// m_FeatureImageVector.push_back(r);
-// m_FeatureImageVector.push_back(g);
-// m_FeatureImageVector.push_back(b);
-
-// AddImageAsDataNode(r,"r");
-// AddImageAsDataNode(g,"g");
-// AddImageAsDataNode(b,"b");
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentation.h b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentation.h
deleted file mode 100644
index 5894d95171..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentation.h
+++ /dev/null
@@ -1,134 +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.
-
-============================================================================*/
-
-#ifndef ClassificationSegmentation_h
-#define ClassificationSegmentation_h
-
-#include <berryISelectionListener.h>
-
-#include <QmitkAbstractView.h>
-
-#include "ui_ClassificationSegmentationControls.h"
-#include <mitkImage.h>
-#include <itkConstNeighborhoodIterator.h>
-#include <itkNeighborhoodFunctorImageFilter.h>
-#include <itkFirstOrderStatisticsFeatureFunctor.h>
-
-#include <mitkImageCast.h>
-#include <vigra/tensorutilities.hxx>
-#include <vigra/convolution.hxx>
-#include <vigra/multi_array.hxx>
-#include <mitkPointSet.h>
-#include <itkHistogram.h>
-#include <QFutureWatcher>
-#include <mitkPointSetDataInteractor.h>
-
-#include <mitkVigraRandomForestClassifier.h>
-/**
-\brief ClassificationSegmentation
-
-\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation.
-
-\sa QmitkAbstractView
-\ingroup ${plugin_target}_internal
-*/
-
-class ctkSliderWidget;
-class ClassificationSegmentation : public QmitkAbstractView
-{
- Q_OBJECT
-
-public:
-
- static const std::string VIEW_ID;
-
- std::vector<mitk::DataNode::Pointer> m_PointSetList;
- bool m_CalculateFeatures;
-
- std::vector<mitk::Image::Pointer> m_FeatureImageVector;
- std::vector<mitk::Image::Pointer> m_ResultImageVector;
- std::vector<mitk::Image::Pointer> m_PostProcessingImageVector;
-
- bool m_BlockManualSegmentation;
- QFutureWatcher<std::vector<mitk::Image::Pointer>> m_ManualSegmentationFutureWatcher;
-
- bool m_BlockPostProcessing;
- QFutureWatcher<std::vector<mitk::Image::Pointer>> m_PostProcessingFutureWatcher;
-
- protected slots:
-
- /// \brief Called when the user clicks the GUI button
- void DoAutomSegmentation();
- void DoSavePointsAsMask();
- void OnButtonCSFToggle(bool);
- void OnButtonLESToggle(bool);
- void OnButtonBRAToggle(bool);
- void OnButtonNoInteractionToggle(bool);
- void OnAddForestToDataManager();
-
- void ManualSegmentationTrigger();
- std::vector<mitk::Image::Pointer> ManualSegmentationCallback();
- void ManualSegmentationFinished();
-
- void PostProcessingTrigger();
- std::vector<mitk::Image::Pointer> PostProcessingCallback();
- void PostProcessingFinished();
-
- void OnFeatureSettingsChanged();
- void OnPostProcessingSettingsChanged();
- void OnInitializeSession(const mitk::DataNode*);
-
-protected:
-
- typedef float MeasurementType;
- typedef itk::Statistics::Histogram< MeasurementType,
- itk::Statistics::DenseFrequencyContainer2 > HistogramType;
-
- // void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart);
- // void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart);
-
- void CreateQtPartControl(QWidget *parent) override;
-
- void SetFocus() override;
-
- mitk::DataNode::Pointer AddAsDataNode(const mitk::BaseData::Pointer & data_, const std::string & name );
-
- void SampleClassMaskByPointSet(const mitk::Image::Pointer & ref_img, mitk::PointSet::Pointer & pointset, mitk::Image::Pointer & outimage);
-
- void ProcessFeatureImages(const mitk::Image::Pointer & raw_image, const mitk::Image::Pointer & mask_image);
-
- void OnSelectionChanged( berry::IWorkbenchPart::Pointer source,
- const QList<mitk::DataNode::Pointer>& nodes ) override;
-
- mitk::Image::Pointer CreateClassMaskByPointsetList(std::map<unsigned int, mitk::PointSet *> a_args);
-
- Ui::ClassificationSegmentationControls m_Controls;
-
- // Feature settings
- ctkSliderWidget * m_GaussSlider;
- ctkSliderWidget * m_HessianSlider;
- ctkSliderWidget * m_STInnerSlider;
- ctkSliderWidget * m_STOuterSlider;
-
- ctkSliderWidget * m_GaussCSFSlider;
- ctkSliderWidget * m_GaussLESSlider;
- ctkSliderWidget * m_GaussBRASlider;
-
- ctkSliderWidget * m_WeightCSFSlider;
- ctkSliderWidget * m_WeightLESSlider;
- ctkSliderWidget * m_WeightBRASlider;
-
- mitk::PointSetDataInteractor::Pointer m_PointSetDataInteractor;
- mitk::VigraRandomForestClassifier::Pointer m_TempClassifier;
-};
-
-#endif // ClassificationSegmentation_h
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentationControls.ui b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentationControls.ui
deleted file mode 100644
index e61b432f3a..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/ClassificationSegmentationControls.ui
+++ /dev/null
@@ -1,588 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ClassificationSegmentationControls</class>
- <widget class="QWidget" name="ClassificationSegmentationControls">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>352</width>
- <height>979</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="windowTitle">
- <string>QmitkTemplate</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="label_2">
- <property name="font">
- <font>
- <pointsize>17</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- <underline>false</underline>
- <strikeout>false</strikeout>
- <stylestrategy>PreferAntialias</stylestrategy>
- <kerning>true</kerning>
- </font>
- </property>
- <property name="text">
- <string>Data selection</string>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="m_InputImageLayout">
- <item>
- <widget class="QLabel" name="m_InputImageLabel">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>CT Head Image</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="m_MaskImageLayout">
- <item>
- <widget class="QLabel" name="m_MaskImageLabel">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Mask Image</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="Line" name="line_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_3">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>32</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>17</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- <underline>false</underline>
- <strikeout>false</strikeout>
- <stylestrategy>PreferAntialias</stylestrategy>
- <kerning>true</kerning>
- </font>
- </property>
- <property name="text">
- <string>Automatic segmentation</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="font">
- <font>
- <pointsize>11</pointsize>
- </font>
- </property>
- <property name="title">
- <string>Show user information</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="m_ClassifierLayout">
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="m_ClassifierLabel">
- <property name="font">
- <font>
- <italic>true</italic>
- </font>
- </property>
- <property name="text">
- <string>Classifier</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <property name="bottomMargin">
- <number>32</number>
- </property>
- <item>
- <widget class="QCommandLinkButton" name="m_DoAutomaticSecmentation">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>64</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>14</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Start classification</string>
- </property>
- <property name="icon">
- <iconset resource="../../resources/ClassificationSegmentation.qrc">
- <normaloff>:/ClassificationSegmentation/button_process.png</normaloff>:/ClassificationSegmentation/button_process.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>32</width>
- <height>32</height>
- </size>
- </property>
- <property name="shortcut">
- <string>Ctrl+A</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="Line" name="line_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>32</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>17</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- <underline>false</underline>
- <strikeout>false</strikeout>
- <stylestrategy>PreferAntialias</stylestrategy>
- <kerning>true</kerning>
- </font>
- </property>
- <property name="text">
- <string>Manual segmentation</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox">
- <property name="font">
- <font>
- <pointsize>11</pointsize>
- </font>
- </property>
- <property name="title">
- <string>Show user information</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="m_PointSetLayout">
- <property name="bottomMargin">
- <number>32</number>
- </property>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QToolButton" name="m_ButtonCSFToggle">
- <property name="minimumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="styleSheet">
- <string notr="true">background-color: #8AFF88</string>
- </property>
- <property name="text">
- <string>CSF</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="autoExclusive">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="m_ButtonLESToggle">
- <property name="minimumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="styleSheet">
- <string notr="true">background-color: #FF7E78</string>
- </property>
- <property name="text">
- <string>Lesion</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="autoExclusive">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="m_ButtonBRAToggle">
- <property name="minimumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="styleSheet">
- <string notr="true">background-color: #4F9EE5</string>
- </property>
- <property name="text">
- <string>Brain</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="autoExclusive">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QToolButton" name="m_ButtonNoInteraction">
- <property name="minimumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Clear all</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="autoExclusive">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_5">
- <property name="bottomMargin">
- <number>32</number>
- </property>
- <item>
- <widget class="QCommandLinkButton" name="m_DoAutomaticSecmentation_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>64</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>14</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Update result</string>
- </property>
- <property name="icon">
- <iconset resource="../../resources/ClassificationSegmentation.qrc">
- <normaloff>:/ClassificationSegmentation/button_process_2.png</normaloff>:/ClassificationSegmentation/button_process_2.png</iconset>
- </property>
- <property name="iconSize">
- <size>
- <width>32</width>
- <height>32</height>
- </size>
- </property>
- <property name="shortcut">
- <string>Ctrl+M</string>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QPushButton" name="m_AddForestToDataManager">
- <property name="text">
- <string>Add classifier to Data Manager</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
- <property name="sizeConstraint">
- <enum>QLayout::SetMinAndMaxSize</enum>
- </property>
- <property name="leftMargin">
- <number>10</number>
- </property>
- <property name="topMargin">
- <number>10</number>
- </property>
- <item>
- <widget class="QPushButton" name="pushButton">
- <property name="text">
- <string>Load pointsets</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="m_SavePointsButton">
- <property name="text">
- <string>Save pointsets</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="Line" name="m_SeperaterIO">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QTextEdit" name="m_ResultTextEdit">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>100</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>250</height>
- </size>
- </property>
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
- <property name="html">
- <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Volumetric data...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QGroupBox" name="m_PostProcessingLayout">
- <property name="title">
- <string>Postprocessing settings</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_4"/>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="m_ParameterLayout">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="title">
- <string>Feature settings</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2"/>
- </widget>
- </item>
- </layout>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <resources>
- <include location="../../resources/ClassificationSegmentation.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationregiongrow_Activator.cpp b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationregiongrow_Activator.cpp
deleted file mode 100644
index d039ab6d19..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationregiongrow_Activator.cpp
+++ /dev/null
@@ -1,29 +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 "org_mitk_gui_qt_classificationregiongrow_Activator.h"
-#include "ClassificationRegionGrow.h"
-
-namespace mitk {
-
-void org_mitk_gui_qt_classificationregiongrow_Activator::start(ctkPluginContext* context)
-{
- BERRY_REGISTER_EXTENSION_CLASS(ClassificationRegionGrow, context)
-}
-
-void org_mitk_gui_qt_classificationregiongrow_Activator::stop(ctkPluginContext* context)
-{
- Q_UNUSED(context)
-}
-
-}
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationregiongrow_Activator.h b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationregiongrow_Activator.h
deleted file mode 100644
index 1edb59a1b8..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationregiongrow_Activator.h
+++ /dev/null
@@ -1,37 +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.
-
-============================================================================*/
-
-
-#ifndef org_mitk_gui_qt_classificationregiongrow_Activator_h
-#define org_mitk_gui_qt_classificationregiongrow_Activator_h
-
-#include <ctkPluginActivator.h>
-
-namespace mitk {
-
-class org_mitk_gui_qt_classificationregiongrow_Activator :
- public QObject, public ctkPluginActivator
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_classificationregiongrow")
- Q_INTERFACES(ctkPluginActivator)
-
-public:
-
- void start(ctkPluginContext* context);
- void stop(ctkPluginContext* context);
-
-}; // org_mitk_gui_qt_classificationregiongrow_Activator
-
-}
-
-#endif // org_mitk_gui_qt_classificationregiongrow_Activator_h
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationsegmentation_Activator.cpp b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationsegmentation_Activator.cpp
deleted file mode 100644
index f32c3f3074..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationsegmentation_Activator.cpp
+++ /dev/null
@@ -1,31 +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 "org_mitk_gui_qt_classificationsegmentation_Activator.h"
-#include "ClassificationSegmentation.h"
-#include "ClassificationRegionGrow.h"
-
-namespace mitk {
-
-void org_mitk_gui_qt_classificationsegmentation_Activator::start(ctkPluginContext* context)
-{
- BERRY_REGISTER_EXTENSION_CLASS(ClassificationSegmentation, context)
- BERRY_REGISTER_EXTENSION_CLASS(ClassificationRegionGrow, context)
-}
-
-void org_mitk_gui_qt_classificationsegmentation_Activator::stop(ctkPluginContext* context)
-{
- Q_UNUSED(context)
-}
-
-}
diff --git a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationsegmentation_Activator.h b/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationsegmentation_Activator.h
deleted file mode 100644
index 31cb539b20..0000000000
--- a/Plugins/org.mitk.gui.qt.classificationsegmentation/src/internal/org_mitk_gui_qt_classificationsegmentation_Activator.h
+++ /dev/null
@@ -1,38 +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.
-
-============================================================================*/
-
-
-#ifndef org_mitk_gui_qt_classificationsegmentation_Activator_h
-#define org_mitk_gui_qt_classificationsegmentation_Activator_h
-
-#include <ctkPluginActivator.h>
-
-namespace mitk {
-
-class org_mitk_gui_qt_classificationsegmentation_Activator :
- public QObject, public ctkPluginActivator
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_classificationsegmentation")
-// Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_classificationregiongrow")
- Q_INTERFACES(ctkPluginActivator)
-
-public:
-
- void start(ctkPluginContext* context) override;
- void stop(ctkPluginContext* context) override;
-
-}; // org_mitk_gui_qt_classificationsegmentation_Activator
-
-}
-
-#endif // org_mitk_gui_qt_classificationsegmentation_Activator_h
diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.cpp
index dd6b34f1af..6c8c22100b 100644
--- a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.cpp
+++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.cpp
@@ -1,145 +1,147 @@
/*============================================================================
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 "QmitkAbstractRenderEditor.h"
#include "internal/QmitkCommonActivator.h"
#include <mitkDataStorageEditorInput.h>
#include <mitkIRenderingManager.h>
#include <mitkCoreServices.h>
#include <mitkIPreferencesService.h>
#include <mitkIPreferences.h>
+#include <mitkTimeNavigationController.h>
+
#include <berryUIException.h>
class QmitkAbstractRenderEditorPrivate
{
public:
QmitkAbstractRenderEditorPrivate()
: m_RenderingManagerInterface(mitk::MakeRenderingManagerInterface(mitk::RenderingManager::GetInstance()))
{
}
~QmitkAbstractRenderEditorPrivate()
{
delete m_RenderingManagerInterface;
}
mitk::IRenderingManager* m_RenderingManagerInterface;
mitk::IPreferences* m_Prefs;
};
QmitkAbstractRenderEditor::QmitkAbstractRenderEditor()
: d(new QmitkAbstractRenderEditorPrivate)
{
}
QmitkAbstractRenderEditor::~QmitkAbstractRenderEditor()
{
if (d->m_Prefs != nullptr)
{
d->m_Prefs->OnChanged.RemoveListener(mitk::MessageDelegate1<QmitkAbstractRenderEditor, const mitk::IPreferences*>
(this, &QmitkAbstractRenderEditor::OnPreferencesChanged ) );
}
}
void QmitkAbstractRenderEditor::Init(berry::IEditorSite::Pointer site, berry::IEditorInput::Pointer input)
{
if (input.Cast<mitk::DataStorageEditorInput>().IsNull())
throw berry::PartInitException("Invalid Input: Must be mitk::DataStorageEditorInput");
this->SetSite(site);
this->SetInput(input);
d->m_Prefs = this->GetPreferences();
if (d->m_Prefs != nullptr)
{
d->m_Prefs->OnChanged.AddListener(mitk::MessageDelegate1<QmitkAbstractRenderEditor, const mitk::IPreferences*>
(this, &QmitkAbstractRenderEditor::OnPreferencesChanged ) );
}
}
mitk::IDataStorageReference::Pointer QmitkAbstractRenderEditor::GetDataStorageReference() const
{
mitk::DataStorageEditorInput::Pointer input = this->GetEditorInput().Cast<mitk::DataStorageEditorInput>();
if (input.IsNotNull())
{
return input->GetDataStorageReference();
}
return mitk::IDataStorageReference::Pointer(nullptr);
}
mitk::DataStorage::Pointer QmitkAbstractRenderEditor::GetDataStorage() const
{
mitk::IDataStorageReference::Pointer ref = this->GetDataStorageReference();
if (ref.IsNotNull()) return ref->GetDataStorage();
return mitk::DataStorage::Pointer(nullptr);
}
mitk::IPreferences* QmitkAbstractRenderEditor::GetPreferences() const
{
mitk::CoreServicePointer prefService(mitk::CoreServices::GetPreferencesService());
return prefService->GetSystemPreferences()->Node(this->GetSite()->GetId().toStdString());
}
mitk::IRenderingManager* QmitkAbstractRenderEditor::GetRenderingManager() const
{
// we use the global rendering manager here. This should maybe replaced
// by a local one, managing only the render windows specific for the editor
return d->m_RenderingManagerInterface;
}
void QmitkAbstractRenderEditor::RequestUpdate(mitk::RenderingManager::RequestType requestType)
{
if (GetRenderingManager())
GetRenderingManager()->RequestUpdateAll(requestType);
}
void QmitkAbstractRenderEditor::ForceImmediateUpdate(mitk::RenderingManager::RequestType requestType)
{
if (GetRenderingManager())
GetRenderingManager()->ForceImmediateUpdateAll(requestType);
}
-mitk::SliceNavigationController* QmitkAbstractRenderEditor::GetTimeNavigationController() const
+mitk::TimeNavigationController* QmitkAbstractRenderEditor::GetTimeNavigationController() const
{
if (GetRenderingManager())
return GetRenderingManager()->GetTimeNavigationController();
return nullptr;
}
void QmitkAbstractRenderEditor::OnPreferencesChanged(const mitk::IPreferences *)
{}
void QmitkAbstractRenderEditor::DoSave()
{}
void QmitkAbstractRenderEditor::DoSaveAs()
{}
bool QmitkAbstractRenderEditor::IsDirty() const
{ return false; }
bool QmitkAbstractRenderEditor::IsSaveAsAllowed() const
{ return false; }
mitk::TimePointType QmitkAbstractRenderEditor::GetSelectedTimePoint(const QString& /*id*/) const
{
auto timeNavigator = this->GetTimeNavigationController();
if (nullptr != timeNavigator)
{
return timeNavigator->GetSelectedTimePoint();
}
return 0;
}
diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.h b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.h
index c0f666c001..d1eb9bf302 100644
--- a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.h
+++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractRenderEditor.h
@@ -1,166 +1,166 @@
/*============================================================================
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 QmitkAbstractRenderEditor_h
#define QmitkAbstractRenderEditor_h
#include <berryQtEditorPart.h>
#include "mitkIRenderWindowPart.h"
#include <mitkIDataStorageReference.h>
#include <mitkDataStorage.h>
#include <org_mitk_gui_qt_common_Export.h>
class QmitkAbstractRenderEditorPrivate;
namespace mitk
{
class IPreferences;
}
/**
* \ingroup org_mitk_gui_qt_common
*
* \brief A convenient base class for MITK render window BlueBerry Editors.
*
* QmitkAbstractRenderEditor provides several convenience methods that ease the introduction of
* a new editor for rendering a MITK DataStorage:
*
* <ol>
* <li> Access to the DataStorage (~ the shared data repository)
* <li> Access to and update notification for the editor's preferences
* <li> Default implementation of some mitk::IRenderWindowPart methods
* </ol>
*
* When inheriting from QmitkAbstractRenderEditor, you must implement the following methods:
* <ul>
* <li>void CreateQtPartControl(QWidget* parent)
* <li>void SetFocus()
* </ul>
*
* You may reimplement the following private virtual methods to be notified about certain changes:
* <ul>
* <li>void OnPreferencesChanged(const mitk::IPreferences*)
* </ul>
*
* \see IRenderWindowPart
* \see ILinkedRenderWindowPart
*/
class MITK_QT_COMMON QmitkAbstractRenderEditor : public berry::QtEditorPart,
public virtual mitk::IRenderWindowPart
{
Q_OBJECT
Q_INTERFACES(mitk::IRenderWindowPart)
public:
berryObjectMacro(QmitkAbstractRenderEditor, QtEditorPart, mitk::IRenderWindowPart);
/**
* \see mitk::IRenderWindowPart::GetSelectedTimePoint()
This default implementation assumes that all renderer use the same TimeNavigationControl
provided by this class (GetTimeNavigationControl()).
*/
mitk::TimePointType GetSelectedTimePoint(const QString& id = QString()) const override;
QmitkAbstractRenderEditor();
~QmitkAbstractRenderEditor() override;
protected:
/**
* Initializes this editor by checking for a valid mitk::DataStorageEditorInput as <code>input</code>.
*
* \see berry::IEditorPart::Init
*/
void Init(berry::IEditorSite::Pointer site, berry::IEditorInput::Pointer input) override;
/**
* Get a reference to the DataStorage set by the editor input.
*/
virtual mitk::IDataStorageReference::Pointer GetDataStorageReference() const;
/**
* Get the DataStorage set by the editor input.
*/
virtual mitk::DataStorage::Pointer GetDataStorage() const;
/**
* Get the preferences for this editor.
*/
virtual mitk::IPreferences* GetPreferences() const;
/**
* Get the RenderingManager used by this editor. This default implementation uses the
* global MITK RenderingManager provided by mitk::RenderingManager::GetInstance().
*
* \see mitk::IRenderWindowPart::GetRenderingManager
*/
mitk::IRenderingManager* GetRenderingManager() const override;
/**
* Request an update of this editor's render windows.
* This implementation calls mitk::IRenderingManager::RequestUpdate on the rendering
* manager interface returned by GetRenderingManager();
*
* \param requestType The type of render windows for which an update is requested.
*
* \see mitk::IRenderWindowPart::RequestUpdate
*/
void RequestUpdate(mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL) override;
/**
* Force an immediate update of this editor's render windows.
* This implementation calls mitk::IRenderingManager::ForceImmediateUpdate() on the rendering
* manager interface returned by GetRenderingManager();
*
* \param requestType The type of render windows for which an immedate update is forced.
*
* \see mitk::IRenderWindowPart::ForceImmediateUpdate
*/
void ForceImmediateUpdate(mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL) override;
/**
* Get the time navigation controller for this editor.
- * This implementation returns the SliceNavigationController returned by the mitk::IRenderingManager::GetTimeNavigationController()
+ * This implementation returns the TimeNavigationController returned by the mitk::IRenderingManager::GetTimeNavigationController()
* method of the interface implementation returned by GetRenderingManager().
*
* \see mitk::IRenderingManager::GetTimeNavigationController
*/
- mitk::SliceNavigationController* GetTimeNavigationController() const override;
+ mitk::TimeNavigationController* GetTimeNavigationController() const override;
/** \see berry::IEditorPart::DoSave */
void DoSave() override;
/** \see berry::IEditorPart::DoSaveAs */
void DoSaveAs() override;
/** \see berry::IEditorPart::IsDirty */
bool IsDirty() const override;
/** \see berry::IEditorPart::IsSaveAsAllowed */
bool IsSaveAsAllowed() const override;
private:
virtual void OnPreferencesChanged(const mitk::IPreferences*);
private:
QScopedPointer<QmitkAbstractRenderEditorPrivate> d;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp
index caefe8515f..95103106a7 100644
--- a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp
+++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp
@@ -1,521 +1,522 @@
/*============================================================================
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 "QmitkAbstractView.h"
#include "QmitkDataNodeSelectionProvider.h"
#include "internal/QmitkCommonActivator.h"
#include "internal/QmitkDataNodeItemModel.h"
// mitk Includes
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkCoreServices.h>
#include <mitkIPreferences.h>
#include <mitkIPreferencesService.h>
#include <mitkIDataStorageService.h>
#include <mitkDataStorageEditorInput.h>
#include <mitkDataNodeObject.h>
#include <mitkIRenderingManager.h>
+#include <mitkTimeNavigationController.h>
// berry Includes
#include <berryIWorkbenchPage.h>
#include <berryIEditorPart.h>
#include <berryINullSelectionListener.h>
#include <berryUIException.h>
// CTK Includes
#include <ctkServiceTracker.h>
// Qt Includes
#include <QItemSelectionModel>
#include <QApplication>
#include <QMessageBox>
#include <QScrollArea>
#include <QVBoxLayout>
class QmitkAbstractViewPrivate
{
public:
QmitkAbstractViewPrivate(QmitkAbstractView* qq)
: q(qq)
, m_DataStorageServiceTracker(QmitkCommonActivator::GetContext())
, m_Parent(nullptr)
, m_DataNodeItemModel(new QmitkDataNodeItemModel)
, m_DataNodeSelectionModel(new QItemSelectionModel(m_DataNodeItemModel))
, m_InDataStorageChanged(false)
{
m_DataStorageServiceTracker.open();
}
~QmitkAbstractViewPrivate()
{
delete m_DataNodeSelectionModel;
delete m_DataNodeItemModel;
m_DataStorageServiceTracker.close();
}
/**
* Called when a DataStorage Add Event was thrown. Sets
* m_InDataStorageChanged to true and calls NodeAdded afterwards.
* \see m_InDataStorageChanged
*/
void NodeAddedProxy(const mitk::DataNode* node)
{
// garantuee no recursions when a new node event is thrown in NodeAdded()
if(!m_InDataStorageChanged)
{
m_InDataStorageChanged = true;
q->NodeAdded(node);
q->DataStorageModified();
m_InDataStorageChanged = false;
}
}
/**
* Called when a DataStorage remove event was thrown. Sets
* m_InDataStorageChanged to true and calls NodeRemoved afterwards.
* \see m_InDataStorageChanged
*/
void NodeRemovedProxy(const mitk::DataNode* node)
{
// garantuee no recursions when a new node event is thrown in NodeAdded()
if(!m_InDataStorageChanged)
{
m_InDataStorageChanged = true;
q->NodeRemoved(node);
q->DataStorageModified();
m_InDataStorageChanged = false;
}
}
/**
* Called when a DataStorage changed event was thrown. Sets
* m_InDataStorageChanged to true and calls NodeChanged afterwards.
* \see m_InDataStorageChanged
*/
void NodeChangedProxy(const mitk::DataNode* node)
{
// garantuee no recursions when a new node event is thrown in NodeAdded()
if(!m_InDataStorageChanged)
{
m_InDataStorageChanged = true;
q->NodeChanged(node);
q->DataStorageModified();
m_InDataStorageChanged = false;
}
}
/**
* reactions to selection events from views
*/
void BlueBerrySelectionChanged(const berry::IWorkbenchPart::Pointer& sourcepart,
const berry::ISelection::ConstPointer& selection)
{
if(sourcepart.IsNull() || sourcepart.GetPointer() == static_cast<berry::IWorkbenchPart*>(q))
return;
if(selection.IsNull())
{
q->OnNullSelection(sourcepart);
return;
}
mitk::DataNodeSelection::ConstPointer _DataNodeSelection
= selection.Cast<const mitk::DataNodeSelection>();
q->OnSelectionChanged(sourcepart, this->DataNodeSelectionToQList(_DataNodeSelection));
}
/**
* Converts a mitk::DataNodeSelection to a QList<mitk::DataNode::Pointer> (possibly empty)
*/
QList<mitk::DataNode::Pointer> DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const;
QmitkAbstractView* const q;
ctkServiceTracker<mitk::IDataStorageService*> m_DataStorageServiceTracker;
/**
* Saves the parent of this view (this is the scrollarea created in CreatePartControl(QWidget*)
* \see CreatePartControl(QWidget*)
*/
QWidget* m_Parent;
/**
* Holds the current selection (selection made by this View !!!)
*/
QmitkDataNodeSelectionProvider::Pointer m_SelectionProvider;
/**
* Holds a helper model for firing selection events.
*/
QmitkDataNodeItemModel* m_DataNodeItemModel;
/**
* The selection model for the QmitkDataNodeItemModel;
*/
QItemSelectionModel* m_DataNodeSelectionModel;
/**
* object to observe BlueBerry selections
*/
QScopedPointer<berry::ISelectionListener> m_BlueBerrySelectionListener;
/**
* Saves if this class is currently working on DataStorage changes.
* This is a protector variable to avoid recursive calls on event listener functions.
*/
bool m_InDataStorageChanged;
};
QmitkAbstractView::QmitkAbstractView()
: d(new QmitkAbstractViewPrivate(this))
{
}
void QmitkAbstractView::CreatePartControl(QWidget* parent)
{
// scrollArea
auto scrollArea = new QScrollArea;
//QVBoxLayout* scrollAreaLayout = new QVBoxLayout(scrollArea);
scrollArea->setFrameShadow(QFrame::Plain);
scrollArea->setFrameShape(QFrame::NoFrame);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
// m_Parent
d->m_Parent = new QWidget;
//m_Parent->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
this->CreateQtPartControl(d->m_Parent);
//scrollAreaLayout->addWidget(m_Parent);
//scrollArea->setLayout(scrollAreaLayout);
// set the widget now
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(d->m_Parent);
// add the scroll area to the real parent (the view tabbar)
QWidget* parentQWidget = static_cast<QWidget*>(parent);
auto parentLayout = new QVBoxLayout(parentQWidget);
parentLayout->setMargin(0);
parentLayout->setSpacing(0);
parentLayout->addWidget(scrollArea);
// finally set the layout containing the scroll area to the parent widget (= show it)
parentQWidget->setLayout(parentLayout);
this->AfterCreateQtPartControl();
}
void QmitkAbstractView::AfterCreateQtPartControl()
{
this->SetSelectionProvider();
// REGISTER DATASTORAGE LISTENER
this->GetDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1<QmitkAbstractViewPrivate, const mitk::DataNode*>
( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) );
this->GetDataStorage()->ChangedNodeEvent.AddListener( mitk::MessageDelegate1<QmitkAbstractViewPrivate, const mitk::DataNode*>
( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) );
this->GetDataStorage()->RemoveNodeEvent.AddListener( mitk::MessageDelegate1<QmitkAbstractViewPrivate, const mitk::DataNode*>
( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy ) );
// REGISTER PREFERENCES LISTENER
auto* prefs = this->GetPreferences();
if (prefs != nullptr)
prefs->OnChanged.AddListener(mitk::MessageDelegate1<QmitkAbstractView, const mitk::IPreferences*>(this, &QmitkAbstractView::OnPreferencesChanged));
// REGISTER FOR WORKBENCH SELECTION EVENTS
d->m_BlueBerrySelectionListener.reset(new berry::NullSelectionChangedAdapter<QmitkAbstractViewPrivate>(
d.data(), &QmitkAbstractViewPrivate::BlueBerrySelectionChanged));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(d->m_BlueBerrySelectionListener.data());
// EMULATE INITIAL SELECTION EVENTS
// send the current selection
berry::IWorkbenchPart::Pointer activePart = this->GetSite()->GetPage()->GetActivePart();
if (activePart.IsNotNull())
{
this->OnSelectionChanged(activePart, this->GetCurrentSelection());
}
// send preferences changed event
this->OnPreferencesChanged(this->GetPreferences());
}
QmitkAbstractView::~QmitkAbstractView()
{
this->Register();
this->GetDataStorage()->AddNodeEvent.RemoveListener( mitk::MessageDelegate1<QmitkAbstractViewPrivate, const mitk::DataNode*>
( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) );
this->GetDataStorage()->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1<QmitkAbstractViewPrivate, const mitk::DataNode*>
( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy) );
this->GetDataStorage()->ChangedNodeEvent.RemoveListener( mitk::MessageDelegate1<QmitkAbstractViewPrivate, const mitk::DataNode*>
( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) );
auto* prefs = this->GetPreferences();
if(prefs != nullptr)
prefs->OnChanged.RemoveListener(mitk::MessageDelegate1<QmitkAbstractView, const mitk::IPreferences*>(this, &QmitkAbstractView::OnPreferencesChanged));
// REMOVE SELECTION PROVIDER
this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(nullptr));
berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
if(s)
{
s->RemovePostSelectionListener(d->m_BlueBerrySelectionListener.data());
}
this->UnRegister(false);
}
void QmitkAbstractView::SetSelectionProvider()
{
// REGISTER A SELECTION PROVIDER
d->m_SelectionProvider = QmitkDataNodeSelectionProvider::Pointer(new QmitkDataNodeSelectionProvider);
d->m_SelectionProvider->SetItemSelectionModel(GetDataNodeSelectionModel());
this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(d->m_SelectionProvider));
}
QItemSelectionModel *QmitkAbstractView::GetDataNodeSelectionModel() const
{
return nullptr;
}
void QmitkAbstractView::OnPreferencesChanged( const mitk::IPreferences* )
{
}
void QmitkAbstractView::DataStorageModified()
{
}
void QmitkAbstractView::DataStorageChanged(mitk::IDataStorageReference::Pointer /*dsRef*/)
{
}
mitk::IRenderWindowPart* QmitkAbstractView::GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategies strategies) const
{
berry::IWorkbenchPage::Pointer page = GetSite()->GetPage();
return mitk::WorkbenchUtil::GetRenderWindowPart(page, strategies);
}
void QmitkAbstractView::RequestRenderWindowUpdate(mitk::RenderingManager::RequestType requestType)
{
mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart();
if (renderPart == nullptr)
return;
if (mitk::IRenderingManager* renderingManager = renderPart->GetRenderingManager())
{
renderingManager->RequestUpdateAll(requestType);
}
else
{
renderPart->RequestUpdate(requestType);
}
}
void QmitkAbstractView::HandleException( const char* str, QWidget* parent, bool showDialog ) const
{
//itkGenericOutputMacro( << "Exception caught: " << str );
MITK_ERROR << str;
if ( showDialog )
{
QMessageBox::critical ( parent, "Exception caught!", str );
}
}
void QmitkAbstractView::HandleException( std::exception& e, QWidget* parent, bool showDialog ) const
{
HandleException( e.what(), parent, showDialog );
}
void QmitkAbstractView::WaitCursorOn()
{
QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
}
void QmitkAbstractView::BusyCursorOn()
{
QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) );
}
void QmitkAbstractView::WaitCursorOff()
{
this->RestoreOverrideCursor();
}
void QmitkAbstractView::BusyCursorOff()
{
this->RestoreOverrideCursor();
}
void QmitkAbstractView::RestoreOverrideCursor()
{
QApplication::restoreOverrideCursor();
}
mitk::IPreferences* QmitkAbstractView::GetPreferences() const
{
mitk::CoreServicePointer prefsService(mitk::CoreServices::GetPreferencesService());
auto* prefs = prefsService->GetSystemPreferences();
if (prefs != nullptr)
{
auto viewSite = const_cast<QmitkAbstractView*>(this)->GetViewSite();
if (viewSite.IsNotNull())
return prefs->Node("/" + viewSite->GetId().toStdString());
}
return nullptr;
}
mitk::DataStorage::Pointer QmitkAbstractView::GetDataStorage() const
{
mitk::IDataStorageService* dsService = d->m_DataStorageServiceTracker.getService();
if (dsService != nullptr)
{
return dsService->GetDataStorage()->GetDataStorage();
}
return nullptr;
}
mitk::IDataStorageReference::Pointer QmitkAbstractView::GetDataStorageReference() const
{
mitk::IDataStorageService* dsService = d->m_DataStorageServiceTracker.getService();
if (dsService != nullptr)
{
return dsService->GetDataStorage();
}
return mitk::IDataStorageReference::Pointer(nullptr);
}
QList<mitk::DataNode::Pointer> QmitkAbstractView::GetCurrentSelection() const
{
berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection());
mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast<const mitk::DataNodeSelection>();
return d->DataNodeSelectionToQList(currentSelection);
}
bool QmitkAbstractView::IsCurrentSelectionValid() const
{
return this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection();
}
QList<mitk::DataNode::Pointer> QmitkAbstractView::GetDataManagerSelection() const
{
berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast<const mitk::DataNodeSelection>();
return d->DataNodeSelectionToQList(currentSelection);
}
bool QmitkAbstractView::IsDataManagerSelectionValid() const
{
return this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager");
}
void QmitkAbstractView::SetDataManagerSelection(const berry::ISelection::ConstPointer &selection,
QItemSelectionModel::SelectionFlags flags) const
{
berry::IViewPart::Pointer datamanagerView = this->GetSite()->GetWorkbenchWindow()->GetActivePage()->FindView("org.mitk.views.datamanager");
if (datamanagerView.IsNull()) return;
datamanagerView->GetSite()->GetSelectionProvider().Cast<berry::QtSelectionProvider>()->SetSelection(selection, flags);
}
void QmitkAbstractView::SynchronizeDataManagerSelection() const
{
berry::ISelection::ConstPointer currentSelection = this->GetSite()->GetSelectionProvider()->GetSelection();
if (currentSelection.IsNull()) return;
SetDataManagerSelection(currentSelection);
}
void QmitkAbstractView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/,
const QList<mitk::DataNode::Pointer>& /*nodes*/)
{
}
void QmitkAbstractView::OnNullSelection(berry::IWorkbenchPart::Pointer /*part*/)
{
}
QList<mitk::DataNode::Pointer> QmitkAbstractViewPrivate::DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const
{
if (currentSelection.IsNull()) return QList<mitk::DataNode::Pointer>();
return QList<mitk::DataNode::Pointer>::fromStdList(currentSelection->GetSelectedDataNodes());
}
void QmitkAbstractView::NodeAdded( const mitk::DataNode* /*node*/ )
{
}
void QmitkAbstractView::NodeRemoved( const mitk::DataNode* /*node*/ )
{
}
void QmitkAbstractView::NodeChanged( const mitk::DataNode* /*node*/ )
{
}
void QmitkAbstractView::FireNodeSelected( mitk::DataNode::Pointer node )
{
QList<mitk::DataNode::Pointer> nodes;
nodes << node;
this->FireNodesSelected(nodes);
}
void QmitkAbstractView::FireNodesSelected( const QList<mitk::DataNode::Pointer>& nodes )
{
// if this is the first call to FireNodesSelected and the selection provider has no QItemSelectiomMode
// yet, set our helper model
if (d->m_SelectionProvider->GetItemSelectionModel() == nullptr)
{
d->m_SelectionProvider->SetItemSelectionModel(d->m_DataNodeSelectionModel);
}
else if (d->m_SelectionProvider->GetItemSelectionModel() != d->m_DataNodeSelectionModel)
{
MITK_WARN << "A custom data node selection model has been set. Ignoring call to FireNodesSelected().";
return;
}
if (nodes.empty())
{
d->m_DataNodeSelectionModel->clearSelection();
d->m_DataNodeItemModel->clear();
}
else
{
// The helper data node model is just used for sending selection events.
// We add the to be selected nodes and set the selection range to everything.
d->m_DataNodeItemModel->clear();
foreach(mitk::DataNode::Pointer node, nodes)
{
d->m_DataNodeItemModel->AddDataNode(node);
}
d->m_DataNodeSelectionModel->select(QItemSelection(d->m_DataNodeItemModel->index(0,0), d->m_DataNodeItemModel->index(nodes.size()-1, 0)),
QItemSelectionModel::ClearAndSelect);
}
}
diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.cpp
index d075ccca6b..01b558111e 100644
--- a/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.cpp
+++ b/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.cpp
@@ -1,235 +1,250 @@
/*============================================================================
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.
============================================================================*/
// Qmitk
-#include "QmitkRenderWindow.h"
-#include "QmitkSliceNavigationListener.h"
+#include <QmitkRenderWindow.h>
+#include <QmitkSliceNavigationListener.h>
-#include "mitkIRenderWindowPart.h"
+#include <mitkIRenderWindowPart.h>
+#include <mitkTimeNavigationController.h>
// Qt
#include <QTimer>
#include <QMessageBox>
///**********************************************
QmitkSliceNavigationListener::QmitkSliceNavigationListener() : m_renderWindowPart(nullptr),
m_PendingSliceChangedEvent(false),
m_CurrentSelectedPosition(std::numeric_limits<mitk::Point3D::ValueType>::lowest()),
m_CurrentSelectedTimePoint(std::numeric_limits<mitk::TimePointType>::lowest())
{
}
QmitkSliceNavigationListener::~QmitkSliceNavigationListener()
{
this->RemoveAllObservers();
}
mitk::TimePointType QmitkSliceNavigationListener::GetCurrentSelectedTimePoint() const
{
return m_CurrentSelectedTimePoint;
}
mitk::Point3D QmitkSliceNavigationListener::GetCurrentSelectedPosition() const
{
return m_CurrentSelectedPosition;
}
void QmitkSliceNavigationListener::OnSliceChangedDelayed()
{
m_PendingSliceChangedEvent = false;
emit SliceChanged();
if (nullptr != m_renderWindowPart)
{
const auto newSelectedPosition = m_renderWindowPart->GetSelectedPosition();
- const auto newSelectedTimePoint = m_renderWindowPart->GetSelectedTimePoint();
if (newSelectedPosition != m_CurrentSelectedPosition)
{
m_CurrentSelectedPosition = newSelectedPosition;
emit SelectedPositionChanged(newSelectedPosition);
}
-
- if (newSelectedTimePoint != m_CurrentSelectedTimePoint)
- {
- m_CurrentSelectedTimePoint = newSelectedTimePoint;
- emit SelectedTimePointChanged(newSelectedTimePoint);
- }
}
}
void QmitkSliceNavigationListener::OnSliceChangedInternal(const itk::EventObject&)
{
// Since there are always 3 events arriving (one for each render window) every time the slice
// or time changes, the slot OnSliceChangedDelayed is triggered - and only if it hasn't been
// triggered yet - so it is only executed once for every slice/time change.
if (!m_PendingSliceChangedEvent)
{
m_PendingSliceChangedEvent = true;
QTimer::singleShot(0, this, SLOT(OnSliceChangedDelayed()));
}
}
+void QmitkSliceNavigationListener::OnTimeChangedInternal(itk::Object* sender, const itk::EventObject& e)
+{
+ if (!dynamic_cast<const mitk::TimeNavigationController::TimeEvent*>(&e))
+ {
+ return;
+ }
+
+ const auto* timeNavigationController = dynamic_cast<mitk::TimeNavigationController*>(sender);
+ if (nullptr == timeNavigationController)
+ {
+ return;
+ }
+
+ const mitk::TimePointType newSelectedTimePoint = timeNavigationController->GetSelectedTimePoint();
+ if (newSelectedTimePoint != m_CurrentSelectedTimePoint)
+ {
+ m_CurrentSelectedTimePoint = newSelectedTimePoint;
+ emit SelectedTimePointChanged(newSelectedTimePoint);
+ }
+}
+
void QmitkSliceNavigationListener::OnSliceNavigationControllerDeleted(const itk::Object* sender, const itk::EventObject& /*e*/)
{
const mitk::SliceNavigationController* sendingSlicer =
dynamic_cast<const mitk::SliceNavigationController*>(sender);
this->RemoveObservers(sendingSlicer);
}
void QmitkSliceNavigationListener::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (m_renderWindowPart != renderWindowPart)
{
m_renderWindowPart = renderWindowPart;
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ itk::MemberCommand<QmitkSliceNavigationListener>::Pointer cmdTimeEvent =
+ itk::MemberCommand<QmitkSliceNavigationListener>::New();
+ cmdTimeEvent->SetCallbackFunction(this, &QmitkSliceNavigationListener::OnTimeChangedInternal);
+ m_ControllerToTimeObserverTag = timeNavigationController->AddObserver(mitk::TimeNavigationController::TimeEvent(0), cmdTimeEvent);
+
if (!InitObservers())
{
QMessageBox::information(nullptr, "Error", "Unable to set up the event observers.");
}
m_CurrentSelectedPosition = m_renderWindowPart->GetSelectedPosition();
- m_CurrentSelectedTimePoint = m_renderWindowPart->GetSelectedTimePoint();
+ m_CurrentSelectedTimePoint = timeNavigationController->GetSelectedTimePoint();
}
}
void QmitkSliceNavigationListener::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart)
{
m_renderWindowPart = nullptr;
this->RemoveAllObservers(renderWindowPart);
}
void QmitkSliceNavigationListener::RenderWindowPartInputChanged(mitk::IRenderWindowPart* renderWindowPart)
{
if (m_renderWindowPart == renderWindowPart)
{
if (!InitObservers())
{
QMessageBox::information(nullptr, "Error", "Unable to set up the event observers.");
}
m_CurrentSelectedPosition = m_renderWindowPart->GetSelectedPosition();
- m_CurrentSelectedTimePoint = m_renderWindowPart->GetSelectedTimePoint();
+
+ const auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ m_CurrentSelectedTimePoint = timeNavigationController->GetSelectedTimePoint();
}
}
bool QmitkSliceNavigationListener::InitObservers()
{
bool result = true;
typedef QHash<QString, QmitkRenderWindow*> WindowMapType;
WindowMapType windowMap = m_renderWindowPart->GetQmitkRenderWindows();
auto i = windowMap.begin();
while (i != windowMap.end())
{
- mitk::SliceNavigationController* sliceNavController =
- i.value()->GetSliceNavigationController();
+ mitk::SliceNavigationController* sliceNavController = i.value()->GetSliceNavigationController();
- if (sliceNavController)
+ if (nullptr != sliceNavController)
{
bool observersInitialized = this->ObserversInitialized(sliceNavController);
- if(false == observersInitialized)
+ if (false == observersInitialized)
{
itk::ReceptorMemberCommand<QmitkSliceNavigationListener>::Pointer cmdSliceEvent =
itk::ReceptorMemberCommand<QmitkSliceNavigationListener>::New();
cmdSliceEvent->SetCallbackFunction(this, &QmitkSliceNavigationListener::OnSliceChangedInternal);
int tag = sliceNavController->AddObserver(
mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0),
cmdSliceEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
i.key().toStdString(), m_renderWindowPart)));
- itk::ReceptorMemberCommand<QmitkSliceNavigationListener>::Pointer cmdTimeEvent =
- itk::ReceptorMemberCommand<QmitkSliceNavigationListener>::New();
- cmdTimeEvent->SetCallbackFunction(this, &QmitkSliceNavigationListener::OnSliceChangedInternal);
- tag = sliceNavController->AddObserver(
- mitk::SliceNavigationController::GeometryTimeEvent(nullptr, 0),
- cmdTimeEvent);
-
- m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
- i.key().toStdString(), m_renderWindowPart)));
-
itk::ReceptorMemberCommand<QmitkSliceNavigationListener>::Pointer cmdUpdateEvent =
itk::ReceptorMemberCommand<QmitkSliceNavigationListener>::New();
cmdUpdateEvent->SetCallbackFunction(this, &QmitkSliceNavigationListener::OnSliceChangedInternal);
tag = sliceNavController->AddObserver(
mitk::SliceNavigationController::GeometryUpdateEvent(nullptr, 0),
cmdUpdateEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
i.key().toStdString(), m_renderWindowPart)));
itk::MemberCommand<QmitkSliceNavigationListener>::Pointer cmdDelEvent =
itk::MemberCommand<QmitkSliceNavigationListener>::New();
cmdDelEvent->SetCallbackFunction(this,
&QmitkSliceNavigationListener::OnSliceNavigationControllerDeleted);
tag = sliceNavController->AddObserver(
itk::DeleteEvent(), cmdDelEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
i.key().toStdString(), m_renderWindowPart)));
}
}
++i;
result = result && sliceNavController;
}
return result;
}
void QmitkSliceNavigationListener::RemoveObservers(const mitk::SliceNavigationController* deletedSlicer)
{
std::pair < ObserverMapType::const_iterator, ObserverMapType::const_iterator> obsRange =
m_ObserverMap.equal_range(deletedSlicer);
for (ObserverMapType::const_iterator pos = obsRange.first; pos != obsRange.second; ++pos)
{
pos->second.controller->RemoveObserver(pos->second.observerTag);
}
m_ObserverMap.erase(deletedSlicer);
}
void QmitkSliceNavigationListener::RemoveAllObservers(mitk::IRenderWindowPart* deletedPart)
{
for (ObserverMapType::const_iterator pos = m_ObserverMap.begin(); pos != m_ObserverMap.end();)
{
ObserverMapType::const_iterator delPos = pos++;
if (deletedPart == nullptr || deletedPart == delPos->second.renderWindowPart)
{
delPos->second.controller->RemoveObserver(delPos->second.observerTag);
m_ObserverMap.erase(delPos);
}
}
+
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ timeNavigationController->RemoveObserver(m_ControllerToTimeObserverTag);
}
bool QmitkSliceNavigationListener::ObserversInitialized(mitk::SliceNavigationController* controller)
{
auto it = m_ObserverMap.find(controller);
return it != m_ObserverMap.end();
}
QmitkSliceNavigationListener::ObserverInfo::ObserverInfo(mitk::SliceNavigationController* controller, int observerTag,
const std::string& renderWindowName, mitk::IRenderWindowPart* part) : controller(controller), observerTag(observerTag),
renderWindowName(renderWindowName), renderWindowPart(part)
{
}
diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.h b/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.h
index a014d14a49..d075f60572 100644
--- a/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.h
+++ b/Plugins/org.mitk.gui.qt.common/src/QmitkSliceNavigationListener.h
@@ -1,135 +1,137 @@
/*============================================================================
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 QmitkSliceNavigationListener_h
#define QmitkSliceNavigationListener_h
#include <mitkTimeGeometry.h>
#include <mitkPoint.h>
#include <itkEventObject.h>
#include <QObject>
#include <org_mitk_gui_qt_common_Export.h>
namespace itk
{
class Object;
}
namespace mitk
{
class SliceNavigationController;
struct IRenderWindowPart;
}
/** @brief Helper class to allow QmitkAbstractView and derived classes to react on changes of the slice/time navigation.
Purpose of the class to be used in view and to give the respective view class (by composition) the posibility to react
on changes of the currently selected timepoint or position in the world geometry.\n
It also offers convinient signals that are only triggered when the selected timepoint or the selected possition of the
active render window have realy changed.\n
In order to setup this class properly the following things must be regarded:
- View class must also derive public from mitk::IRenderWindowPartListener
- View class must implement void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) and pass the renderWindowPart to the listener.
void QmitkMyView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
this->m_SliceNavigationListener.RenderWindowPartActivated(renderWindowPart);
}
- View class must implement void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) and pass the renderWindowPart to the listener.
void QmitkMyView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart)
{
this->m_SliceNavigationListener.RenderWindowPartDeactivated(renderWindowPart);
}
- View class must pass its on render window part in its CreateQtPartControl(QWidget* parent)
this->m_SliceNavigationListener.RenderWindowPartActivated(this->GetRenderWindowPart());
- View class must connect the SliceChanged signal of the listener as see fit.
*/
class MITK_QT_COMMON QmitkSliceNavigationListener : public QObject
{
Q_OBJECT
public:
QmitkSliceNavigationListener();
~QmitkSliceNavigationListener() override;
mitk::TimePointType GetCurrentSelectedTimePoint() const;
mitk::Point3D GetCurrentSelectedPosition() const;
signals:
/** Signal triggered as soon as there is any change. It may be a change in the position/slice or of the selected timepoint.*/
void SliceChanged();
/** Convinience signal that can be used if you are only interested in changes of the current selected time point.
Changes in spatial position will be ignored.*/
void SelectedTimePointChanged(const mitk::TimePointType& newTimePoint);
/** Convinience signal that can be used if you are only interested in changes of the current selected position.
Changes in time will be ignored.*/
void SelectedPositionChanged(const mitk::Point3D& newPoint);
public slots:
void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart);
void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart);
void RenderWindowPartInputChanged(mitk::IRenderWindowPart* renderWindowPart);
protected slots:
/** Overwrite function to implement the behavior on slice/time changes. */
void OnSliceChangedDelayed();
protected:
/** @brief Calls OnSliceChangedDelayed so the event isn't triggered multiple times. */
void OnSliceChangedInternal(const itk::EventObject& e);
+ void OnTimeChangedInternal(itk::Object* sender, const itk::EventObject& e);
void OnSliceNavigationControllerDeleted(const itk::Object* sender, const itk::EventObject& /*e*/);
/** Initializes and sets the observers that are used to monitor changes in the selected position
or time point in order to actualize the view.h*/
bool InitObservers();
void RemoveObservers(const mitk::SliceNavigationController* deletedSlicer);
/** Removes all observers of the deletedPart. If null pointer is passed all observers will be removed.*/
void RemoveAllObservers(mitk::IRenderWindowPart* deletedPart = nullptr);
bool ObserversInitialized(mitk::SliceNavigationController* controller);
mitk::IRenderWindowPart* m_renderWindowPart;
// Needed for observing the events for when a slice or time step is changed.
bool m_PendingSliceChangedEvent;
/**Helper structure to manage the registered observer events.*/
struct ObserverInfo
{
mitk::SliceNavigationController* controller;
int observerTag;
std::string renderWindowName;
mitk::IRenderWindowPart* renderWindowPart;
ObserverInfo(mitk::SliceNavigationController* controller, int observerTag,
const std::string& renderWindowName, mitk::IRenderWindowPart* part);
};
typedef std::multimap<const mitk::SliceNavigationController*, ObserverInfo> ObserverMapType;
ObserverMapType m_ObserverMap;
+ unsigned int m_ControllerToTimeObserverTag;
mitk::Point3D m_CurrentSelectedPosition;
mitk::TimePointType m_CurrentSelectedTimePoint;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.common/src/internal/QmitkCommonActivator.cpp b/Plugins/org.mitk.gui.qt.common/src/internal/QmitkCommonActivator.cpp
index b925ff44dd..b66e9ccc1d 100644
--- a/Plugins/org.mitk.gui.qt.common/src/internal/QmitkCommonActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.common/src/internal/QmitkCommonActivator.cpp
@@ -1,71 +1,71 @@
/*============================================================================
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 "QmitkCommonActivator.h"
#include <berryPlatformUI.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkCoreServices.h>
#include "QmitkNodeSelectionPreferencePage.h"
#include <usModuleInitialization.h>
US_INITIALIZE_MODULE
QmitkCommonActivator* QmitkCommonActivator::m_Instance = nullptr;
ctkPluginContext* QmitkCommonActivator::m_Context = nullptr;
ctkPluginContext* QmitkCommonActivator::GetContext()
{
return m_Context;
}
QmitkCommonActivator* QmitkCommonActivator::GetInstance()
{
return m_Instance;
}
mitk::IPreferencesService* QmitkCommonActivator::GetPreferencesService()
{
return mitk::CoreServices::GetPreferencesService();
}
void
QmitkCommonActivator::start(ctkPluginContext* context)
{
this->m_Instance = this;
this->m_Context = context;
if(berry::PlatformUI::IsWorkbenchRunning())
{
m_ViewCoordinator.reset(new QmitkViewCoordinator);
m_ViewCoordinator->Start();
}
else
{
MITK_ERROR << "BlueBerry Workbench not running!";
}
BERRY_REGISTER_EXTENSION_CLASS(QmitkNodeSelectionPreferencePage, context)
}
void
QmitkCommonActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_ViewCoordinator->Stop();
m_ViewCoordinator.reset();
this->m_Context = nullptr;
this->m_Instance = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/DicomEventHandler.cpp b/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/DicomEventHandler.cpp
index c5292db40d..b9a6a78fab 100644
--- a/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/DicomEventHandler.cpp
+++ b/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/DicomEventHandler.cpp
@@ -1,256 +1,256 @@
/*============================================================================
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 "mitkPluginActivator.h"
#include "DicomEventHandler.h"
#include <service/event/ctkEventConstants.h>
#include <ctkDictionary.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <mitkDataNode.h>
#include <mitkIDataStorageService.h>
#include <service/event/ctkEventAdmin.h>
#include <ctkServiceReference.h>
#include <mitkRenderingManager.h>
#include <QVector>
#include "mitkImage.h"
#include <mitkContourModelSet.h>
#include <mitkFileReaderRegistry.h>
#include <mitkDICOMRTMimeTypes.h>
#include <mitkDICOMFileReaderSelector.h>
#include <mitkDICOMDCMTKTagScanner.h>
#include <mitkDICOMEnums.h>
#include <mitkDICOMTagsOfInterestHelper.h>
#include <mitkDICOMProperty.h>
#include <mitkPropertyNameHelper.h>
#include "mitkBaseDICOMReaderService.h"
#include <mitkRTConstants.h>
#include <mitkIsoDoseLevelCollections.h>
#include <mitkIsoDoseLevelSetProperty.h>
#include <mitkIsoDoseLevelVectorProperty.h>
#include <mitkDoseImageVtkMapper2D.h>
#include <mitkRTUIConstants.h>
#include <mitkIsoLevelsGenerator.h>
#include <mitkDoseNodeHelper.h>
#include <vtkSmartPointer.h>
#include <vtkMath.h>
#include <mitkTransferFunction.h>
#include <mitkTransferFunctionProperty.h>
#include <mitkRenderingModeProperty.h>
#include <mitkLocaleSwitch.h>
#include <mitkIOUtil.h>
#include <mitkCoreServices.h>
#include <mitkIPreferencesService.h>
#include <mitkIPreferences.h>
#include <ImporterUtil.h>
namespace
{
mitk::IFileReader* GetReader(mitk::FileReaderRegistry& readerRegistry, const mitk::CustomMimeType& mimeType)
{
try
{
return readerRegistry.GetReaders(mitk::MimeType(mimeType, -1, -1)).at(0);
}
catch (const std::out_of_range&)
{
mitkThrow() << "Cannot find " << mimeType.GetCategory() << " " << mimeType.GetComment() << " file reader.";
}
}
}
DicomEventHandler::DicomEventHandler()
{
}
DicomEventHandler::~DicomEventHandler()
{
}
void DicomEventHandler::OnSignalAddSeriesToDataManager(const ctkEvent& ctkEvent)
{
QStringList listOfFilesForSeries;
listOfFilesForSeries = ctkEvent.getProperty("FilesForSeries").toStringList();
if (!listOfFilesForSeries.isEmpty())
{
//for rt data, if the modality tag isn't defined or is "CT" the image is handled like before
if(ctkEvent.containsProperty("Modality") &&
(ctkEvent.getProperty("Modality").toString().compare("RTDOSE",Qt::CaseInsensitive) == 0 ||
ctkEvent.getProperty("Modality").toString().compare("RTSTRUCT",Qt::CaseInsensitive) == 0 ||
ctkEvent.getProperty("Modality").toString().compare("RTPLAN", Qt::CaseInsensitive) == 0))
{
QString modality = ctkEvent.getProperty("Modality").toString();
mitk::FileReaderRegistry readerRegistry;
if(modality.compare("RTDOSE",Qt::CaseInsensitive) == 0)
{
auto doseReader = GetReader(readerRegistry, mitk::DICOMRTMimeTypes::DICOMRT_DOSE_MIMETYPE());
doseReader->SetInput(ImporterUtil::getUTF8String(listOfFilesForSeries.front()));
std::vector<itk::SmartPointer<mitk::BaseData> > readerOutput = doseReader->Read();
if (!readerOutput.empty()){
mitk::Image::Pointer doseImage = dynamic_cast<mitk::Image*>(readerOutput.at(0).GetPointer());
mitk::DataNode::Pointer doseImageNode = mitk::DataNode::New();
doseImageNode->SetData(doseImage);
doseImageNode->SetName("RTDose");
if (doseImage != nullptr)
{
std::string sopUID;
if (mitk::GetBackwardsCompatibleDICOMProperty(0x0008, 0x0016, "dicomseriesreader.SOPClassUID", doseImage->GetPropertyList(), sopUID))
{
doseImageNode->SetName(sopUID);
};
auto* prefService = mitk::CoreServices::GetPreferencesService();
auto* prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID);
if (prefNode == nullptr)
mitkThrow() << "Error in preference interface. Cannot find preset node under given name. Name: " << prefNode;
//set some specific colorwash and isoline properties
bool showColorWashGlobal = prefNode->GetBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_COLORWASH_ID, true);
//Set reference dose property
double referenceDose = prefNode->GetDouble(mitk::RTUIConstants::REFERENCE_DOSE_ID, mitk::RTUIConstants::DEFAULT_REFERENCE_DOSE_VALUE);
mitk::ConfigureNodeAsDoseNode(doseImageNode, mitk::GenerateIsoLevels_Virtuos(), referenceDose, showColorWashGlobal);
ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference<mitk::IDataStorageService>();
mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService<mitk::IDataStorageService>(serviceReference);
mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage();
dataStorage->Add(doseImageNode);
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage);
}
}//END DOSE
}
else if(modality.compare("RTSTRUCT",Qt::CaseInsensitive) == 0)
{
auto structReader = GetReader(readerRegistry, mitk::DICOMRTMimeTypes::DICOMRT_STRUCT_MIMETYPE());
structReader->SetInput(ImporterUtil::getUTF8String(listOfFilesForSeries.front()));
std::vector<itk::SmartPointer<mitk::BaseData> > readerOutput = structReader->Read();
if (readerOutput.empty()){
MITK_ERROR << "No structure sets were created" << endl;
}
else {
std::vector<mitk::DataNode::Pointer> modelVector;
ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference<mitk::IDataStorageService>();
mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService<mitk::IDataStorageService>(serviceReference);
mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage();
for (const auto& aStruct : readerOutput){
mitk::ContourModelSet::Pointer countourModelSet = dynamic_cast<mitk::ContourModelSet*>(aStruct.GetPointer());
mitk::DataNode::Pointer structNode = mitk::DataNode::New();
structNode->SetData(countourModelSet);
structNode->SetProperty("name", aStruct->GetProperty("name"));
structNode->SetProperty("color", aStruct->GetProperty("contour.color"));
structNode->SetProperty("contour.color", aStruct->GetProperty("contour.color"));
structNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
dataStorage->Add(structNode);
}
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage);
}
}
else if (modality.compare("RTPLAN", Qt::CaseInsensitive) == 0)
{
auto planReader = GetReader(readerRegistry, mitk::DICOMRTMimeTypes::DICOMRT_PLAN_MIMETYPE());
planReader->SetInput(ImporterUtil::getUTF8String(listOfFilesForSeries.front()));
std::vector<itk::SmartPointer<mitk::BaseData> > readerOutput = planReader->Read();
if (!readerOutput.empty()){
//there is no image, only the properties are interesting
mitk::Image::Pointer planDummyImage = dynamic_cast<mitk::Image*>(readerOutput.at(0).GetPointer());
mitk::DataNode::Pointer planImageNode = mitk::DataNode::New();
planImageNode->SetData(planDummyImage);
planImageNode->SetName("RTPlan");
ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference<mitk::IDataStorageService>();
mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService<mitk::IDataStorageService>(serviceReference);
mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage();
dataStorage->Add(planImageNode);
}
}
}
else
{
mitk::StringList seriesToLoad;
QStringListIterator it(listOfFilesForSeries);
while (it.hasNext())
{
seriesToLoad.push_back(ImporterUtil::getUTF8String(it.next()));
}
//Get Reference for default data storage.
ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference<mitk::IDataStorageService>();
mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService<mitk::IDataStorageService>(serviceReference);
mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage();
std::vector<mitk::BaseData::Pointer> baseDatas = mitk::IOUtil::Load(seriesToLoad.front());
for (const auto &data : baseDatas)
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(data);
std::string nodeName = mitk::DataNode::NO_NAME_VALUE();
auto nameDataProp = data->GetProperty("name");
if (nameDataProp.IsNotNull())
{ //if data has a name property set by reader, use this name
nodeName = nameDataProp->GetValueAsString();
}
else
{ //reader didn't specify a name, generate one.
nodeName = mitk::GenerateNameFromDICOMProperties(node);
}
node->SetName(nodeName);
dataStorage->Add(node);
}
}
}
else
{
MITK_INFO << "There are no files for the current series";
}
}
void DicomEventHandler::OnSignalRemoveSeriesFromStorage(const ctkEvent& /*ctkEvent*/)
{
}
void DicomEventHandler::SubscribeSlots()
{
ctkServiceReference ref = mitk::PluginActivator::getContext()->getServiceReference<ctkEventAdmin>();
if (ref)
{
ctkEventAdmin* eventAdmin = mitk::PluginActivator::getContext()->getService<ctkEventAdmin>(ref);
ctkDictionary properties;
properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/ADD";
eventAdmin->subscribeSlot(this, SLOT(OnSignalAddSeriesToDataManager(ctkEvent)), properties);
properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/DELETED";
eventAdmin->subscribeSlot(this, SLOT(OnSignalRemoveSeriesFromStorage(ctkEvent)), properties);
}
}
diff --git a/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDicomDirectoryListener.cpp b/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDicomDirectoryListener.cpp
index 50458cea84..7b8c2335b9 100644
--- a/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDicomDirectoryListener.cpp
+++ b/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkDicomDirectoryListener.cpp
@@ -1,115 +1,115 @@
/*============================================================================
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 "QmitkDicomDirectoryListener.h"
#include <QString>
#include <QFile>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <QFileInfoList>
#include <QDirIterator>
QmitkDicomDirectoryListener::QmitkDicomDirectoryListener()
: m_FileSystemWatcher(new QFileSystemWatcher())
, m_IsListening(true)
{
connect(m_FileSystemWatcher,SIGNAL(directoryChanged(const QString&)),this,SLOT(OnDirectoryChanged(const QString&)));
}
QmitkDicomDirectoryListener::~QmitkDicomDirectoryListener()
{
disconnect(m_FileSystemWatcher,SIGNAL(directoryChanged(const QString&)),this,SLOT(OnDirectoryChanged(const QString&)));
m_IsListening = false;
RemoveTemporaryFiles();
delete m_FileSystemWatcher;
}
void QmitkDicomDirectoryListener::OnDirectoryChanged(const QString&)
{
if(m_IsListening)
{
QDirIterator it( m_DicomListenerDirectory.absolutePath() , QDir::Files , QDirIterator::Subdirectories);
QString currentPath;
m_FilesToImport.clear();
while(it.hasNext())
{
it.next();
currentPath = it.fileInfo().absoluteFilePath();
if(!m_AlreadyImportedFiles.contains(currentPath))
{
m_AlreadyImportedFiles.insert( currentPath , currentPath );
m_FilesToImport.append(currentPath);
}
}
if(!m_FilesToImport.isEmpty())
{
emit SignalStartDicomImport(m_FilesToImport);
}
}
}
void QmitkDicomDirectoryListener::OnDicomNetworkError(const QString& /*errorMsg*/)
{
m_IsListening = false;
m_AlreadyImportedFiles.clear();
m_IsListening = true;
}
void QmitkDicomDirectoryListener::RemoveTemporaryFiles()
{
if(m_DicomListenerDirectory.absolutePath().contains(m_DicomFolderSuffix))
{
QDirIterator it( m_DicomListenerDirectory.absolutePath() , QDir::AllEntries , QDirIterator::Subdirectories);
while(it.hasNext())
{
it.next();
m_DicomListenerDirectory.remove(it.fileInfo().absoluteFilePath());
}
m_DicomListenerDirectory.rmdir(m_DicomListenerDirectory.absolutePath());
}
}
void QmitkDicomDirectoryListener::SetDicomListenerDirectory(const QString& directory)
{
QDir dir(directory);
if(dir.exists())
{
m_DicomListenerDirectory=dir;
m_FileSystemWatcher->addPath(m_DicomListenerDirectory.absolutePath());
}
else
{
dir.mkpath(directory);
m_DicomListenerDirectory=dir;
m_FileSystemWatcher->addPath(m_DicomListenerDirectory.absolutePath());
}
}
QString QmitkDicomDirectoryListener::GetDicomListenerDirectory()
{
return m_DicomListenerDirectory.absolutePath();
}
bool QmitkDicomDirectoryListener::IsListening()
{
return m_IsListening;
}
void QmitkDicomDirectoryListener::SetListening(bool listening)
{
m_IsListening = listening;
}
void QmitkDicomDirectoryListener::SetDicomFolderSuffix(QString suffix)
{
m_DicomFolderSuffix = suffix;
}
diff --git a/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkStoreSCPLauncher.cpp b/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkStoreSCPLauncher.cpp
index d295cdf7df..b9ee7254b4 100644
--- a/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkStoreSCPLauncher.cpp
+++ b/Plugins/org.mitk.gui.qt.dicombrowser/src/internal/QmitkStoreSCPLauncher.cpp
@@ -1,199 +1,199 @@
/*============================================================================
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 "QmitkStoreSCPLauncher.h"
#include <QMessageBox>
#include <QProcessEnvironment>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <fstream>
#include <iostream>
#include <QFile>
#include <QTextStream>
#include <QIODevice>
#include <QDir>
#include <QDirIterator>
#include <QCoreApplication>
#include "org_mitk_gui_qt_dicombrowser_config.h"
QmitkStoreSCPLauncher::QmitkStoreSCPLauncher(QmitkStoreSCPLauncherBuilder* builder)
: m_StoreSCP(new QProcess())
{
m_StoreSCP->setProcessChannelMode(QProcess::MergedChannels);
connect( m_StoreSCP, SIGNAL(error(QProcess::ProcessError)),this, SLOT(OnProcessError(QProcess::ProcessError)));
connect( m_StoreSCP, SIGNAL(stateChanged(QProcess::ProcessState)),this, SLOT(OnStateChanged(QProcess::ProcessState)));
connect( m_StoreSCP, SIGNAL(readyReadStandardOutput()),this, SLOT(OnReadyProcessOutput()));
SetArgumentList(builder);
}
QmitkStoreSCPLauncher::~QmitkStoreSCPLauncher()
{
disconnect( m_StoreSCP, SIGNAL(error(QProcess::ProcessError)),this, SLOT(OnProcessError(QProcess::ProcessError)));
disconnect( m_StoreSCP, SIGNAL(stateChanged(QProcess::ProcessState)),this, SLOT(OnStateChanged(QProcess::ProcessState)));
disconnect( m_StoreSCP, SIGNAL(readyReadStandardOutput()),this, SLOT(OnReadyProcessOutput()));
m_StoreSCP->close();
m_StoreSCP->waitForFinished(1000);
delete m_StoreSCP;
}
void QmitkStoreSCPLauncher::StartStoreSCP()
{
FindPathToStoreSCP();
m_StoreSCP->start(m_PathToStoreSCP,m_ArgumentList);
}
void QmitkStoreSCPLauncher::FindPathToStoreSCP()
{
QString appPath= QCoreApplication::applicationDirPath();
if(m_PathToStoreSCP.isEmpty())
{
QString fileName;
#ifdef _WIN32
fileName = "/storescp.exe";
#else
fileName = "/storescp";
#endif
m_PathToStoreSCP = appPath + fileName;
//In developement the storescp isn't copied into bin directory
if(!QFile::exists(m_PathToStoreSCP))
{
m_PathToStoreSCP = static_cast<QString>(DCMTK_STORESCP);
}
}
}
void QmitkStoreSCPLauncher::OnReadyProcessOutput()
{
QString out(m_StoreSCP->readAllStandardOutput());
QStringList allDataList,importList;
allDataList = out.split("\n",QString::SkipEmptyParts);
QStringListIterator it(allDataList);
while(it.hasNext())
{
QString output = it.next();
if (output.contains("E: "))
{
output.replace("E: ","");
m_ErrorText = output;
OnProcessError(QProcess::UnknownError);
return;
}
if(output.contains("I: storing DICOM file: "))
{
output.replace("I: storing DICOM file: ","");
output.replace("\\", "/"); // cannot handle backslashes
output.replace("\r", ""); // cannot handle carriage return
importList += output;
}
}
if(!importList.isEmpty())
{
emit SignalStartImport(importList);
}
}
void QmitkStoreSCPLauncher::OnProcessError(QProcess::ProcessError err)
{
switch(err)
{
case QProcess::FailedToStart:
m_ErrorText.prepend("Failed to start storage provider: ");
m_ErrorText.append(m_StoreSCP->errorString());
emit SignalStoreSCPError(m_ErrorText);
m_ErrorText.clear();
break;
case QProcess::Crashed:
m_ErrorText.prepend("Storage provider closed: ");
m_ErrorText.append(m_StoreSCP->errorString());
emit SignalStoreSCPError(m_ErrorText);
m_ErrorText.clear();
break;
case QProcess::Timedout:
m_ErrorText.prepend("Storage provider timeout: ");
m_ErrorText.append(m_StoreSCP->errorString());
emit SignalStoreSCPError(m_ErrorText);
m_ErrorText.clear();
break;
case QProcess::WriteError:
m_ErrorText.prepend("Storage provider write error: ");
m_ErrorText.append(m_StoreSCP->errorString());
emit SignalStoreSCPError(m_ErrorText);
m_ErrorText.clear();
break;
case QProcess::ReadError:
m_ErrorText.prepend("Storage provider read error: ");
m_ErrorText.append(m_StoreSCP->errorString());
emit SignalStoreSCPError(m_ErrorText);
m_ErrorText.clear();
break;
case QProcess::UnknownError:
m_ErrorText.prepend("Storage provider unknown error: ");
m_ErrorText.append(m_StoreSCP->errorString());
emit SignalStoreSCPError(m_ErrorText);
m_ErrorText.clear();
break;
default:
m_ErrorText.prepend("Storage provider unknown error: ");
m_ErrorText.append(m_StoreSCP->errorString());
emit SignalStoreSCPError(m_ErrorText);
m_ErrorText.clear();
break;
}
}
void QmitkStoreSCPLauncher::OnStateChanged(QProcess::ProcessState status)
{
switch(status)
{
case QProcess::NotRunning:
m_StatusText.prepend("Storage provider not running!");
emit SignalStatusOfStoreSCP(m_StatusText);
m_StatusText.clear();
break;
case QProcess::Starting:
m_StatusText.prepend("Starting storage provider!");
emit SignalStatusOfStoreSCP(m_StatusText);
m_StatusText.clear();
break;
case QProcess::Running:
m_StatusText.prepend(m_ArgumentList[0]).prepend(" Port: ").prepend(m_ArgumentList[2]).prepend(" AET: ").prepend("Storage provider running! ");
emit SignalStatusOfStoreSCP(m_StatusText);
m_StatusText.clear();
break;
default:
m_StatusText.prepend("Storage provider unknown error!");
emit SignalStatusOfStoreSCP(m_StatusText);
m_StatusText.clear();
break;
}
}
void QmitkStoreSCPLauncher::SetArgumentList(QmitkStoreSCPLauncherBuilder* builder)
{
m_ArgumentList << *builder->GetPort() << QString("-aet") <<*builder->GetAETitle() << *builder->GetTransferSyntax()
<< *builder->GetOtherNetworkOptions() << *builder->GetMode() << QString("-od") << *builder->GetOutputDirectory();
}
QString QmitkStoreSCPLauncher::ArgumentListToQString()
{
QString argumentString;
QStringListIterator argumentIterator(m_ArgumentList);
while(argumentIterator.hasNext())
{
argumentString.append(" ");
argumentString.append(argumentIterator.next());
}
return argumentString;
}
diff --git a/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp b/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp
index d3b1171e2c..c0808922fb 100644
--- a/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp
+++ b/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.cpp
@@ -1,377 +1,389 @@
/*============================================================================
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.
============================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIWorkbenchPage.h>
// mitk
#include <QmitkRenderWindow.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkPixelTypeMultiplex.h>
+#include <mitkTimeNavigationController.h>
// Qt
#include <QMessageBox>
#include <QMessageBox>
#include <QFileDialog>
#include <qwt_plot_marker.h>
#include "QmitkDicomInspectorView.h"
const std::string QmitkDicomInspectorView::VIEW_ID = "org.mitk.views.dicominspector";
QmitkDicomInspectorView::ObserverInfo::ObserverInfo(mitk::SliceNavigationController* controller,
- int observerTag, const std::string& renderWindowName, mitk::IRenderWindowPart* part) : controller(controller), observerTag(observerTag),
- renderWindowName(renderWindowName), renderWindowPart(part)
+ int observerTag, mitk::IRenderWindowPart* part)
+ : controller(controller)
+ , observerTag(observerTag)
+ , renderWindowPart(part)
{
}
QmitkDicomInspectorView::QmitkDicomInspectorView()
: m_RenderWindowPart(nullptr)
, m_PendingSliceChangedEvent(false)
, m_SelectedNode(nullptr)
, m_SelectedTimePoint(0.)
, m_CurrentSelectedZSlice(0)
{
m_SelectedPosition.Fill(0.0);
}
QmitkDicomInspectorView::~QmitkDicomInspectorView()
{
this->RemoveAllObservers();
}
void QmitkDicomInspectorView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (m_RenderWindowPart != renderWindowPart)
{
m_RenderWindowPart = renderWindowPart;
if (!InitObservers())
{
QMessageBox::information(nullptr, "Error", "Unable to set up the event observers. The " \
"plot will not be triggered on changing the crosshair, " \
"position or time step.");
}
}
}
void QmitkDicomInspectorView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart)
{
m_RenderWindowPart = nullptr;
this->RemoveAllObservers(renderWindowPart);
}
void QmitkDicomInspectorView::CreateQtPartControl(QWidget* parent)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls.setupUi(parent);
m_Controls.singleSlot->SetDataStorage(GetDataStorage());
m_Controls.singleSlot->SetSelectionIsOptional(true);
m_Controls.singleSlot->SetAutoSelectNewNodes(true);
m_Controls.singleSlot->SetEmptyInfo(QString("Please select a data node"));
m_Controls.singleSlot->SetPopUpTitel(QString("Select data node"));
m_SelectionServiceConnector = std::make_unique<QmitkSelectionServiceConnector>();
SetAsSelectionListener(true);
m_Controls.timePointValueLabel->setText(QString(""));
m_Controls.sliceNumberValueLabel->setText(QString(""));
connect(m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged,
this, &QmitkDicomInspectorView::OnCurrentSelectionChanged);
mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart();
RenderWindowPartActivated(renderWindowPart);
}
bool QmitkDicomInspectorView::InitObservers()
{
bool result = true;
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ itk::SimpleMemberCommand<QmitkDicomInspectorView>::Pointer cmdTimeEvent =
+ itk::SimpleMemberCommand<QmitkDicomInspectorView>::New();
+ cmdTimeEvent->SetCallbackFunction(this, &QmitkDicomInspectorView::OnTimeChanged);
+ m_ControllerToTimeObserverTag = timeNavigationController->AddObserver(mitk::TimeNavigationController::TimeEvent(0), cmdTimeEvent);
+
typedef QHash<QString, QmitkRenderWindow*> WindowMapType;
WindowMapType windowMap = m_RenderWindowPart->GetQmitkRenderWindows();
auto i = windowMap.begin();
while (i != windowMap.end())
{
- mitk::SliceNavigationController* sliceNavController =
- i.value()->GetSliceNavigationController();
+ mitk::SliceNavigationController* sliceNavController = i.value()->GetSliceNavigationController();
- if (sliceNavController)
+ if (nullptr != sliceNavController)
{
auto cmdSliceEvent = itk::SimpleMemberCommand<QmitkDicomInspectorView>::New();
cmdSliceEvent->SetCallbackFunction(this, &QmitkDicomInspectorView::OnSliceChanged);
int tag = sliceNavController->AddObserver(
mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), cmdSliceEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
- i.key().toStdString(), m_RenderWindowPart)));
-
- auto cmdTimeEvent = itk::SimpleMemberCommand<QmitkDicomInspectorView>::New();
- cmdTimeEvent->SetCallbackFunction(this, &QmitkDicomInspectorView::OnSliceChanged);
- tag = sliceNavController->AddObserver(
- mitk::SliceNavigationController::GeometryTimeEvent(nullptr, 0), cmdTimeEvent);
-
- m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
- i.key().toStdString(), m_RenderWindowPart)));
+ m_RenderWindowPart)));
auto cmdDelEvent = itk::MemberCommand<QmitkDicomInspectorView>::New();
cmdDelEvent->SetCallbackFunction(this, &QmitkDicomInspectorView::OnSliceNavigationControllerDeleted);
tag = sliceNavController->AddObserver(itk::DeleteEvent(), cmdDelEvent);
m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag,
- i.key().toStdString(), m_RenderWindowPart)));
+ m_RenderWindowPart)));
}
++i;
result = result && sliceNavController;
}
return result;
}
void QmitkDicomInspectorView::RemoveObservers(const mitk::SliceNavigationController* deletedSlicer)
{
std::pair<ObserverMapType::const_iterator, ObserverMapType::const_iterator> obsRange =
m_ObserverMap.equal_range(deletedSlicer);
for (ObserverMapType::const_iterator pos = obsRange.first; pos != obsRange.second; ++pos)
{
pos->second.controller->RemoveObserver(pos->second.observerTag);
}
m_ObserverMap.erase(deletedSlicer);
}
void QmitkDicomInspectorView::RemoveAllObservers(mitk::IRenderWindowPart* deletedPart)
{
for (ObserverMapType::const_iterator pos = m_ObserverMap.begin(); pos != m_ObserverMap.end();)
{
ObserverMapType::const_iterator delPos = pos++;
if (nullptr == deletedPart || deletedPart == delPos->second.renderWindowPart)
{
delPos->second.controller->RemoveObserver(delPos->second.observerTag);
m_ObserverMap.erase(delPos);
}
}
}
void QmitkDicomInspectorView::OnCurrentSelectionChanged(QList<mitk::DataNode::Pointer> nodes)
{
if (nodes.empty() || nodes.front().IsNull())
{
m_SelectedNode = nullptr;
m_SelectedData = nullptr;
UpdateData();
return;
}
if (nodes.front() != this->m_SelectedNode)
{
// node is selected, create DICOM tag table
m_SelectedNode = nodes.front();
m_SelectedData = this->m_SelectedNode->GetData();
m_SelectedNodeTime.Modified();
UpdateData();
OnSliceChangedDelayed();
}
}
void QmitkDicomInspectorView::OnSliceChanged()
{
// Since there are always 3 events arriving (one for each render window) every time the slice
// or time changes, the slot OnSliceChangedDelayed is triggered - and only if it hasn't been
// triggered yet - so it is only executed once for every slice/time change.
if (!m_PendingSliceChangedEvent)
{
m_PendingSliceChangedEvent = true;
QTimer::singleShot(0, this, SLOT(OnSliceChangedDelayed()));
}
}
void QmitkDicomInspectorView::OnSliceNavigationControllerDeleted(const itk::Object* sender, const itk::EventObject& /*e*/)
{
auto sendingSlicer = dynamic_cast<const mitk::SliceNavigationController*>(sender);
this->RemoveObservers(sendingSlicer);
}
void QmitkDicomInspectorView::ValidateAndSetCurrentPosition()
{
- auto* renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN);
- auto currentSelectedPosition = renderWindowPart->GetSelectedPosition(nullptr);
- const auto currentSelectedTimePoint = renderWindowPart->GetSelectedTimePoint();
+ const auto currentSelectedPosition = m_RenderWindowPart->GetSelectedPosition();
+ const auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ const mitk::TimeStepType currentSelectedTimePoint = timeNavigationController->GetSelectedTimePoint();
if (m_SelectedPosition != currentSelectedPosition
|| m_SelectedTimePoint != currentSelectedTimePoint
|| m_SelectedNodeTime > m_CurrentPositionTime)
{
// the current position has been changed, the selected node has been changed since
// the last position validation or the current time position has been changed -> check position
m_SelectedPosition = currentSelectedPosition;
m_SelectedTimePoint = currentSelectedTimePoint;
m_CurrentPositionTime.Modified();
m_ValidSelectedPosition = false;
if (m_SelectedData.IsNull())
{
return;
}
mitk::BaseGeometry::Pointer geometry = m_SelectedData->GetTimeGeometry()->GetGeometryForTimePoint(m_SelectedTimePoint);
// check for invalid time step
if (geometry.IsNull())
{
geometry = m_SelectedData->GetTimeGeometry()->GetGeometryForTimeStep(0);
}
if (geometry.IsNull())
{
return;
}
m_ValidSelectedPosition = geometry->IsInside(m_SelectedPosition);
itk::Index<3> index;
geometry->WorldToIndex(m_SelectedPosition, index);
m_CurrentSelectedZSlice = index[2];
}
}
void QmitkDicomInspectorView::OnSliceChangedDelayed()
{
m_PendingSliceChangedEvent = false;
ValidateAndSetCurrentPosition();
m_Controls.tableTags->setEnabled(m_ValidSelectedPosition);
if (m_SelectedNode.IsNotNull())
{
RenderTable();
}
}
+void QmitkDicomInspectorView::OnTimeChanged()
+{
+ ValidateAndSetCurrentPosition();
+
+ m_Controls.tableTags->setEnabled(m_ValidSelectedPosition);
+
+ if (m_SelectedNode.IsNotNull())
+ {
+ RenderTable();
+ }
+}
+
void QmitkDicomInspectorView::RenderTable()
{
assert(nullptr != m_RenderWindowPart);
const auto timeStep = (m_SelectedData.IsNull()) ? 0 : m_SelectedData->GetTimeGeometry()->TimePointToTimeStep(m_SelectedTimePoint);
unsigned int rowIndex = 0;
for (const auto& element : m_Tags)
{
QTableWidgetItem* newItem = new QTableWidgetItem(QString::fromStdString(
element.second.prop->GetValue(timeStep, m_CurrentSelectedZSlice, true, true)));
m_Controls.tableTags->setItem(rowIndex, 3, newItem);
++rowIndex;
}
UpdateLabels();
}
void QmitkDicomInspectorView::UpdateData()
{
QStringList headers;
m_Controls.tableTags->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
m_Tags.clear();
if (m_SelectedData.IsNotNull())
{
for (const auto& element : *(m_SelectedData->GetPropertyList()->GetMap()))
{
if (element.first.find("DICOM") == 0)
{
std::istringstream stream(element.first);
std::string token;
std::getline(stream, token, '.'); //drop the DICOM suffix
std::getline(stream, token, '.'); //group id
unsigned long dcmgroup = std::stoul(token, nullptr, 16);
std::getline(stream, token, '.'); //element id
unsigned long dcmelement = std::stoul(token, nullptr, 16);
TagInfo info(mitk::DICOMTag(dcmgroup, dcmelement), dynamic_cast<const mitk::DICOMProperty*>(element.second.GetPointer()));
m_Tags.insert(std::make_pair(element.first, info));
}
}
}
m_Controls.tableTags->setRowCount(m_Tags.size());
unsigned int rowIndex = 0;
for (const auto& element : m_Tags)
{
QTableWidgetItem* newItem = new QTableWidgetItem(QString::number(element.second.tag.GetGroup(), 16));
m_Controls.tableTags->setItem(rowIndex, 0, newItem);
newItem = new QTableWidgetItem(QString::number(element.second.tag.GetElement(), 16));
m_Controls.tableTags->setItem(rowIndex, 1, newItem);
newItem = new QTableWidgetItem(QString::fromStdString(element.second.tag.GetName()));
m_Controls.tableTags->setItem(rowIndex, 2, newItem);
newItem = new QTableWidgetItem(QString::fromStdString(element.second.prop->GetValue()));
m_Controls.tableTags->setItem(rowIndex, 3, newItem);
++rowIndex;
}
UpdateLabels();
}
void QmitkDicomInspectorView::UpdateLabels()
{
if (m_SelectedData.IsNull())
{
m_Controls.timePointValueLabel->setText(QString(""));
m_Controls.sliceNumberValueLabel->setText(QString(""));
}
else
{
const auto timeStep = m_SelectedData->GetTimeGeometry()->TimePointToTimeStep(m_SelectedTimePoint);
if (m_ValidSelectedPosition)
{
m_Controls.timePointValueLabel->setText(QString::number(timeStep) + QStringLiteral("(")+ QString::number(m_SelectedTimePoint/1000.) + QStringLiteral(" [s])"));
m_Controls.sliceNumberValueLabel->setText(QString::number(m_CurrentSelectedZSlice));
}
else
{
m_Controls.timePointValueLabel->setText(QString("outside data geometry"));
m_Controls.sliceNumberValueLabel->setText(QString("outside data geometry"));
}
}
}
void QmitkDicomInspectorView::SetAsSelectionListener(bool checked)
{
if (checked)
{
m_SelectionServiceConnector->AddPostSelectionListener(GetSite()->GetWorkbenchWindow()->GetSelectionService());
connect(m_SelectionServiceConnector.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged,
m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection);
}
else
{
m_SelectionServiceConnector->RemovePostSelectionListener();
disconnect(m_SelectionServiceConnector.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged,
m_Controls.singleSlot, &QmitkSingleNodeSelectionWidget::SetCurrentSelection);
}
}
diff --git a/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.h b/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.h
index 5bc3e4aba2..b26f77fd27 100644
--- a/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.h
+++ b/Plugins/org.mitk.gui.qt.dicominspector/src/internal/QmitkDicomInspectorView.h
@@ -1,155 +1,155 @@
/*============================================================================
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 QmitkDicomInspectorView_h
#define QmitkDicomInspectorView_h
#include "ui_QmitkDicomInspectorViewControls.h"
// Blueberry
#include <berryIPartListener.h>
// mitk DICOM module
#include <mitkDICOMTag.h>
#include <mitkDICOMProperty.h>
// mitk gui common plugin
#include <mitkIRenderWindowPartListener.h>
// mitk gui qt common plugin
#include <QmitkAbstractView.h>
#include <QmitkSelectionServiceConnector.h>
/**
* @brief View class to inspect all DICOM tags available for the data of a node.
*/
class QmitkDicomInspectorView : public QmitkAbstractView, public mitk::IRenderWindowPartListener
{
Q_OBJECT
public:
QmitkDicomInspectorView();
~QmitkDicomInspectorView() override;
static const std::string VIEW_ID;
void SetFocus() override { };
void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) override;
void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) override;
protected:
void CreateQtPartControl(QWidget* parent) override;
/** @brief Initializes and sets the observers that are used to monitor changes in the selected position
or time point in order to actualize the view*/
bool InitObservers();
/** @brief Removes all observers of the specific deleted slice navigation controller.*/
void RemoveObservers(const mitk::SliceNavigationController* deletedSlicer);
/** @brief Removes all observers of the deletedPart. If null pointer is passed all observers will be removed.*/
void RemoveAllObservers(mitk::IRenderWindowPart* deletedPart = nullptr);
/** @brief Called by the selection widget when the selection has changed.*/
void OnCurrentSelectionChanged(QList<mitk::DataNode::Pointer> nodes);
/** @brief Calls OnSliceChangedDelayed so the event isn't triggered multiple times.*/
void OnSliceChanged();
+ void OnTimeChanged();
void OnSliceNavigationControllerDeleted(const itk::Object* sender, const itk::EventObject& /*e*/);
/** @brief Sets m_currentSelectedPosition to the current selection and validates if this position is valid
* for the input image of the currently selected fit. If it is valid, m_validSelectedPosition is set to true.
* If the fit, his input image or geometry is not specified, it will also handled as invalid.*/
void ValidateAndSetCurrentPosition();
private Q_SLOTS:
/** @brief Updates the current slice and time is correctly displayed.*/
void OnSliceChangedDelayed();
private:
void RenderTable();
/** (Re-)initializes the headers of the data table.*/
void UpdateData();
void UpdateLabels();
void SetAsSelectionListener(bool checked);
Ui::QmitkDicomInspectorViewControls m_Controls;
mitk::IRenderWindowPart* m_RenderWindowPart;
std::unique_ptr<QmitkSelectionServiceConnector> m_SelectionServiceConnector;
/** Needed for observing the events for when a slice or time step is changed.*/
bool m_PendingSliceChangedEvent;
/** Helper structure to manage the registered observer events.*/
struct ObserverInfo
{
mitk::SliceNavigationController* controller;
int observerTag;
- std::string renderWindowName;
mitk::IRenderWindowPart* renderWindowPart;
- ObserverInfo(mitk::SliceNavigationController* controller, int observerTag,
- const std::string& renderWindowName, mitk::IRenderWindowPart* part);
+ ObserverInfo(mitk::SliceNavigationController* controller, int observerTag, mitk::IRenderWindowPart* part);
};
typedef std::multimap<const mitk::SliceNavigationController*, ObserverInfo> ObserverMapType;
ObserverMapType m_ObserverMap;
+ unsigned int m_ControllerToTimeObserverTag;
/** @brief Currently selected node for the DICOM information.*/
mitk::DataNode::ConstPointer m_SelectedNode;
/** @brief Base data of the currently selected node.*/
mitk::BaseData::ConstPointer m_SelectedData;
/** @brief Valid selected position in the inspector.*/
mitk::Point3D m_SelectedPosition;
/** @brief Indicates if the currently selected position is valid for the currently selected data.*/
bool m_ValidSelectedPosition;
mitk::TimePointType m_SelectedTimePoint;
itk::IndexValueType m_CurrentSelectedZSlice;
/*************************************/
/* Members for visualizing the model */
itk::TimeStamp m_SelectedNodeTime;
itk::TimeStamp m_CurrentPositionTime;
/**Helper structure to manage the registered observer events.*/
struct TagInfo
{
mitk::DICOMTag tag;
mitk::DICOMProperty::ConstPointer prop;
TagInfo(const mitk::DICOMTag& aTag, mitk::DICOMProperty::ConstPointer aProp)
: tag(aTag)
, prop(aProp)
{
};
};
typedef std::map<std::string, TagInfo> TagMapType;
TagMapType m_Tags;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.eventrecorder/src/internal/InteractionEventRecorder.cpp b/Plugins/org.mitk.gui.qt.eventrecorder/src/internal/InteractionEventRecorder.cpp
index 926a63b541..cfdecd38f2 100644
--- a/Plugins/org.mitk.gui.qt.eventrecorder/src/internal/InteractionEventRecorder.cpp
+++ b/Plugins/org.mitk.gui.qt.eventrecorder/src/internal/InteractionEventRecorder.cpp
@@ -1,152 +1,152 @@
/*============================================================================
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.
============================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "InteractionEventRecorder.h"
// Qt
#include <QMessageBox>
#include <QFileDialog>
// us
#include "usGetModuleContext.h"
#include "usModuleContext.h"
#include "usModuleResource.h"
#include <usModuleInitialization.h>
#include <mitkXML2EventParser.h>
#include <vtkSmartPointer.h>
#include "QmitkRenderWindow.h"
US_INITIALIZE_MODULE
const std::string InteractionEventRecorder::VIEW_ID = "org.mitk.views.interactioneventrecorder";
void InteractionEventRecorder::SetFocus()
{
m_Controls.textFileName->setFocus();
}
void InteractionEventRecorder::StartRecording()
{
MITK_INFO << "Start Recording";
MITK_INFO << "Performing Reinit";
mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage());
m_CurrentObserver->SetOutputFile(m_Controls.textFileName->text().toStdString());
m_CurrentObserver->StartRecording();
}
void InteractionEventRecorder::StopRecording()
{
MITK_INFO << "Stop Recording";
m_CurrentObserver->StopRecording();
}
void InteractionEventRecorder::Play()
{
std::ifstream xmlStream(m_Controls.textFileName->text().toStdString().c_str());
mitk::XML2EventParser parser(xmlStream);
mitk::XML2EventParser::EventContainerType events = parser.GetInteractions();
MITK_INFO << "parsed events";
for (std::size_t i=0; i < events.size(); ++i)
events.at(i)->GetSender()->GetDispatcher()->ProcessEvent(events.at(i));
MITK_INFO << "DONE";
}
void InteractionEventRecorder::OpenFile()
{
QString fn = QFileDialog::getOpenFileName(nullptr, "Open File...",
QString(), "All Files (*)");
if (!fn.isEmpty())
this->m_Controls.textFileName->setText(fn);
}
void InteractionEventRecorder::RotatePlanes()
{
mitk::Point3D center;
center.Fill(0);
mitk::Vector3D firstVec;
mitk::Vector3D secondVec;
firstVec[0] = 1.0;
firstVec[1] = .5;
firstVec[2] = .25;
secondVec[0] = 1;
secondVec[1] = .25;
secondVec[2] = 1;
// Rotate Planes to a predefined state which can later be used again in tests
auto* axialRenderWindow = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow("axial");
axialRenderWindow->GetSliceNavigationController()->ReorientSlices( center, firstVec,secondVec );
axialRenderWindow->GetRenderer()->RequestUpdate();
}
void InteractionEventRecorder::RotateView()
{
// Rotate the view in 3D to a predefined state which can later be used again in tests
// this simulates a prior VTK Interaction
auto allRenderWindows = mitk::BaseRenderer::GetAll3DRenderWindows();
for (auto mapit = allRenderWindows.begin(); mapit != allRenderWindows.end(); ++mapit)
{
vtkRenderWindow* renderWindow = mapit->first;
if (renderWindow == nullptr)
continue;
- mitk::Stepper* stepper = mapit->second->GetCameraRotationController()->GetSlice();
+ mitk::Stepper* stepper = mapit->second->GetCameraRotationController()->GetStepper();
if (stepper == nullptr)
return;
unsigned int newPos = 17;
stepper->SetPos(newPos);
}
}
void InteractionEventRecorder::CreateQtPartControl( QWidget *parent )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls.setupUi( parent );
connect( m_Controls.btnStopRecording, SIGNAL(clicked()), this, SLOT(StopRecording()) );
connect( m_Controls.btnStartRecording, SIGNAL(clicked()), this, SLOT(StartRecording()) );
connect( m_Controls.btnPlay, SIGNAL(clicked()), this, SLOT(Play()) );
connect( m_Controls.btnOpenFile, SIGNAL(clicked()), this, SLOT(OpenFile()) );
connect( m_Controls.rotatePlanes, SIGNAL(clicked()), this, SLOT(RotatePlanes()) );
connect( m_Controls.rotate3D, SIGNAL(clicked()), this, SLOT(RotateView()) );
m_CurrentObserver = new mitk::EventRecorder();
// Register as listener via micro services
us::ServiceProperties props;
props["name"] = std::string("EventRecorder");
m_ServiceRegistration = us::GetModuleContext()->RegisterService<mitk::InteractionEventObserver>(m_CurrentObserver,props);
/*
delete m_CurrentObserverDEBUG;
m_ServiceRegistrationDEBUG.Unregister();
*/
}
diff --git a/Plugins/org.mitk.gui.qt.ext/files.cmake b/Plugins/org.mitk.gui.qt.ext/files.cmake
index 562bc5d984..d00f357e6c 100644
--- a/Plugins/org.mitk.gui.qt.ext/files.cmake
+++ b/Plugins/org.mitk.gui.qt.ext/files.cmake
@@ -1,63 +1,61 @@
set(SRC_CPP_FILES
QmitkExtActionBarAdvisor.cpp
QmitkExtWorkbenchWindowAdvisor.cpp
QmitkExtFileSaveProjectAction.cpp
QmitkOpenDicomEditorAction.cpp
QmitkOpenMxNMultiWidgetEditorAction.cpp
QmitkOpenStdMultiWidgetEditorAction.cpp
)
set(INTERNAL_CPP_FILES
QmitkAboutHandler.cpp
QmitkAppInstancesPreferencePage.cpp
QmitkExternalProgramsPreferencePage.cpp
QmitkCommonExtPlugin.cpp
- QmitkInputDevicesPrefPage.cpp
QmitkModuleView.cpp
)
set(UI_FILES
src/internal/QmitkAppInstancesPreferencePage.ui
src/internal/QmitkExternalProgramsPreferencePage.ui
)
set(MOC_H_FILES
src/QmitkExtFileSaveProjectAction.h
src/QmitkExtWorkbenchWindowAdvisor.h
src/internal/QmitkAboutHandler.h
src/internal/QmitkAppInstancesPreferencePage.h
src/internal/QmitkExternalProgramsPreferencePage.h
src/internal/QmitkCommonExtPlugin.h
src/internal/QmitkExtWorkbenchWindowAdvisorHack.h
- src/internal/QmitkInputDevicesPrefPage.h
src/internal/QmitkModuleView.h
src/QmitkOpenDicomEditorAction.h
src/QmitkOpenMxNMultiWidgetEditorAction.h
src/QmitkOpenStdMultiWidgetEditorAction.h
)
set(CACHED_RESOURCE_FILES
# list of resource files which can be used by the plug-in
# system without loading the plug-ins shared library,
# for example the icon used in the menu and tabs for the
# plug-in views in the workbench
plugin.xml
resources/ModuleView.png
)
set(QRC_FILES
# uncomment the following line if you want to use Qt resources
resources/org_mitk_gui_qt_ext.qrc
resources/org_mitk_icons.qrc
)
set(CPP_FILES )
foreach(file ${SRC_CPP_FILES})
set(CPP_FILES ${CPP_FILES} src/${file})
endforeach(file ${SRC_CPP_FILES})
foreach(file ${INTERNAL_CPP_FILES})
set(CPP_FILES ${CPP_FILES} src/internal/${file})
endforeach(file ${INTERNAL_CPP_FILES})
diff --git a/Plugins/org.mitk.gui.qt.ext/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.ext/manifest_headers.cmake
index 9a31004ed0..52edead2e7 100644
--- a/Plugins/org.mitk.gui.qt.ext/manifest_headers.cmake
+++ b/Plugins/org.mitk.gui.qt.ext/manifest_headers.cmake
@@ -1,5 +1,5 @@
set(Plugin-Name "Common Qt Ext Plugin")
set(Plugin-Version "0.1")
set(Plugin-Vendor "German Cancer Research Center (DKFZ)")
set(Plugin-ContactAddress "https://www.mitk.org")
-set(Require-Plugin org.mitk.core.ext org.mitk.gui.qt.application)
+set(Require-Plugin org.mitk.gui.qt.application)
diff --git a/Plugins/org.mitk.gui.qt.ext/plugin.xml b/Plugins/org.mitk.gui.qt.ext/plugin.xml
index ecba76ad09..a1656fa533 100644
--- a/Plugins/org.mitk.gui.qt.ext/plugin.xml
+++ b/Plugins/org.mitk.gui.qt.ext/plugin.xml
@@ -1,42 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<extension point="org.blueberry.ui.preferencePages">
- <page id="org.mitk.InputDevicesPreferencePage" name="Input Devices" class="QmitkInputDevicesPrefPage">
- <keywordreference id="org.mitk.InputDevicesPreferencePageKeywords"/>
- </page>
<page id="org.mitk.AppInstancesPreferencePage" name="Application Instances"
class="QmitkAppInstancesPreferencePage" category="org.mitk.GeneralPreferencePage">
<keywordreference id="org.mitk.AppInstancesPreferencePageKeywords"/>
</page>
<page id="org.mitk.ExternalProgramsPreferencePage" name="External Programs"
class="QmitkExternalProgramsPreferencePage" >
<keywordreference id="org.mitk.ExternalProgramsPreferencePageKeywords"/>
</page>
</extension>
<extension point="org.blueberry.ui.keywords">
<keyword id="org.mitk.ExternalProgramsPreferencePageKeywords" label="External program gnuplot ffmpeg libav"/>
- <keyword id="org.mitk.InputDevicesPreferencePageKeywords" label="3D mouse"/>
- <keyword id="org.mitk.InputDevicesPreferencePageKeywords" label="WiiMote"/>
- <keyword id="org.mitk.InputDevicesPreferencePageKeywords" label="Input Devices"/>
<keyword id="org.mitk.AppInstancesPreferencePageKeywords" label="application instances running multiple behavior repeated invocations mitk"/>
<keyword id="org.mitk.AppInstancesPreferencePageKeywords" label="scene file .mitk"/>
</extension>
<extension point="org.blueberry.ui.views">
<view
id="org.mitk.views.modules"
name="Modules"
category="org.mitk.views.general"
class="QmitkModuleView"
icon="resources/ModuleView.png" />
</extension>
<extension point="org.blueberry.ui.handlers">
<handler
commandId="org.blueberry.ui.help.aboutAction"
class="QmitkAboutHandler"/>
</extension>
</plugin>
diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp
index baf901c607..7e85faa6f1 100644
--- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp
+++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp
@@ -1,239 +1,237 @@
/*============================================================================
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 "QmitkCommonExtPlugin.h"
#include <QtWidgetsExtRegisterClasses.h>
#include "QmitkAboutHandler.h"
#include "QmitkAppInstancesPreferencePage.h"
#include "QmitkExternalProgramsPreferencePage.h"
-#include "QmitkInputDevicesPrefPage.h"
#include "QmitkModuleView.h"
#include <mitkIDataStorageService.h>
#include <mitkSceneIO.h>
#include <mitkProgressBar.h>
#include <mitkRenderingManager.h>
#include <mitkIOUtil.h>
#include <mitkCoreServices.h>
#include <mitkIPreferencesService.h>
#include <mitkIPreferences.h>
#include <mitkBaseApplication.h>
#include <berryPlatformUI.h>
#include <berryPlatform.h>
#include <Poco/Util/OptionProcessor.h>
#include <QProcess>
#include <QMainWindow>
#include <usModuleInitialization.h>
US_INITIALIZE_MODULE
ctkPluginContext* QmitkCommonExtPlugin::_context = nullptr;
void QmitkCommonExtPlugin::start(ctkPluginContext* context)
{
this->_context = context;
QtWidgetsExtRegisterClasses();
BERRY_REGISTER_EXTENSION_CLASS(QmitkAboutHandler, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkAppInstancesPreferencePage, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkExternalProgramsPreferencePage, context)
- BERRY_REGISTER_EXTENSION_CLASS(QmitkInputDevicesPrefPage, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkModuleView, context)
if (qApp->metaObject()->indexOfSignal("messageReceived(QByteArray)") > -1)
{
connect(qApp, SIGNAL(messageReceived(QByteArray)), this, SLOT(handleIPCMessage(QByteArray)));
}
// This is a potentially long running operation.
loadDataFromDisk(berry::Platform::GetApplicationArgs(), true);
}
void QmitkCommonExtPlugin::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
this->_context = nullptr;
}
ctkPluginContext* QmitkCommonExtPlugin::getContext()
{
return _context;
}
void QmitkCommonExtPlugin::loadDataFromDisk(const QStringList &arguments, bool globalReinit)
{
if (!arguments.empty())
{
ctkServiceReference serviceRef = _context->getServiceReference<mitk::IDataStorageService>();
if (serviceRef)
{
mitk::IDataStorageService* dataStorageService = _context->getService<mitk::IDataStorageService>(serviceRef);
mitk::DataStorage::Pointer dataStorage = dataStorageService->GetDefaultDataStorage()->GetDataStorage();
int argumentsAdded = 0;
for (int i = 0; i < arguments.size(); ++i)
{
if (arguments[i].right(5) == ".mitk")
{
mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New();
bool clearDataStorageFirst(false);
mitk::ProgressBar::GetInstance()->AddStepsToDo(2);
dataStorage = sceneIO->LoadScene( arguments[i].toLocal8Bit().constData(), dataStorage, clearDataStorageFirst );
mitk::ProgressBar::GetInstance()->Progress(2);
argumentsAdded++;
}
else if (arguments[i].right(15) == ".mitksceneindex")
{
mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New();
bool clearDataStorageFirst(false);
mitk::ProgressBar::GetInstance()->AddStepsToDo(2);
dataStorage = sceneIO->LoadSceneUnzipped(arguments[i].toLocal8Bit().constData(), dataStorage, clearDataStorageFirst);
mitk::ProgressBar::GetInstance()->Progress(2);
argumentsAdded++;
}
else
{
try
{
const std::string path(arguments[i].toStdString());
auto addedNodes = mitk::IOUtil::Load(path, *dataStorage);
for (const auto& node : *addedNodes )
{
node->SetIntProperty("layer", argumentsAdded);
}
argumentsAdded++;
}
catch(...)
{
MITK_WARN << "Failed to load command line argument: " << arguments[i].toStdString();
}
}
} // end for each command line argument
if (argumentsAdded > 0 && globalReinit)
{
// calculate bounding geometry
mitk::RenderingManager::GetInstance()->InitializeViews(dataStorage->ComputeBoundingGeometry3D());
}
}
else
{
MITK_ERROR << "A service reference for mitk::IDataStorageService does not exist";
}
}
}
void QmitkCommonExtPlugin::startNewInstance(const QStringList &args, const QStringList& files)
{
QStringList newArgs(args);
#ifdef Q_OS_UNIX
newArgs << QString("--") + mitk::BaseApplication::ARG_NEWINSTANCE;
#else
newArgs << QString("/") + mitk::BaseApplication::ARG_NEWINSTANCE;
#endif
newArgs << files;
QProcess::startDetached(qApp->applicationFilePath(), newArgs);
}
void QmitkCommonExtPlugin::handleIPCMessage(const QByteArray& msg)
{
QDataStream ds(msg);
QString msgType;
ds >> msgType;
// we only handle messages containing command line arguments
if (msgType != "$cmdLineArgs") return;
// activate the current workbench window
berry::IWorkbenchWindow::Pointer window =
berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow();
QMainWindow* mainWindow =
static_cast<QMainWindow*> (window->GetShell()->GetControl());
mainWindow->setWindowState(mainWindow->windowState() & ~Qt::WindowMinimized);
mainWindow->raise();
mainWindow->activateWindow();
// Get the preferences for the instantiation behavior
auto* prefService = mitk::CoreServices::GetPreferencesService();
auto* prefs = prefService->GetSystemPreferences()->Node("/General");
bool newInstanceAlways = prefs->GetBool("newInstance.always", false);
bool newInstanceScene = prefs->GetBool("newInstance.scene", true);
QStringList args;
ds >> args;
QStringList fileArgs;
QStringList sceneArgs;
foreach (QString arg, args)
{
if (arg.endsWith(".mitk"))
{
sceneArgs << arg;
}
else
{
fileArgs << arg;
}
}
if (newInstanceAlways)
{
if (newInstanceScene)
{
startNewInstance(args, fileArgs);
foreach(QString sceneFile, sceneArgs)
{
startNewInstance(args, QStringList(sceneFile));
}
}
else
{
fileArgs.append(sceneArgs);
startNewInstance(args, fileArgs);
}
}
else
{
loadDataFromDisk(fileArgs, false);
if (newInstanceScene)
{
foreach(QString sceneFile, sceneArgs)
{
startNewInstance(args, QStringList(sceneFile));
}
}
else
{
loadDataFromDisk(sceneArgs, false);
}
}
}
diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkInputDevicesPrefPage.cpp b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkInputDevicesPrefPage.cpp
deleted file mode 100644
index ad4632cd6a..0000000000
--- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkInputDevicesPrefPage.cpp
+++ /dev/null
@@ -1,186 +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 "QmitkInputDevicesPrefPage.h"
-
-#include <mitkCoreServices.h>
-#include <mitkIPreferencesService.h>
-#include <mitkIPreferences.h>
-
-#include <QLabel>
-#include <QPushButton>
-#include <QFormLayout>
-#include <QCheckBox>
-#include <QHashIterator>
-#include <QMessageBox>
-
-#include <mitkIInputDeviceRegistry.h>
-#include <mitkIInputDeviceDescriptor.h>
-#include <mitkCoreExtConstants.h>
-
-#include "QmitkCommonExtPlugin.h"
-
-namespace
-{
- mitk::IPreferences* GetPreferences()
- {
- auto* preferencesService = mitk::CoreServices::GetPreferencesService();
- return preferencesService->GetSystemPreferences()->Node(mitk::CoreExtConstants::INPUTDEVICE_PREFERENCES.toStdString());
- }
-}
-
-QmitkInputDevicesPrefPage::QmitkInputDevicesPrefPage()
-: m_MainControl(nullptr)
-{
-}
-
-void QmitkInputDevicesPrefPage::Init(berry::IWorkbench::Pointer )
-{
-}
-
-void QmitkInputDevicesPrefPage::CreateQtControl(QWidget* parent)
-{
- m_MainControl = new QWidget(parent);
- auto layout = new QVBoxLayout;
-
- QList<mitk::IInputDeviceDescriptor::Pointer> temp(GetInputDeviceRegistry()->GetInputDevices());
-
- for(QList<mitk::IInputDeviceDescriptor::Pointer>::const_iterator it = temp.begin(); it != temp.end();++it)
- {
- QString inputDeviceName((*it)->GetName());
- auto checkBox = new QCheckBox((inputDeviceName),m_MainControl);
- layout->addWidget(checkBox);
- m_InputDevices.insert(checkBox,(*it)->GetID());
-
- if(inputDeviceName == "WiiMote")
- {
- m_WiiMoteModes = new QGroupBox("WiiMote Modus");
-
- m_WiiMoteHeadTracking = new QRadioButton(mitk::CoreExtConstants::WIIMOTE_HEADTRACKING);
- m_WiiMoteSurfaceInteraction = new QRadioButton(mitk::CoreExtConstants::WIIMOTE_SURFACEINTERACTION);
- m_WiiMoteHeadTracking->setChecked(true);
-
- auto vBoxLayout = new QVBoxLayout;
-
- vBoxLayout->addWidget(m_WiiMoteHeadTracking);
- vBoxLayout->addWidget(m_WiiMoteSurfaceInteraction);
-
- m_WiiMoteModes->setLayout(vBoxLayout);
-
- layout->addWidget(m_WiiMoteModes);
- }
-
- }
-
- layout->addStretch();
- m_MainControl->setLayout(layout);
- this->Update();
-}
-
-QWidget* QmitkInputDevicesPrefPage::GetQtControl() const
-{
- return m_MainControl;
-}
-
-bool QmitkInputDevicesPrefPage::PerformOk()
-{
- auto* prefs = GetPreferences();
- bool result = true;
-
- mitk::IInputDeviceRegistry* inputDeviceRegistry = GetInputDeviceRegistry();
-
- QHashIterator<QCheckBox*, QString> it(m_InputDevices);
- while (it.hasNext())
- {
- it.next();
- mitk::IInputDeviceDescriptor::Pointer inputdevice(inputDeviceRegistry->Find(it.value()));
-
- if(it.value() == mitk::CoreExtConstants::WIIMOTE_XMLATTRIBUTE_NAME)
- {
- const auto headTracking(m_WiiMoteHeadTracking->text().toStdString());
- const auto surfaceInteraction(m_WiiMoteSurfaceInteraction->text().toStdString());
-
- prefs->PutBool(headTracking, m_WiiMoteHeadTracking->isChecked());
- prefs->PutBool(surfaceInteraction, m_WiiMoteSurfaceInteraction->isChecked());
-
- // forced flush of the preferences is needed
- // because otherwise the mitk::WiiMoteActivator class
- // cannot distinguish the two different modes without
- // changing the interface for all input devices
- prefs->Flush();
- }
-
- if(it.key()->isChecked())
- {
- result &= inputdevice->CreateInputDevice()->RegisterInputDevice();
- }
- else
- {
- result &= inputdevice->CreateInputDevice()->UnRegisterInputDevice();
-
- // temporary fix, unclean solution:
- // e.g. user activates SpaceNavigator and leaves the
- // the wiimote deactivated, the user will get the warning
- // despite the fact that it has never been activated
- if(it.value() == mitk::CoreExtConstants::WIIMOTE_XMLATTRIBUTE_NAME)
- {
- // until now 2010-09-06 there were some unfixed problems
- // with reconnecting the wiimote after disconnecting it.
- // It was suggested that it might have something to do
- // with the type of stack, that is used for the pairing.
- // MS-Stack for example does not work properly.
- QMessageBox::information(nullptr,"WiiMote supportproblem",
- "A reconnect of the WiiMote is not yet supported! "
- "Please restart the application, if you want to "
- "activate the Wii remote/s again.");
- }
- }
-
- if(result)
- {
- prefs->PutBool(it.value().toStdString(), it.key()->isChecked());
- }
- }
- return result;
-}
-
-void QmitkInputDevicesPrefPage::PerformCancel()
-{
-
-}
-
-void QmitkInputDevicesPrefPage::Update()
-{
- auto* prefs = GetPreferences();
- QHashIterator<QCheckBox*, QString> it(m_InputDevices);
-
- while (it.hasNext())
- {
- it.next();
- it.key()->setChecked(prefs->GetBool(it.value().toStdString(), false));
- if(it.value() == mitk::CoreExtConstants::WIIMOTE_XMLATTRIBUTE_NAME)
- {
- m_WiiMoteHeadTracking->setChecked(
- prefs->GetBool(mitk::CoreExtConstants::WIIMOTE_HEADTRACKING.toStdString(), false));
- m_WiiMoteSurfaceInteraction->setChecked
- (prefs->GetBool(mitk::CoreExtConstants::WIIMOTE_SURFACEINTERACTION.toStdString(), false));
- }
- }
-}
-
-mitk::IInputDeviceRegistry *QmitkInputDevicesPrefPage::GetInputDeviceRegistry() const
-{
- ctkServiceReference serviceRef = QmitkCommonExtPlugin::getContext()->getServiceReference<mitk::IInputDeviceRegistry>();
- if (!serviceRef) return nullptr;
-
- return QmitkCommonExtPlugin::getContext()->getService<mitk::IInputDeviceRegistry>(serviceRef);
-}
diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkInputDevicesPrefPage.h b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkInputDevicesPrefPage.h
deleted file mode 100644
index 0f1b91d115..0000000000
--- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkInputDevicesPrefPage.h
+++ /dev/null
@@ -1,87 +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.
-
-============================================================================*/
-
-
-#ifndef QmitkInputDevicesPrefPage_h
-#define QmitkInputDevicesPrefPage_h
-
-#include "berryIQtPreferencePage.h"
-
-#include <QHash>
-#include <QGroupBox>
-#include <QRadioButton>
-
-class QWidget;
-class QCheckBox;
-
-namespace mitk {
-struct IInputDeviceRegistry;
-}
-
-class QmitkInputDevicesPrefPage : public QObject, public berry::IQtPreferencePage
-{
- Q_OBJECT
- Q_INTERFACES(berry::IPreferencePage)
-
-public:
-
- /**
- * Default constructor
- */
- QmitkInputDevicesPrefPage();
-
- /**
- * @see berry::IPreferencePage::Init(berry::IWorkbench::Pointer workbench)
- */
- void Init(berry::IWorkbench::Pointer workbench) override;
-
- /**
- * @see berry::IPreferencePage::CreateQtControl(void* parent)
- */
- void CreateQtControl(QWidget* widget) override;
-
- /**
- * @see berry::IPreferencePage::CreateQtControl()
- */
- QWidget* GetQtControl() const override;
-
- /**
- * @see berry::IPreferencePage::PerformOk()
- */
- bool PerformOk() override;
-
- /**
- * @see berry::IPreferencePage::PerformCancel()
- */
- void PerformCancel() override;
-
- /**
- * @see berry::IPreferencePage::Update()
- */
- void Update() override;
-
-protected:
-
- QWidget* m_MainControl;
-
- QHash<QCheckBox*,QString> m_InputDevices;
-
- // specific for Wiimote
- QGroupBox* m_WiiMoteModes;
- QRadioButton* m_WiiMoteHeadTracking;
- QRadioButton* m_WiiMoteSurfaceInteraction;
-
- mitk::IInputDeviceRegistry* GetInputDeviceRegistry() const;
-
-};
-
-#endif
diff --git a/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkExtApplicationPlugin.cpp b/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkExtApplicationPlugin.cpp
index 90740e0e6d..974dcb3ad5 100644
--- a/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkExtApplicationPlugin.cpp
+++ b/Plugins/org.mitk.gui.qt.extapplication/src/internal/QmitkExtApplicationPlugin.cpp
@@ -1,81 +1,81 @@
/*============================================================================
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 "QmitkExtApplicationPlugin.h"
#include "perspectives/QmitkExtDefaultPerspective.h"
#include "perspectives/QmitkEditorPerspective.h"
#include "perspectives/QmitkVisualizationPerspective.h"
#include "QmitkExtApplication.h"
#include <mitkVersion.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <service/cm/ctkConfigurationAdmin.h>
#include <service/cm/ctkConfiguration.h>
#include <QFileInfo>
#include <QDateTime>
QmitkExtApplicationPlugin* QmitkExtApplicationPlugin::inst = nullptr;
QmitkExtApplicationPlugin::QmitkExtApplicationPlugin()
{
inst = this;
}
QmitkExtApplicationPlugin::~QmitkExtApplicationPlugin()
{
}
QmitkExtApplicationPlugin* QmitkExtApplicationPlugin::GetDefault()
{
return inst;
}
void QmitkExtApplicationPlugin::start(ctkPluginContext* context)
{
berry::AbstractUICTKPlugin::start(context);
this->context = context;
BERRY_REGISTER_EXTENSION_CLASS(QmitkExtDefaultPerspective, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkEditorPerspective, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkExtApplication, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkVisualizationPerspective, context);
ctkServiceReference cmRef = context->getServiceReference<ctkConfigurationAdmin>();
ctkConfigurationAdmin* configAdmin = nullptr;
if (cmRef)
{
configAdmin = context->getService<ctkConfigurationAdmin>(cmRef);
}
// Use the CTK Configuration Admin service to configure the BlueBerry help system
if (configAdmin)
{
ctkConfigurationPtr conf = configAdmin->getConfiguration("org.blueberry.services.help", QString());
ctkDictionary helpProps;
helpProps.insert("homePage", "qthelp://org.mitk.gui.qt.extapplication/bundle/index.html");
conf->update(helpProps);
context->ungetService(cmRef);
}
else
{
MITK_WARN << "Configuration Admin service unavailable, cannot set home page url.";
}
}
ctkPluginContext* QmitkExtApplicationPlugin::GetPluginContext() const
{
return context;
}
diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp
index 44a8d83a62..b22c7e827b 100644
--- a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp
+++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp
@@ -1,639 +1,680 @@
/*============================================================================
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 "GenericDataFittingView.h"
#include "mitkWorkbenchUtil.h"
#include <mitkLinearModelFactory.h>
#include <mitkLinearModelParameterizer.h>
#include <mitkGenericParamModelFactory.h>
#include <mitkGenericParamModelParameterizer.h>
#include <mitkT2DecayModelFactory.h>
#include <mitkT2DecayModelParameterizer.h>
-
+#include <mitkExponentialSaturationModel.h>
+#include <mitkExponentialSaturationModelFactory.h>
+#include <mitkExponentialSaturationModelParameterizer.h>
#include <mitkValueBasedParameterizationDelegate.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateOr.h>
#include <mitkPixelBasedParameterFitImageGenerator.h>
#include <mitkROIBasedParameterFitImageGenerator.h>
#include <mitkLevenbergMarquardtModelFitFunctor.h>
#include <mitkSumOfSquaredDifferencesFitCostFunction.h>
#include <mitkNormalizedSumOfSquaredDifferencesFitCostFunction.h>
#include <mitkSimpleBarrierConstraintChecker.h>
#include <mitkModelFitResultHelper.h>
#include <mitkImageTimeSelector.h>
#include <mitkMaskedDynamicImageStatisticsGenerator.h>
#include <mitkExtractTimeGrid.h>
#include <QMessageBox>
#include <QThreadPool>
#include <QmitkDataStorageComboBox.h>
// Includes for image casting between ITK and MITK
#include <mitkImage.h>
#include "mitkImageCast.h"
#include "mitkITKImageImport.h"
#include <itkImage.h>
#include <itkImageRegionIterator.h>
#include <iostream>
const std::string GenericDataFittingView::VIEW_ID = "org.mitk.views.fit.genericfitting";
void GenericDataFittingView::SetFocus()
{
m_Controls.btnModelling->setFocus();
}
void GenericDataFittingView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_Controls.btnModelling->setEnabled(false);
this->InitModelComboBox();
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()));
//Gerneric setting
m_Controls.groupGeneric->hide();
m_Controls.labelFormulaInfo->hide();
connect(m_Controls.editFormula, SIGNAL(textChanged(const QString&)), this,
SLOT(UpdateGUIControls()));
connect(m_Controls.checkFormulaInfo, SIGNAL(toggled(bool)), m_Controls.labelFormulaInfo,
SLOT(setVisible(bool)));
connect(m_Controls.nrOfParams, SIGNAL(valueChanged(int)), this, SLOT(OnNrOfParamsChanged()));
//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.initialValuesManager, SIGNAL(initialValuesChanged(void)), this, SLOT(UpdateGUIControls()));
- 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.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)));
UpdateGUIControls();
}
void GenericDataFittingView::UpdateGUIControls()
{
m_Controls.lineFitName->setPlaceholderText(QString::fromStdString(this->GetDefaultFitName()));
m_Controls.lineFitName->setEnabled(!m_FittingInProgress);
m_Controls.checkBox_Constraints->setEnabled(m_modelConstraints.IsNotNull());
bool isGenericFactory = dynamic_cast<mitk::GenericParamModelFactory*>
(m_selectedModelFactory.GetPointer()) != nullptr;
m_Controls.groupGeneric->setVisible(isGenericFactory);
m_Controls.groupBox_FitConfiguration->setVisible(m_selectedModelFactory);
m_Controls.groupBox->setEnabled(!m_FittingInProgress);
m_Controls.comboModel->setEnabled(!m_FittingInProgress);
m_Controls.groupGeneric->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());
}
std::string GenericDataFittingView::GetFitName() const
{
std::string fitName = m_Controls.lineFitName->text().toStdString();
if (fitName.empty())
{
fitName = m_Controls.lineFitName->placeholderText().toStdString();
}
return fitName;
}
std::string GenericDataFittingView::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 GenericDataFittingView::OnNrOfParamsChanged()
{
PrepareFitConfiguration();
UpdateGUIControls();
}
void GenericDataFittingView::OnModellSet(int index)
{
m_selectedModelFactory = nullptr;
if (index > 0)
{
if (static_cast<ModelFactoryStackType::size_type>(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<mitk::SimpleBarrierConstraintChecker*>
+ (m_selectedModelFactory->CreateDefaultConstraints().GetPointer());
+
+ m_Controls.initialValuesManager->setInitialValues(m_selectedModelFactory->GetParameterNames(),
+ m_selectedModelFactory->GetDefaultInitialParameterization());
+
+ m_Controls.constraintManager->setChecker(this->m_modelConstraints,
+ this->m_selectedModelFactory->GetParameterNames());
+
+ }
+
UpdateGUIControls();
}
bool GenericDataFittingView::IsGenericParamFactorySelected() const
{
return dynamic_cast<mitk::GenericParamModelFactory*>
(m_selectedModelFactory.GetPointer()) != nullptr;
}
void GenericDataFittingView::PrepareFitConfiguration()
{
if (m_selectedModelFactory)
{
mitk::ModelBase::ParameterNamesType paramNames = m_selectedModelFactory->GetParameterNames();
unsigned int nrOfPools = this->m_Controls.nrOfParams->value();
//init values
if (this->IsGenericParamFactorySelected())
{
mitk::modelFit::ModelFitInfo::Pointer fitInfo = mitk::modelFit::ModelFitInfo::New();
fitInfo->staticParamMap.Add(mitk::GenericParamModel::NAME_STATIC_PARAMETER_number, { static_cast<double>(nrOfPools) });
auto parameterizer = m_selectedModelFactory->CreateParameterizer(fitInfo);
paramNames = parameterizer->GetParameterNames();
m_Controls.initialValuesManager->setInitialValues(paramNames, parameterizer->GetDefaultInitialParameterization());
}
else
{
m_Controls.initialValuesManager->setInitialValues(paramNames, this->m_selectedModelFactory->GetDefaultInitialParameterization());
}
//constraints
this->m_modelConstraints = dynamic_cast<mitk::SimpleBarrierConstraintChecker*>
(m_selectedModelFactory->CreateDefaultConstraints().GetPointer());
if (this->m_modelConstraints.IsNull())
{
this->m_modelConstraints = mitk::SimpleBarrierConstraintChecker::New();
}
m_Controls.constraintManager->setChecker(this->m_modelConstraints, paramNames);
}
};
void GenericDataFittingView::OnModellingButtonClicked()
{
//check if all static parameters set
if (m_selectedModelFactory.IsNotNull() && CheckModelSettings())
{
mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr;
mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr;
bool isLinearFactory = dynamic_cast<mitk::LinearModelFactory*>
(m_selectedModelFactory.GetPointer()) != nullptr;
bool isGenericFactory = dynamic_cast<mitk::GenericParamModelFactory*>
(m_selectedModelFactory.GetPointer()) != nullptr;
bool isT2DecayFactory = dynamic_cast<mitk::T2DecayModelFactory*>
(m_selectedModelFactory.GetPointer()) != nullptr;
+ bool isExponentialSaturationFactory = dynamic_cast<mitk::ExponentialSaturationModelFactory*>
+ (m_selectedModelFactory.GetPointer()) != nullptr;
+
if (isLinearFactory)
{
if (this->m_Controls.radioPixelBased->isChecked())
{
GenerateModelFit_PixelBased<mitk::LinearModelParameterizer>(fitSession, generator);
}
else
{
GenerateModelFit_ROIBased<mitk::LinearModelParameterizer>(fitSession, generator);
}
}
else if (isGenericFactory)
{
if (this->m_Controls.radioPixelBased->isChecked())
{
GenerateModelFit_PixelBased<mitk::GenericParamModelParameterizer>(fitSession, generator);
}
else
{
GenerateModelFit_ROIBased<mitk::GenericParamModelParameterizer>(fitSession, generator);
}
}
else if (isT2DecayFactory)
{
if (this->m_Controls.radioPixelBased->isChecked())
{
GenerateModelFit_PixelBased<mitk::T2DecayModelParameterizer>(fitSession, generator);
}
else
{
GenerateModelFit_ROIBased<mitk::T2DecayModelParameterizer>(fitSession, generator);
}
}
+ else if (isExponentialSaturationFactory)
+ {
+ if (this->m_Controls.radioPixelBased->isChecked())
+ {
+ GenerateModelFit_PixelBased<mitk::ExponentialSaturationModelParameterizer>(fitSession, generator);
+ }
+ else
+ {
+ GenerateModelFit_ROIBased<mitk::ExponentialSaturationModelParameterizer>(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 GenericDataFittingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/,
const QList<mitk::DataNode::Pointer>& selectedNodes)
{
m_selectedNode = nullptr;
m_selectedImage = nullptr;
m_selectedMaskNode = nullptr;
m_selectedMask = nullptr;
m_Controls.masklabel->setText("No (valid) mask selected.");
m_Controls.timeserieslabel->setText("No (valid) series selected.");
QList<mitk::DataNode::Pointer> nodes = selectedNodes;
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::NodePredicateOr::Pointer maskPredicate = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet);
if (nodes.size() > 0 && isImage->CheckNode(nodes.front()))
{
this->m_selectedNode = nodes.front();
this->m_selectedImage = dynamic_cast<mitk::Image*>(this->m_selectedNode->GetData());
m_Controls.timeserieslabel->setText((this->m_selectedNode->GetName()).c_str());
nodes.pop_front();
}
if (nodes.size() > 0 && maskPredicate->CheckNode(nodes.front()))
{
this->m_selectedMaskNode = nodes.front();
this->m_selectedMask = dynamic_cast<mitk::Image*>(this->m_selectedMaskNode->GetData());
if (this->m_selectedMask->GetTimeSteps() > 1)
{
MITK_INFO <<
"Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " <<
m_selectedMaskNode->GetName();
mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New();
maskedImageTimeSelector->SetInput(this->m_selectedMask);
maskedImageTimeSelector->SetTimeNr(0);
maskedImageTimeSelector->UpdateLargestPossibleRegion();
this->m_selectedMask = maskedImageTimeSelector->GetOutput();
}
m_Controls.masklabel->setText((this->m_selectedMaskNode->GetName()).c_str());
}
if (m_selectedMask.IsNull())
{
this->m_Controls.radioPixelBased->setChecked(true);
}
UpdateGUIControls();
}
bool GenericDataFittingView::CheckModelSettings() const
{
bool ok = true;
//check wether any model is set at all. Otherwise exit with false
if (m_selectedModelFactory.IsNotNull())
{
bool isGenericFactory = dynamic_cast<mitk::GenericParamModelFactory*>(m_selectedModelFactory.GetPointer()) != nullptr;
if (isGenericFactory)
{
ok = !m_Controls.editFormula->text().isEmpty();
}
}
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 has an invalid image setting as source.";
+ MITK_ERROR << warning;
+ m_Controls.infoBox->append(QString("<font color='red'><b>") + QString::fromStdString(warning) + QString("</b></font>"));
+
+ ok = false;
+ };
return ok;
}
void GenericDataFittingView::ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase*
parameterizer) const
{
if (m_Controls.radioButton_StartParameters->isChecked())
{
//use user defined initial parameters
mitk::ValueBasedParameterizationDelegate::Pointer paramDelegate =
mitk::ValueBasedParameterizationDelegate::New();
paramDelegate->SetInitialParameterization(m_Controls.initialValuesManager->getInitialValues());
parameterizer->SetInitialParameterizationDelegate(paramDelegate);
}
mitk::GenericParamModelParameterizer* genericParameterizer =
dynamic_cast<mitk::GenericParamModelParameterizer*>(parameterizer);
if (genericParameterizer)
{
genericParameterizer->SetFunctionString(m_Controls.editFormula->text().toStdString());
}
}
template <typename TParameterizer>
void GenericDataFittingView::GenerateModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer&
modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
{
mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
mitk::PixelBasedParameterFitImageGenerator::New();
typename TParameterizer::Pointer modelParameterizer =
TParameterizer::New();
auto genericParameterizer = dynamic_cast<mitk::GenericParamModelParameterizer*>(modelParameterizer.GetPointer());
if (genericParameterizer)
{
genericParameterizer->SetNumberOfParameters(this->m_Controls.nrOfParams->value());
}
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(this->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 <typename TParameterizer>
void GenericDataFittingView::GenerateModelFit_ROIBased(
mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo,
mitk::ParameterFitImageGeneratorBase::Pointer& generator)
{
mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
mitk::ROIBasedParameterFitImageGenerator::New();
typename TParameterizer::Pointer modelParameterizer =
TParameterizer::New();
auto genericParameterizer = dynamic_cast<mitk::GenericParamModelParameterizer*>(modelParameterizer.GetPointer());
if (genericParameterizer)
{
genericParameterizer->SetNumberOfParameters(this->m_Controls.nrOfParams->value());
}
this->ConfigureInitialParametersOfParameterizer(modelParameterizer);
//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();
//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);
}
void GenericDataFittingView::DoFit(const mitk::modelFit::ModelFitInfo* fitSession,
mitk::ParameterFitImageGeneratorBase* generator)
{
QString message = "<font color='green'>Fitting Data Set . . .</font>";
m_Controls.infoBox->append(message);
/////////////////////////
//create job and put it into the thread pool
ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(generator, fitSession, this->m_selectedNode);
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);
}
GenericDataFittingView::GenericDataFittingView() : m_FittingInProgress(false)
{
m_selectedImage = nullptr;
m_selectedMask = nullptr;
mitk::ModelFactoryBase::Pointer factory =
mitk::LinearModelFactory::New().GetPointer();
m_FactoryStack.push_back(factory);
factory = mitk::GenericParamModelFactory::New().GetPointer();
m_FactoryStack.push_back(factory);
factory = mitk::T2DecayModelFactory::New().GetPointer();
m_FactoryStack.push_back(factory);
+ factory = mitk::ExponentialSaturationModelFactory::New().GetPointer();
+ m_FactoryStack.push_back(factory);
this->m_IsNotABinaryImagePredicate = mitk::NodePredicateAnd::New(
mitk::TNodePredicateDataType<mitk::Image>::New(),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("binary",
mitk::BoolProperty::New(true))),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer();
this->m_IsBinaryImagePredicate = mitk::NodePredicateAnd::New(
mitk::TNodePredicateDataType<mitk::Image>::New(),
mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer();
}
void GenericDataFittingView::OnJobFinished()
{
this->m_Controls.infoBox->append(QString("<font color='green'>Fitting finished</font>"));
this->m_FittingInProgress = false;
this->UpdateGUIControls();
};
void GenericDataFittingView::OnJobError(QString err)
{
MITK_ERROR << err.toStdString().c_str();
m_Controls.infoBox->append(QString("<font color='red'><b>") + err + QString("</b></font>"));
};
void GenericDataFittingView::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());
};
void GenericDataFittingView::OnJobProgress(double progress)
{
QString report = QString("Progress. ") + QString::number(progress);
this->m_Controls.infoBox->append(report);
};
void GenericDataFittingView::OnJobStatusChanged(QString info)
{
this->m_Controls.infoBox->append(info);
}
void GenericDataFittingView::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::ModelFitFunctorBase::Pointer GenericDataFittingView::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.fit.inspector/src/internal/ModelFitInspectorView.cpp b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp
index 2a44448ab0..50ae633df5 100644
--- a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp
+++ b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp
@@ -1,920 +1,918 @@
/*============================================================================
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 "ModelFitInspectorView.h"
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIWorkbenchPage.h>
// mitk
#include <QmitkRenderWindow.h>
// Qt
#include <QMessageBox>
#include <QFileDialog>
#include <QTableWidget>
#include <qwt_plot_marker.h>
-#include "QmitkPlotWidget.h"
-
-#include "mitkNodePredicateFunction.h"
-#include "mitkScalarListLookupTableProperty.h"
-#include "mitkModelFitConstants.h"
-#include "mitkExtractTimeGrid.h"
-#include "mitkModelGenerator.h"
-#include "mitkModelFitException.h"
-#include "mitkModelFitParameterValueExtraction.h"
-#include "mitkTimeGridHelper.h"
-#include "mitkModelFitResultRelationRule.h"
-
-#include "mitkModelFitPlotDataHelper.h"
-
-#include "ModelFitInspectorView.h"
+#include <QmitkPlotWidget.h>
+
+#include <mitkNodePredicateFunction.h>
+#include <mitkScalarListLookupTableProperty.h>
+#include <mitkModelFitConstants.h>
+#include <mitkExtractTimeGrid.h>
+#include <mitkModelGenerator.h>
+#include <mitkModelFitException.h>
+#include <mitkModelFitParameterValueExtraction.h>
+#include <mitkModelFitResultRelationRule.h>
+#include <mitkModelFitPlotDataHelper.h>
+#include <mitkTimeGridHelper.h>
+#include <mitkTimeNavigationController.h>
const std::string ModelFitInspectorView::VIEW_ID = "org.mitk.views.fit.inspector";
const unsigned int ModelFitInspectorView::INTERPOLATION_STEPS = 10;
const std::string DEFAULT_X_AXIS = "Time [s]";
ModelFitInspectorView::ModelFitInspectorView() :
m_renderWindowPart(nullptr),
m_internalUpdateFlag(false),
m_currentFit(nullptr),
m_currentModelParameterizer(nullptr),
m_currentModelProviderService(nullptr),
m_currentSelectedTimeStep(0),
m_currentSelectedNode(nullptr)
{
m_currentSelectedPosition.Fill(0.0);
m_modelfitList.clear();
}
ModelFitInspectorView::~ModelFitInspectorView()
{
}
void ModelFitInspectorView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (m_renderWindowPart != renderWindowPart)
{
m_renderWindowPart = renderWindowPart;
}
this->m_SliceChangeListener.RenderWindowPartActivated(renderWindowPart);
}
void ModelFitInspectorView::RenderWindowPartDeactivated(
mitk::IRenderWindowPart* renderWindowPart)
{
m_renderWindowPart = nullptr;
this->m_SliceChangeListener.RenderWindowPartDeactivated(renderWindowPart);
}
void ModelFitInspectorView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
m_SelectionServiceConnector = std::make_unique<QmitkSelectionServiceConnector>();
m_SelectionServiceConnector->AddPostSelectionListener(this->GetSite()->GetWorkbenchWindow()->GetSelectionService());
m_Controls.inputNodeSelector->SetDataStorage(GetDataStorage());
m_Controls.inputNodeSelector->SetEmptyInfo(QString("Please select input data to be viewed."));
m_Controls.inputNodeSelector->SetInvalidInfo(QString("<b><font color=\"red\">No input data is selected</font></b>"));
m_Controls.inputNodeSelector->SetPopUpTitel(QString("Choose 3D+t input data that should be viewed!"));
m_Controls.inputNodeSelector->SetSelectionIsOptional(false);
m_Controls.inputNodeSelector->SetSelectOnlyVisibleNodes(true);
auto predicate = mitk::NodePredicateFunction::New([](const mitk::DataNode *node) {
bool isModelFitNode = node->GetData() && node->GetData()->GetProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str()).IsNotNull();
return isModelFitNode || (node && node->GetData() && node->GetData()->GetTimeSteps() > 1);
});
m_Controls.inputNodeSelector->SetNodePredicate(predicate);
connect(m_SelectionServiceConnector.get(), &QmitkSelectionServiceConnector::ServiceSelectionChanged, m_Controls.inputNodeSelector, &QmitkSingleNodeSelectionWidget::SetCurrentSelection);
connect(m_Controls.inputNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &ModelFitInspectorView::OnInputChanged);
this->m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
connect(m_Controls.cmbFit, SIGNAL(currentIndexChanged(int)), this,
SLOT(OnFitSelectionChanged(int)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.sbFixMin,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.sbFixMax,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.labelFixMin,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.labelFixMax,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.btnScaleToData,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), this, SLOT(OnScaleFixedYChecked(bool)));
connect(m_Controls.btnScaleToData, SIGNAL(clicked()), this, SLOT(OnScaleToDataYClicked()));
connect(m_Controls.sbFixMax, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingYChanged(double)));
connect(m_Controls.sbFixMin, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingYChanged(double)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.sbFixMin_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.sbFixMax_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.labelFixMin_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.labelFixMax_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.btnScaleToData_x,
SLOT(setEnabled(bool)));
connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), this, SLOT(OnScaleFixedXChecked(bool)));
connect(m_Controls.btnScaleToData_x, SIGNAL(clicked()), this, SLOT(OnScaleToDataXClicked()));
connect(m_Controls.sbFixMax_x, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingXChanged(double)));
connect(m_Controls.sbFixMin_x, SIGNAL(valueChanged(double)), this,
SLOT(OnFixedScalingXChanged(double)));
connect(m_Controls.btnFullPlot, SIGNAL(clicked(bool)), this, SLOT(OnFullPlotClicked(bool)));
this->EnsureBookmarkPointSet();
m_Controls.inspectionPositionWidget->SetPositionBookmarkNode(m_PositionBookmarksNode.Lock());
connect(m_Controls.inspectionPositionWidget, SIGNAL(PositionBookmarksChanged()), this, SLOT(OnPositionBookmarksChanged()));
// For some reason this needs to be called to set the plot widget's minimum width to an
// acceptable level (since Qwt 6).
// Otherwise it tries to keep both axes equal in length, resulting in a minimum width of
// 400-500px which is way too much.
m_Controls.widgetPlot->GetPlot()->updateAxes();
m_Controls.cmbFit->clear();
mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart();
RenderWindowPartActivated(renderWindowPart);
}
void ModelFitInspectorView::SetFocus()
{
}
void ModelFitInspectorView::NodeRemoved(const mitk::DataNode* node)
{
if (node == this->m_currentSelectedNode)
{
QmitkSingleNodeSelectionWidget::NodeList emptylist;
this->m_Controls.inputNodeSelector->SetCurrentSelection(emptylist);
}
}
void ModelFitInspectorView::OnScaleFixedYChecked(bool checked)
{
m_Controls.widgetPlot->GetPlot()->setAxisAutoScale(QwtPlot::yLeft, !checked);
if (checked)
{
OnScaleToDataYClicked();
}
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnScaleFixedXChecked(bool checked)
{
m_Controls.widgetPlot->GetPlot()->setAxisAutoScale(QwtPlot::xBottom, !checked);
if (checked)
{
OnScaleToDataXClicked();
}
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnScaleToDataYClicked()
{
auto minmax = this->m_PlotCurves.GetYMinMax();
auto min = minmax.first - std::abs(minmax.first) * 0.01;
auto max = minmax.second + std::abs(minmax.second) * 0.01;
m_Controls.sbFixMin->setValue(min);
m_Controls.sbFixMax->setValue(max);
};
void ModelFitInspectorView::OnScaleToDataXClicked()
{
auto minmax = this->m_PlotCurves.GetXMinMax();
auto min = minmax.first - std::abs(minmax.first) * 0.01;
auto max = minmax.second + std::abs(minmax.second) * 0.01;
m_Controls.sbFixMin_x->setValue(min);
m_Controls.sbFixMax_x->setValue(max);
};
void ModelFitInspectorView::OnFixedScalingYChanged(double /*value*/)
{
m_Controls.widgetPlot->GetPlot()->setAxisScale(QwtPlot::yLeft, m_Controls.sbFixMin->value(),
m_Controls.sbFixMax->value());
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnFixedScalingXChanged(double /*value*/)
{
m_Controls.widgetPlot->GetPlot()->setAxisScale(QwtPlot::xBottom, m_Controls.sbFixMin_x->value(),
m_Controls.sbFixMax_x->value());
m_Controls.widgetPlot->GetPlot()->replot();
};
void ModelFitInspectorView::OnFullPlotClicked(bool checked)
{
m_Controls.tabWidget->setVisible(!checked);
};
int ModelFitInspectorView::ActualizeFitSelectionWidget()
{
mitk::modelFit::ModelFitInfo::UIDType selectedFitUD = "";
bool isModelFitNode = false;
if (this->m_Controls.inputNodeSelector->GetSelectedNode().IsNotNull())
{
isModelFitNode = this->m_Controls.inputNodeSelector->GetSelectedNode()->GetData()->GetPropertyList()->GetStringProperty(
mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), selectedFitUD);
}
mitk::DataStorage::Pointer storage = this->GetDataStorage();
mitk::modelFit::NodeUIDSetType fitUIDs = mitk::modelFit::GetFitUIDsOfNode(
this->m_currentSelectedNode, storage);
this->m_modelfitList.clear();
this->m_Controls.cmbFit->clear();
for (const auto & fitUID : fitUIDs)
{
mitk::modelFit::ModelFitInfo::ConstPointer info = mitk::modelFit::CreateFitInfoFromNode(fitUID,
storage).GetPointer();
if (info.IsNotNull())
{
this->m_modelfitList.insert(std::make_pair(info->uid, info));
std::ostringstream nameStrm;
if (info->fitName.empty())
{
nameStrm << info->uid;
}
else
{
nameStrm << info->fitName;
}
nameStrm << " (" << info->modelName << ")";
QVariant data(info->uid.c_str());
m_Controls.cmbFit->addItem(QString::fromStdString(nameStrm.str()), data);
}
else
{
MITK_ERROR <<
"Was not able to extract model fit information from storage. Node properties in storage may be invalid. Failed fit UID:"
<< fitUID;
}
}
int cmbIndex = 0;
if (m_modelfitList.empty())
{
cmbIndex = -1;
};
if (isModelFitNode)
{
//model was selected, thus select this one in combobox
QVariant data(selectedFitUD.c_str());
cmbIndex = m_Controls.cmbFit->findData(data);
if (cmbIndex == -1)
{
MITK_WARN <<
"Model fit Inspector in invalid state. Selected fit seems to be not avaible in plugin selection. Failed fit UID:"
<< selectedFitUD;
}
};
m_Controls.cmbFit->setCurrentIndex(cmbIndex);
return cmbIndex;
}
void ModelFitInspectorView::OnInputChanged(const QList<mitk::DataNode::Pointer>& nodes)
{
if (nodes.size() > 0)
{
if (nodes.front() != this->m_currentSelectedNode)
{
m_internalUpdateFlag = true;
this->m_currentSelectedNode = nodes.front();
mitk::modelFit::ModelFitInfo::UIDType selectedFitUD = "";
bool isModelFitNode = this->m_currentSelectedNode->GetData()->GetPropertyList()->GetStringProperty(
mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), selectedFitUD);
if (isModelFitNode)
{
this->m_currentSelectedNode = this->GetInputNode(this->m_currentSelectedNode);
if (this->m_currentSelectedNode.IsNull())
{
MITK_WARN <<
"Model fit Inspector in invalid state. Input image for selected fit cannot be found in data storage. Failed fit UID:"
<< selectedFitUD;
}
}
auto cmbIndex = ActualizeFitSelectionWidget();
m_internalUpdateFlag = false;
m_selectedNodeTime.Modified();
if (cmbIndex == -1)
{
//only raw 4D data selected. Just update plots for current position
m_currentFit = nullptr;
m_currentFitTime.Modified();
OnSliceChanged();
m_Controls.plotDataWidget->SetXName(DEFAULT_X_AXIS);
}
else
{
//refresh fit selection (and implicitly update plots)
OnFitSelectionChanged(cmbIndex);
}
}
}
else
{
if (this->m_currentSelectedNode.IsNotNull())
{
m_internalUpdateFlag = true;
this->m_currentSelectedNode = nullptr;
this->m_currentFit = nullptr;
this->m_modelfitList.clear();
this->m_Controls.cmbFit->clear();
m_internalUpdateFlag = false;
m_selectedNodeTime.Modified();
OnFitSelectionChanged(0);
RefreshPlotData();
m_Controls.plotDataWidget->SetPlotData(&(this->m_PlotCurves));
m_Controls.fitParametersWidget->setFits(QmitkFitParameterModel::FitVectorType());
RenderPlot();
}
}
}
mitk::DataNode::ConstPointer
ModelFitInspectorView::GetInputNode(mitk::DataNode::ConstPointer node)
{
if (node.IsNotNull())
{
std::string selectedFitUD = "";
auto rule = mitk::ModelFitResultRelationRule::New();
auto predicate = rule->GetDestinationsDetector(node);
mitk::DataStorage::SetOfObjects::ConstPointer parentNodeList =
GetDataStorage()->GetSubset(predicate);
if (parentNodeList->size() > 0)
{
return parentNodeList->front().GetPointer();
}
}
return mitk::DataNode::ConstPointer();
}
void ModelFitInspectorView::ValidateAndSetCurrentPosition()
{
- mitk::Point3D currentSelectedPosition = GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetSelectedPosition(nullptr);
- unsigned int currentSelectedTimestep = m_renderWindowPart->GetTimeNavigationController()->GetTime()->
- GetPos();
+ const mitk::Point3D currentSelectedPosition = GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetSelectedPosition(nullptr);
+ const unsigned int currentSelectedTimestep = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimeStep();
if (m_currentSelectedPosition != currentSelectedPosition
|| m_currentSelectedTimeStep != currentSelectedTimestep
|| m_selectedNodeTime > m_currentPositionTime)
{
//the current position has been changed or the selected node has been changed since the last position validation -> check position
m_currentSelectedPosition = currentSelectedPosition;
m_currentSelectedTimeStep = currentSelectedTimestep;
m_currentPositionTime.Modified();
m_validSelectedPosition = false;
auto inputImage = this->GetCurrentInputImage();
if (inputImage.IsNull())
{
return;
}
mitk::BaseGeometry::ConstPointer geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep(
m_currentSelectedTimeStep).GetPointer();
// check for invalid time step
if (geometry.IsNull())
{
geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep(0);
}
if (geometry.IsNull())
{
return;
}
m_validSelectedPosition = geometry->IsInside(m_currentSelectedPosition);
}
}
mitk::Image::ConstPointer ModelFitInspectorView::GetCurrentInputImage() const
{
mitk::Image::ConstPointer result = nullptr;
if (this->m_currentFit.IsNotNull())
{
result = m_currentFit->inputImage;
}
else if (this->m_currentSelectedNode.IsNotNull())
{
result = dynamic_cast<mitk::Image*>(this->m_currentSelectedNode->GetData());
if (result.IsNotNull() && result->GetTimeSteps() <= 1)
{
//if the image is not dynamic, we can't use it.
result = nullptr;
}
}
return result;
};
const mitk::ModelBase::TimeGridType ModelFitInspectorView::GetCurrentTimeGrid() const
{
if (m_currentModelProviderService && m_currentFit.IsNotNull())
{
return m_currentModelProviderService->GetVariableGrid(m_currentFit);
}
else
{ //fall back if there is no model provider we assume to use the normal time grid.
return ExtractTimeGrid(GetCurrentInputImage());
}
};
void ModelFitInspectorView::OnSliceChanged()
{
ValidateAndSetCurrentPosition();
m_Controls.widgetPlot->setEnabled(m_validSelectedPosition);
if (m_currentSelectedNode.IsNotNull())
{
m_Controls.inspectionPositionWidget->SetCurrentPosition(m_currentSelectedPosition);
if (RefreshPlotData())
{
RenderPlot();
m_Controls.plotDataWidget->SetPlotData(&m_PlotCurves);
RenderFitInfo();
}
}
}
void ModelFitInspectorView::OnPositionBookmarksChanged()
{
if (RefreshPlotData())
{
RenderPlot();
m_Controls.plotDataWidget->SetPlotData(&m_PlotCurves);
RenderFitInfo();
}
}
void ModelFitInspectorView::OnFitSelectionChanged(int index)
{
if (!m_internalUpdateFlag)
{
MITK_DEBUG << "selected fit index: " << index;
std::string uid = "";
if (m_Controls.cmbFit->count() > index)
{
uid = m_Controls.cmbFit->itemData(index).toString().toStdString();
}
mitk::modelFit::ModelFitInfo::ConstPointer newFit = nullptr;
ModelFitInfoListType::iterator finding = m_modelfitList.find(uid);
if (finding != m_modelfitList.end())
{
newFit = finding->second;
}
if (m_currentFit != newFit)
{
m_currentModelParameterizer = nullptr;
m_currentModelProviderService = nullptr;
if (newFit.IsNotNull())
{
m_currentModelParameterizer = mitk::ModelGenerator::GenerateModelParameterizer(*newFit);
m_currentModelProviderService = mitk::ModelGenerator::GetProviderService(newFit->functionClassID);
}
m_currentFit = newFit;
m_currentFitTime.Modified();
auto name = m_currentFit->xAxisName;
if (!m_currentFit->xAxisUnit.empty())
{
name += " [" + m_currentFit->xAxisUnit + "]";
}
m_Controls.plotDataWidget->SetXName(name);
OnSliceChanged();
}
}
}
mitk::PlotDataCurveCollection::Pointer ModelFitInspectorView::RefreshPlotDataCurveCollection(const mitk::Point3D& position,
const mitk::Image* input, const mitk::modelFit::ModelFitInfo* fitInfo,
const mitk::ModelBase::TimeGridType& timeGrid, mitk::ModelParameterizerBase* parameterizer)
{
mitk::PlotDataCurveCollection::Pointer result = mitk::PlotDataCurveCollection::New();
//sample curve
if (input)
{
result->InsertElement(mitk::MODEL_FIT_PLOT_SAMPLE_NAME(), GenerateImageSamplePlotData(position, input, timeGrid));
}
//model signal curve
if (fitInfo)
{
// Interpolate time grid (x values) so the curve looks smooth
const mitk::ModelBase::TimeGridType interpolatedTimeGrid = mitk::GenerateSupersampledTimeGrid(timeGrid, INTERPOLATION_STEPS);
auto hires_curve = mitk::GenerateModelSignalPlotData(position, fitInfo, interpolatedTimeGrid, parameterizer);
result->InsertElement(mitk::MODEL_FIT_PLOT_INTERPOLATED_SIGNAL_NAME(), hires_curve);
auto curve = mitk::GenerateModelSignalPlotData(position, fitInfo, timeGrid, parameterizer);
result->InsertElement(mitk::MODEL_FIT_PLOT_SIGNAL_NAME(), curve);
}
return result;
};
bool ModelFitInspectorView::RefreshPlotData()
{
bool changed = false;
if (m_currentSelectedNode.IsNull())
{
this->m_PlotCurves = mitk::ModelFitPlotData();
changed = m_selectedNodeTime > m_lastRefreshTime;
m_lastRefreshTime.Modified();
}
else
{
assert(GetRenderWindowPart() != NULL);
const mitk::Image* input = GetCurrentInputImage();
const mitk::ModelBase::TimeGridType timeGrid = GetCurrentTimeGrid();
if (m_currentFitTime > m_lastRefreshTime || m_currentPositionTime > m_lastRefreshTime)
{
if (m_validSelectedPosition)
{
m_PlotCurves.currentPositionPlots = RefreshPlotDataCurveCollection(m_currentSelectedPosition,input,m_currentFit, timeGrid, m_currentModelParameterizer);
}
else
{
m_PlotCurves.currentPositionPlots = mitk::PlotDataCurveCollection::New();
}
changed = true;
}
auto bookmarks = m_PositionBookmarks.Lock();
if (bookmarks.IsNotNull())
{
if (m_currentFitTime > m_lastRefreshTime || bookmarks->GetMTime() > m_lastRefreshTime)
{
m_PlotCurves.positionalPlots.clear();
auto endIter = bookmarks->End();
for (auto iter = bookmarks->Begin(); iter != endIter; iter++)
{
auto collection = RefreshPlotDataCurveCollection(iter.Value(), input, m_currentFit, timeGrid, m_currentModelParameterizer);
m_PlotCurves.positionalPlots.emplace(iter.Index(), std::make_pair(iter.Value(), collection));
}
changed = true;
}
}
else
{
m_PlotCurves.positionalPlots.clear();
}
// input data curve
if (m_currentFitTime > m_lastRefreshTime)
{
m_PlotCurves.staticPlots->clear();
if (m_currentFit.IsNotNull())
{
m_PlotCurves.staticPlots = GenerateAdditionalModelFitPlotData(m_currentSelectedPosition, m_currentFit, timeGrid);
}
changed = true;
}
m_lastRefreshTime.Modified();
}
return changed;
}
void ModelFitInspectorView::RenderFitInfo()
{
assert(m_renderWindowPart != nullptr);
// configure fit information
if (m_currentFit.IsNull())
{
m_Controls.lFitType->setText("");
m_Controls.lFitUID->setText("");
m_Controls.lModelName->setText("");
m_Controls.lModelType->setText("");
}
else
{
m_Controls.lFitType->setText(QString::fromStdString(m_currentFit->fitType));
m_Controls.lFitUID->setText(QString::fromStdString(m_currentFit->uid));
m_Controls.lModelName->setText(QString::fromStdString(m_currentFit->modelName));
m_Controls.lModelType->setText(QString::fromStdString(m_currentFit->modelType));
}
// print results
std::stringstream infoOutput;
m_Controls.fitParametersWidget->setVisible(false);
m_Controls.groupSettings->setVisible(false);
if (m_currentFit.IsNull())
{
infoOutput << "No fit selected. Only raw image data is plotted.";
}
else if (!m_validSelectedPosition)
{
infoOutput <<
"Current position is outside of the input image of the selected fit.\nInspector is deactivated.";
}
else
{
m_Controls.fitParametersWidget->setVisible(true);
m_Controls.fitParametersWidget->setFits({ m_currentFit });
m_Controls.fitParametersWidget->setPositionBookmarks(m_PositionBookmarks.Lock());
m_Controls.fitParametersWidget->setCurrentPosition(m_currentSelectedPosition);
}
// configure data table
m_Controls.tableInputData->clearContents();
if (m_currentFit.IsNull())
{
infoOutput << "No fit selected. Only raw image data is plotted.";
}
else
{
m_Controls.groupSettings->setVisible(true);
m_Controls.tableInputData->setRowCount(m_PlotCurves.staticPlots->size());
unsigned int rowIndex = 0;
for (mitk::PlotDataCurveCollection::const_iterator pos = m_PlotCurves.staticPlots->begin();
pos != m_PlotCurves.staticPlots->end(); ++pos, ++rowIndex)
{
QColor dataColor;
if (pos->first == "ROI")
{
dataColor = QColor(0, 190, 0);
}
else
{
//Use HSV schema of QColor to calculate a different color depending on the
//number of already existing free iso lines.
dataColor.setHsv(((rowIndex + 1) * 85) % 360, 255, 255);
}
QTableWidgetItem* newItem = new QTableWidgetItem(QString::fromStdString(pos->first));
m_Controls.tableInputData->setItem(rowIndex, 0, newItem);
newItem = new QTableWidgetItem();
newItem->setBackgroundColor(dataColor);
m_Controls.tableInputData->setItem(rowIndex, 1, newItem);
}
}
m_Controls.lInfo->setText(QString::fromStdString(infoOutput.str()));
}
void ModelFitInspectorView::RenderPlotCurve(const mitk::PlotDataCurveCollection* curveCollection, const QColor& sampleColor, const QColor& signalColor, const std::string& posString)
{
auto sampleCurve = mitk::ModelFitPlotData::GetSamplePlot(curveCollection);
if (sampleCurve)
{
std::string name = mitk::MODEL_FIT_PLOT_SAMPLE_NAME() + posString;
unsigned int curveId = m_Controls.widgetPlot->InsertCurve(name.c_str());
m_Controls.widgetPlot->SetCurveData(curveId, sampleCurve->GetValues());
m_Controls.widgetPlot->SetCurvePen(curveId, QPen(Qt::NoPen));
// QwtSymbol needs to passed as a real pointer from MITK v2013.09.0 on
// (QwtPlotCurve deletes it on destruction and assignment).
QwtSymbol* dataSymbol = new QwtSymbol(QwtSymbol::Diamond, sampleColor, sampleColor, QSize(8, 8));
m_Controls.widgetPlot->SetCurveSymbol(curveId, dataSymbol);
// Again, there is no way to set a curve's legend attributes via QmitkPlotWidget so this
// gets unnecessarily complicated.
QwtPlotCurve* measurementCurve = dynamic_cast<QwtPlotCurve*>(m_Controls.widgetPlot->
GetPlot()->itemList(QwtPlotItem::Rtti_PlotCurve).back());
measurementCurve->setLegendAttribute(QwtPlotCurve::LegendShowSymbol);
measurementCurve->setLegendIconSize(QSize(8, 8));
}
//draw model curve
auto signalCurve = mitk::ModelFitPlotData::GetInterpolatedSignalPlot(curveCollection);
if (signalCurve)
{
std::string name = mitk::MODEL_FIT_PLOT_SIGNAL_NAME() + posString;
QPen pen;
pen.setColor(signalColor);
pen.setWidth(2);
unsigned int curveId = m_Controls.widgetPlot->InsertCurve(name.c_str());
m_Controls.widgetPlot->SetCurveData(curveId, signalCurve->GetValues());
m_Controls.widgetPlot->SetCurvePen(curveId, pen);
// Manually set the legend attribute to use the symbol as the legend icon and alter its
// size. Otherwise it would revert to default which is drawing a square which is the color
// of the curve's pen, so in this case none which defaults to black.
// Unfortunately, QmitkPlotWidget offers no way to set the legend attribute and icon size so
// this looks a bit hacky.
QwtPlotCurve* fitCurve = dynamic_cast<QwtPlotCurve*>(m_Controls.widgetPlot->GetPlot()->
itemList(QwtPlotItem::Rtti_PlotCurve).back());
fitCurve->setLegendAttribute(QwtPlotCurve::LegendShowLine);
}
}
void ModelFitInspectorView::RenderPlot()
{
m_Controls.widgetPlot->Clear();
std::string xAxis = DEFAULT_X_AXIS;
std::string yAxis = "Intensity";
std::string plotTitle = "Raw data plot: no data";
if (m_currentSelectedNode.IsNotNull())
{
plotTitle = "Raw data plot: " + m_currentSelectedNode->GetName();
}
if (m_currentFit.IsNotNull())
{
plotTitle = m_currentFit->modelName.c_str();
xAxis = m_currentFit->xAxisName;
if (!m_currentFit->xAxisUnit.empty())
{
xAxis += " [" + m_currentFit->xAxisUnit + "]";
}
yAxis = m_currentFit->yAxisName;
if (!m_currentFit->yAxisUnit.empty())
{
yAxis += " [" + m_currentFit->yAxisUnit + "]";
}
}
m_Controls.widgetPlot->SetAxisTitle(QwtPlot::xBottom, xAxis.c_str());
m_Controls.widgetPlot->SetAxisTitle(QwtPlot::yLeft, yAxis.c_str());
m_Controls.widgetPlot->SetPlotTitle(plotTitle.c_str());
// Draw static curves
unsigned int colorIndex = 0;
for (mitk::PlotDataCurveCollection::const_iterator pos = m_PlotCurves.staticPlots->begin();
pos != m_PlotCurves.staticPlots->end(); ++pos)
{
QColor dataColor;
unsigned int curveId = m_Controls.widgetPlot->InsertCurve(pos->first.c_str());
m_Controls.widgetPlot->SetCurveData(curveId, pos->second->GetValues());
if (pos->first == "ROI")
{
dataColor = QColor(0, 190, 0);
QPen pen;
pen.setColor(dataColor);
pen.setStyle(Qt::SolidLine);
m_Controls.widgetPlot->SetCurvePen(curveId, pen);
}
else
{
//Use HSV schema of QColor to calculate a different color depending on the
//number of already existing curves.
dataColor.setHsv((++colorIndex * 85) % 360, 255, 150);
m_Controls.widgetPlot->SetCurvePen(curveId, QPen(Qt::NoPen));
}
// QwtSymbol needs to passed as a real pointer from MITK v2013.09.0 on
// (QwtPlotCurve deletes it on destruction and assignment).
QwtSymbol* dataSymbol = new QwtSymbol(QwtSymbol::Triangle, dataColor, dataColor,
QSize(8, 8));
m_Controls.widgetPlot->SetCurveSymbol(curveId, dataSymbol);
// Again, there is no way to set a curve's legend attributes via QmitkPlotWidget so this
// gets unnecessarily complicated.
QwtPlotCurve* measurementCurve = dynamic_cast<QwtPlotCurve*>(m_Controls.widgetPlot->
GetPlot()->itemList(QwtPlotItem::Rtti_PlotCurve).back());
measurementCurve->setLegendAttribute(QwtPlotCurve::LegendShowSymbol);
measurementCurve->setLegendIconSize(QSize(8, 8));
}
// Draw positional curves
for (const auto& posIter : this->m_PlotCurves.positionalPlots)
{
QColor dataColor;
dataColor.setHsv((++colorIndex * 85) % 360, 255, 150);
this->RenderPlotCurve(posIter.second.second, dataColor, dataColor, " @ "+mitk::ModelFitPlotData::GetPositionalCollectionName(posIter));
}
// Draw current pos curve
this->RenderPlotCurve(m_PlotCurves.currentPositionPlots, QColor(Qt::red), QColor(Qt::black), "");
QwtLegend* legend = new QwtLegend();
legend->setFrameShape(QFrame::Box);
legend->setFrameShadow(QFrame::Sunken);
legend->setLineWidth(1);
m_Controls.widgetPlot->SetLegend(legend, QwtPlot::BottomLegend);
m_Controls.widgetPlot->Replot();
}
void ModelFitInspectorView::EnsureBookmarkPointSet()
{
if (m_PositionBookmarks.IsExpired() || m_PositionBookmarksNode.IsExpired())
{
const char* nodeName = "org.mitk.gui.qt.fit.inspector.positions";
mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode(nodeName);
if (!node)
{
node = mitk::DataNode::New();
node->SetName(nodeName);
node->SetBoolProperty("helper object", true);
this->GetDataStorage()->Add(node);
}
m_PositionBookmarksNode = node;
mitk::PointSet::Pointer pointSet = dynamic_cast<mitk::PointSet*>(node->GetData());
if (pointSet.IsNull())
{
pointSet = mitk::PointSet::New();
node->SetData(pointSet);
}
m_PositionBookmarks = pointSet;
}
}
diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp
index 85bbb1257e..096380482c 100644
--- a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp
+++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp
@@ -1,606 +1,606 @@
/*============================================================================
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.
============================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkIGTTrackingSemiAutomaticMeasurementView.h"
// Qt
#include <QMessageBox>
#include <qfiledialog.h>
#include <qevent.h>
#include <QCheckBox>
// MITK
#include <mitkNavigationToolStorageDeserializer.h>
#include <mitkTrackingDeviceSourceConfigurator.h>
-#include <mitkLog.h>
+#include <mitkLogBackend.h>
#include "mitkHummelProtocolEvaluation.h"
// POCO
#include <Poco/File.h>
#include <Poco/Path.h>
const std::string QmitkIGTTrackingSemiAutomaticMeasurementView::VIEW_ID = "org.mitk.views.igttrackingsemiautomaticmeasurement";
QmitkIGTTrackingSemiAutomaticMeasurementView::QmitkIGTTrackingSemiAutomaticMeasurementView()
: m_Controls(nullptr)
{
m_NextFile = 0;
m_FilenameVector = std::vector<std::string>();
m_Timer = new QTimer(this);
m_logging = false;
m_referenceValid = true;
m_tracking = false;
m_EvaluationFilter = mitk::NavigationDataEvaluationFilter::New();
}
QmitkIGTTrackingSemiAutomaticMeasurementView::~QmitkIGTTrackingSemiAutomaticMeasurementView()
{
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::CreateResults()
{
QString LogFileName = m_Controls->m_OutputPath->text() + "_results.log";
- mitk::LoggingBackend::Unregister();
- mitk::LoggingBackend::SetLogFile(LogFileName.toStdString().c_str());
- mitk::LoggingBackend::Register();
+ mitk::LogBackend::Unregister();
+ mitk::LogBackend::SetLogFile(LogFileName.toStdString());
+ mitk::LogBackend::Register();
double RMSmean = 0;
for (std::size_t i = 0; i < m_RMSValues.size(); ++i)
{
MITK_INFO << "RMS at " << this->m_FilenameVector.at(i) << ": " << m_RMSValues.at(i);
RMSmean += m_RMSValues.at(i);
}
RMSmean /= m_RMSValues.size();
MITK_INFO << "RMS mean over " << m_RMSValues.size() << " values: " << RMSmean;
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName("Tracking Results");
newNode->SetData(this->m_MeanPoints);
this->GetDataStorage()->Add(newNode);
std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> results5cmDistances;
if (m_Controls->m_mediumVolume->isChecked())
mitk::HummelProtocolEvaluation::Evaluate5cmDistances(m_MeanPoints, mitk::HummelProtocolEvaluation::medium, results5cmDistances);
else if (m_Controls->m_smallVolume->isChecked())
mitk::HummelProtocolEvaluation::Evaluate5cmDistances(m_MeanPoints, mitk::HummelProtocolEvaluation::small, results5cmDistances);
else if (m_Controls->m_standardVolume->isChecked())
mitk::HummelProtocolEvaluation::Evaluate5cmDistances(m_MeanPoints, mitk::HummelProtocolEvaluation::standard, results5cmDistances);
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::CreateQtPartControl(QWidget *parent)
{
// build up qt view, unless already done
if (!m_Controls)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkIGTTrackingSemiAutomaticMeasurementViewControls;
m_Controls->setupUi(parent);
//buttons
connect(m_Controls->m_LoadMeasurementToolStorage, SIGNAL(clicked()), this, SLOT(OnLoadMeasurementStorage()));
connect(m_Controls->m_LoadReferenceToolStorage, SIGNAL(clicked()), this, SLOT(OnLoadReferenceStorage()));
connect(m_Controls->m_StartTracking, SIGNAL(clicked()), this, SLOT(OnStartTracking()));
connect(m_Controls->m_LoadList, SIGNAL(clicked()), this, SLOT(OnMeasurementLoadFile()));
connect(m_Controls->m_StartNextMeasurement, SIGNAL(clicked()), this, SLOT(StartNextMeasurement()));
connect(m_Controls->m_ReapeatLastMeasurement, SIGNAL(clicked()), this, SLOT(RepeatLastMeasurement()));
connect(m_Controls->m_SetReference, SIGNAL(clicked()), this, SLOT(OnSetReference()));
connect(m_Controls->m_UseReferenceTrackingSystem, SIGNAL(toggled(bool)), this, SLOT(OnUseReferenceToggled(bool)));
connect(m_Controls->m_CreateResults, SIGNAL(clicked()), this, SLOT(CreateResults()));
//event filter
qApp->installEventFilter(this);
//timers
connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateTimer()));
}
//initialize some view
m_Controls->m_StopTracking->setEnabled(false);
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::OnUseReferenceToggled(bool state)
{
if (state)
{
m_Controls->m_ReferenceBox->setEnabled(true);
m_Controls->m_SetReference->setEnabled(true);
}
else
{
m_Controls->m_ReferenceBox->setEnabled(false);
m_Controls->m_SetReference->setEnabled(false);
}
}
mitk::NavigationToolStorage::Pointer QmitkIGTTrackingSemiAutomaticMeasurementView::ReadStorage(std::string file)
{
mitk::NavigationToolStorage::Pointer returnValue;
//initialize tool storage
returnValue = mitk::NavigationToolStorage::New();
//read tool storage from disk
mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage());
returnValue = myDeserializer->Deserialize(file);
if (returnValue.IsNull())
{
QMessageBox msgBox;
msgBox.setText(myDeserializer->GetErrorMessage().c_str());
msgBox.exec();
returnValue = nullptr;
}
return returnValue;
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::OnSetReference()
{
//initialize reference
m_ReferenceStartPositions = std::vector<mitk::Point3D>();
m_ReferenceTrackingDeviceSource->Update();
QString Label = "Positions At Start: ";
for (unsigned int i = 0; i < m_ReferenceTrackingDeviceSource->GetNumberOfOutputs(); ++i)
{
mitk::Point3D position = m_ReferenceTrackingDeviceSource->GetOutput(i)->GetPosition();
Label = Label + "Tool" + QString::number(i) + ":[" + QString::number(position[0]) + ":" + QString::number(position[1]) + ":" + QString::number(position[1]) + "] ";
m_ReferenceStartPositions.push_back(position);
}
m_Controls->m_ReferencePosAtStart->setText(Label);
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::OnLoadMeasurementStorage()
{
//read in filename
QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Toolfile"), "/", tr("All Files (*.*)"));
if (filename.isNull()) return;
m_MeasurementStorage = ReadStorage(filename.toStdString());
//update label
Poco::Path myPath = Poco::Path(filename.toStdString()); //use this to seperate filename from path
QString toolLabel = QString("Tool Storage: ") + QString::number(m_MeasurementStorage->GetToolCount()) + " Tools from " + myPath.getFileName().c_str();
m_Controls->m_MeasurementToolStorageLabel->setText(toolLabel);
//update status widget
m_Controls->m_ToolStatusWidget->RemoveStatusLabels();
m_Controls->m_ToolStatusWidget->PreShowTools(m_MeasurementStorage);
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::OnLoadReferenceStorage()
{
//read in filename
static QString oldFile;
if (oldFile.isNull()) oldFile = "/";
QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Toolfile"), oldFile, tr("All Files (*.*)"));
if (filename.isNull()) return;
oldFile = filename;
m_ReferenceStorage = ReadStorage(filename.toStdString());
//update label
Poco::Path myPath = Poco::Path(filename.toStdString()); //use this to seperate filename from path
QString toolLabel = QString("Tool Storage: ") + QString::number(m_ReferenceStorage->GetToolCount()) + " Tools from " + myPath.getFileName().c_str();
m_Controls->m_ReferenceToolStorageLabel->setText(toolLabel);
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::OnStartTracking()
{
//check if everything is ready to start tracking
if (m_MeasurementStorage.IsNull())
{
MessageBox("Error: No measurement tools loaded yet!");
return;
}
else if (m_ReferenceStorage.IsNull() && m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
MessageBox("Error: No refernce tools loaded yet!");
return;
}
else if (m_MeasurementStorage->GetToolCount() == 0)
{
MessageBox("Error: No way to track without tools!");
return;
}
else if (m_Controls->m_UseReferenceTrackingSystem->isChecked() && (m_ReferenceStorage->GetToolCount() == 0))
{
MessageBox("Error: No way to track without tools!");
return;
}
//build the first IGT pipeline (MEASUREMENT)
mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory1 = mitk::TrackingDeviceSourceConfigurator::New(this->m_MeasurementStorage, this->m_Controls->m_MeasurementTrackingDeviceConfigurationWidget->GetTrackingDevice());
m_MeasurementTrackingDeviceSource = myTrackingDeviceSourceFactory1->CreateTrackingDeviceSource(this->m_MeasurementToolVisualizationFilter);
if (m_MeasurementTrackingDeviceSource.IsNull())
{
MessageBox(myTrackingDeviceSourceFactory1->GetErrorMessage());
return;
}
//connect the tool visualization widget
for (unsigned int i = 0; i < m_MeasurementTrackingDeviceSource->GetNumberOfOutputs(); ++i)
{
m_Controls->m_ToolStatusWidget->AddNavigationData(m_MeasurementTrackingDeviceSource->GetOutput(i));
m_EvaluationFilter->SetInput(i, m_MeasurementTrackingDeviceSource->GetOutput(i));
}
m_Controls->m_ToolStatusWidget->ShowStatusLabels();
m_Controls->m_ToolStatusWidget->SetShowPositions(true);
m_Controls->m_ToolStatusWidget->SetShowQuaternions(true);
//build the second IGT pipeline (REFERENCE)
if (m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory2 = mitk::TrackingDeviceSourceConfigurator::New(this->m_ReferenceStorage, this->m_Controls->m_ReferenceDeviceConfigurationWidget->GetTrackingDevice());
m_ReferenceTrackingDeviceSource = myTrackingDeviceSourceFactory2->CreateTrackingDeviceSource();
if (m_ReferenceTrackingDeviceSource.IsNull())
{
MessageBox(myTrackingDeviceSourceFactory2->GetErrorMessage());
return;
}
}
//initialize tracking
try
{
m_MeasurementTrackingDeviceSource->Connect();
m_MeasurementTrackingDeviceSource->StartTracking();
if (m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
m_ReferenceTrackingDeviceSource->Connect();
m_ReferenceTrackingDeviceSource->StartTracking();
}
}
catch (...)
{
MessageBox("Error while starting the tracking device!");
return;
}
//set reference
if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) OnSetReference();
//start timer
m_Timer->start(1000 / (m_Controls->m_SamplingRate->value()));
m_Controls->m_StartTracking->setEnabled(false);
m_Controls->m_StartTracking->setEnabled(true);
m_tracking = true;
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::OnStopTracking()
{
if (this->m_logging) FinishMeasurement();
m_MeasurementTrackingDeviceSource->Disconnect();
m_MeasurementTrackingDeviceSource->StopTracking();
if (m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
m_ReferenceTrackingDeviceSource->Disconnect();
m_ReferenceTrackingDeviceSource->StopTracking();
}
m_Timer->stop();
m_Controls->m_StartTracking->setEnabled(true);
m_Controls->m_StartTracking->setEnabled(false);
m_tracking = false;
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::OnMeasurementLoadFile()
{
m_FilenameVector = std::vector<std::string>();
m_FilenameVector.clear();
m_NextFile = 0;
//read in filename
QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Measurement Filename List"), "/", tr("All Files (*.*)"));
if (filename.isNull()) return;
//define own locale
std::locale C("C");
setlocale(LC_ALL, "C");
//read file
std::ifstream file;
file.open(filename.toStdString().c_str(), std::ios::in);
if (file.good())
{
//read out file
file.seekg(0L, std::ios::beg); // move to begin of file
while (!file.eof())
{
std::string buffer;
std::getline(file, buffer); // read out file line by line
if (buffer.size() > 0) m_FilenameVector.push_back(buffer);
}
}
//fill list at GUI
m_Controls->m_MeasurementList->clear();
for (unsigned int i = 0; i < m_FilenameVector.size(); i++) { new QListWidgetItem(tr(m_FilenameVector.at(i).c_str()), m_Controls->m_MeasurementList); }
//update label next measurement
std::stringstream label;
label << "Next Measurement: " << m_FilenameVector.at(0);
m_Controls->m_NextMeasurement->setText(label.str().c_str());
//reset results files
m_MeanPoints = mitk::PointSet::New();
m_RMSValues = std::vector<double>();
m_EvaluationFilter = mitk::NavigationDataEvaluationFilter::New();
if (m_MeasurementToolVisualizationFilter.IsNotNull()) m_EvaluationFilter->SetInput(0, m_MeasurementToolVisualizationFilter->GetOutput(0));
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::UpdateTimer()
{
if (m_EvaluationFilter.IsNotNull() && m_logging) m_EvaluationFilter->Update();
else m_MeasurementToolVisualizationFilter->Update();
m_Controls->m_ToolStatusWidget->Refresh();
//update reference
if (m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
m_ReferenceTrackingDeviceSource->Update();
QString Label = "Current Positions: ";
bool distanceThresholdExceeded = false;
for (unsigned int i = 0; i < m_ReferenceTrackingDeviceSource->GetNumberOfOutputs(); ++i)
{
mitk::Point3D position = m_ReferenceTrackingDeviceSource->GetOutput(i)->GetPosition();
Label = Label + "Tool" + QString::number(i) + ":[" + QString::number(position[0]) + ":" + QString::number(position[1]) + ":" + QString::number(position[1]) + "] ";
if (position.EuclideanDistanceTo(m_ReferenceStartPositions.at(i)) > m_Controls->m_ReferenceThreshold->value()) distanceThresholdExceeded = true;
}
m_Controls->m_ReferenceCurrentPos->setText(Label);
if (distanceThresholdExceeded)
{
m_Controls->m_ReferenceOK->setText("<html><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:28pt; font-weight:400; font-style:normal;\">NOT OK!</body></html>");
m_referenceValid = false;
}
else
{
m_Controls->m_ReferenceOK->setText("<html><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:28pt; font-weight:400; font-style:normal;\">OK</body></html>");
m_referenceValid = true;
}
}
//update logging
if (m_logging)
{
//check for missing objects
if (m_MeasurementLoggingFilterXML.IsNull() ||
m_MeasurementLoggingFilterCSV.IsNull()
)
{
return;
}
//log/measure
m_MeasurementLoggingFilterXML->Update();
m_MeasurementLoggingFilterCSV->Update();
if (m_Controls->m_UseReferenceTrackingSystem->isChecked() &&
m_ReferenceLoggingFilterXML.IsNotNull() &&
m_ReferenceLoggingFilterCSV.IsNotNull())
{
m_ReferenceLoggingFilterXML->Update();
m_ReferenceLoggingFilterCSV->Update();
}
m_loggedFrames++;
LogAdditionalCSVFile();
//check if all frames are logged ... if yes finish the measurement
if (m_loggedFrames > m_Controls->m_SamplesPerMeasurement->value()) { FinishMeasurement(); }
//update logging label
QString loggingLabel = "Collected Samples: " + QString::number(m_loggedFrames);
m_Controls->m_CollectedSamples->setText(loggingLabel);
}
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::StartNextMeasurement()
{
if (this->m_NextFile >= static_cast<int>(m_FilenameVector.size()))
{
MessageBox("Last Measurement reached!");
return;
}
m_loggedFrames = 0;
m_logging = true;
//check if directory exists, if not create one
Poco::File myPath(std::string(m_Controls->m_OutputPath->text().toUtf8()).c_str());
if (!myPath.exists()) myPath.createDirectory();
QString LogFileName = m_Controls->m_OutputPath->text() + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".log";
- mitk::LoggingBackend::Unregister();
- mitk::LoggingBackend::SetLogFile(LogFileName.toStdString().c_str());
- mitk::LoggingBackend::Register();
+ mitk::LogBackend::Unregister();
+ mitk::LogBackend::SetLogFile(LogFileName.toStdString());
+ mitk::LogBackend::Register();
//initialize logging filters
m_MeasurementLoggingFilterXML = mitk::NavigationDataRecorderDeprecated::New();
m_MeasurementLoggingFilterXML->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile);
m_MeasurementLoggingFilterCSV = mitk::NavigationDataRecorderDeprecated::New();
m_MeasurementLoggingFilterCSV->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile);
m_MeasurementLoggingFilterXML->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::xml);
m_MeasurementLoggingFilterCSV->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::csv);
QString MeasurementFilenameXML = m_Controls->m_OutputPath->text() + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".xml";
QString MeasurementFilenameCSV = m_Controls->m_OutputPath->text() + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".csv";
m_MeasurementLoggingFilterXML->SetFileName(MeasurementFilenameXML.toStdString());
m_MeasurementLoggingFilterCSV->SetFileName(MeasurementFilenameCSV.toStdString());
m_MeasurementLoggingFilterXML->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value());
m_MeasurementLoggingFilterCSV->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value());
if (m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
m_ReferenceLoggingFilterXML = mitk::NavigationDataRecorderDeprecated::New();
m_ReferenceLoggingFilterXML->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile);
m_ReferenceLoggingFilterCSV = mitk::NavigationDataRecorderDeprecated::New();
m_ReferenceLoggingFilterCSV->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile);
m_ReferenceLoggingFilterXML->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::xml);
m_ReferenceLoggingFilterCSV->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::csv);
QString ReferenceFilenameXML = m_Controls->m_OutputPath->text() + "Reference_" + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".xml";
QString ReferenceFilenameCSV = m_Controls->m_OutputPath->text() + "Reference_" + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".csv";
m_ReferenceLoggingFilterXML->SetFileName(ReferenceFilenameXML.toStdString());
m_ReferenceLoggingFilterCSV->SetFileName(ReferenceFilenameCSV.toStdString());
m_ReferenceLoggingFilterXML->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value());
m_ReferenceLoggingFilterCSV->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value());
}
//start additional csv logging
StartLoggingAdditionalCSVFile(m_FilenameVector.at(m_NextFile));
//connect filter
for (unsigned int i = 0; i < m_MeasurementToolVisualizationFilter->GetNumberOfOutputs(); ++i)
{
m_MeasurementLoggingFilterXML->AddNavigationData(m_MeasurementToolVisualizationFilter->GetOutput(i));
m_MeasurementLoggingFilterCSV->AddNavigationData(m_MeasurementToolVisualizationFilter->GetOutput(i));
}
if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) for (unsigned int i = 0; i < m_ReferenceTrackingDeviceSource->GetNumberOfOutputs(); ++i)
{
m_ReferenceLoggingFilterXML->AddNavigationData(m_ReferenceTrackingDeviceSource->GetOutput(i));
m_ReferenceLoggingFilterCSV->AddNavigationData(m_ReferenceTrackingDeviceSource->GetOutput(i));
}
//start filter
m_MeasurementLoggingFilterXML->StartRecording();
m_MeasurementLoggingFilterCSV->StartRecording();
if (m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
m_ReferenceLoggingFilterXML->StartRecording();
m_ReferenceLoggingFilterCSV->StartRecording();
}
//disable all buttons
DisableAllButtons();
//update label next measurement
std::stringstream label;
if ((m_NextFile + 1) >= static_cast<int>(m_FilenameVector.size())) label << "Next Measurement: <none>";
else label << "Next Measurement: " << m_FilenameVector.at(m_NextFile + 1);
m_Controls->m_NextMeasurement->setText(label.str().c_str());
//update label last measurement
std::stringstream label2;
label2 << "Last Measurement: " << m_FilenameVector.at(m_NextFile);
m_Controls->m_LastMeasurement->setText(label2.str().c_str());
m_NextFile++;
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::RepeatLastMeasurement()
{
m_NextFile--;
StartNextMeasurement();
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::MessageBox(std::string s)
{
QMessageBox msgBox;
msgBox.setText(s.c_str());
msgBox.exec();
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::DisableAllButtons()
{
m_Controls->m_LoadList->setEnabled(false);
m_Controls->m_StartNextMeasurement->setEnabled(false);
m_Controls->m_ReapeatLastMeasurement->setEnabled(false);
m_Controls->m_SamplingRate->setEnabled(false);
m_Controls->m_SamplesPerMeasurement->setEnabled(false);
m_Controls->m_ReferenceThreshold->setEnabled(false);
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::EnableAllButtons()
{
m_Controls->m_LoadList->setEnabled(true);
m_Controls->m_StartNextMeasurement->setEnabled(true);
m_Controls->m_ReapeatLastMeasurement->setEnabled(true);
m_Controls->m_SamplingRate->setEnabled(true);
m_Controls->m_SamplesPerMeasurement->setEnabled(true);
m_Controls->m_ReferenceThreshold->setEnabled(true);
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::FinishMeasurement()
{
m_logging = false;
m_MeasurementLoggingFilterXML->StopRecording();
m_MeasurementLoggingFilterCSV->StopRecording();
if (m_Controls->m_UseReferenceTrackingSystem->isChecked())
{
m_ReferenceLoggingFilterXML->StopRecording();
m_ReferenceLoggingFilterCSV->StopRecording();
}
StopLoggingAdditionalCSVFile();
int id = m_NextFile - 1;
mitk::Point3D positionMean = m_EvaluationFilter->GetPositionMean(0);
MITK_INFO << "Evaluated " << m_EvaluationFilter->GetNumberOfAnalysedNavigationData(0) << " samples.";
double rms = m_EvaluationFilter->GetPositionErrorRMS(0);
MITK_INFO << "RMS: " << rms;
MITK_INFO << "Position Mean: " << positionMean;
m_MeanPoints->SetPoint(id, positionMean);
if (static_cast<int>(m_RMSValues.size()) <= id) m_RMSValues.push_back(rms);
else m_RMSValues[id] = rms;
m_EvaluationFilter->ResetStatistic();
EnableAllButtons();
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::StartLoggingAdditionalCSVFile(std::string filePostfix)
{
//write logfile header
QString header = "Nr;MITK_Time;Valid_Reference;";
QString tool = QString("MeasureTool_") + QString(m_MeasurementTrackingDeviceSource->GetOutput(0)->GetName());
header = header + tool + "[x];" + tool + "[y];" + tool + "[z];" + tool + "[qx];" + tool + "[qy];" + tool + "[qz];" + tool + "[qr]\n";
//open logfile and write header
m_logFileCSV.open(std::string(m_Controls->m_OutputPath->text().toUtf8()).append("/LogFileCombined").append(filePostfix.c_str()).append(".csv").c_str(), std::ios::out);
m_logFileCSV << header.toStdString().c_str();
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::LogAdditionalCSVFile()
{
mitk::Point3D pos = m_MeasurementTrackingDeviceSource->GetOutput(0)->GetPosition();
mitk::Quaternion rot = m_MeasurementTrackingDeviceSource->GetOutput(0)->GetOrientation();
std::string valid = "";
if (m_referenceValid) valid = "true";
else valid = "false";
std::stringstream timestamp;
timestamp << m_MeasurementTrackingDeviceSource->GetOutput(0)->GetTimeStamp();
QString dataSet = QString::number(m_loggedFrames) + ";" + QString(timestamp.str().c_str()) + ";" + QString(valid.c_str()) + ";" + QString::number(pos[0]) + ";" + QString::number(pos[1]) + ";" + QString::number(pos[2]) + ";" + QString::number(rot.x()) + ";" + QString::number(rot.y()) + ";" + QString::number(rot.z()) + ";" + QString::number(rot.r()) + "\n";
m_logFileCSV << dataSet.toStdString();
}
void QmitkIGTTrackingSemiAutomaticMeasurementView::StopLoggingAdditionalCSVFile()
{
m_logFileCSV.close();
}
bool QmitkIGTTrackingSemiAutomaticMeasurementView::eventFilter(QObject *, QEvent *ev)
{
if (ev->type() == QEvent::KeyPress)
{
QKeyEvent *k = (QKeyEvent *)ev;
bool down = k->key() == 16777239;
if (down && m_tracking && !m_logging)
StartNextMeasurement();
}
return false;
}
diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.cpp
index 182ffa70d2..99f3c3ad57 100644
--- a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.cpp
+++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.cpp
@@ -1,74 +1,74 @@
/*============================================================================
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 "mitkUSNavigationLoggingBackend.h"
#include <mitkCommon.h>
mitk::USNavigationLoggingBackend::USNavigationLoggingBackend()
{
}
mitk::USNavigationLoggingBackend::~USNavigationLoggingBackend()
{
if ( m_OutputStream.is_open() ) { m_OutputStream.close(); }
}
void mitk::USNavigationLoggingBackend::SetOutputFileName(std::string filename)
{
if ( m_OutputStream.is_open() ) { m_OutputStream.close(); }
m_OutputStream.open(filename.c_str());
if ( ! m_OutputStream.is_open() )
{
MITK_ERROR("USNavigationLoggingBackend")
<< "File '" << filename << "' cannot be opened for logging.";
mitkThrow() << "File '" << filename << "' cannot be opened for logging.";
}
}
-void mitk::USNavigationLoggingBackend::ProcessMessage(const mbilog::LogMessage& logMessage)
+void mitk::USNavigationLoggingBackend::ProcessMessage(const LogMessage& logMessage)
{
if ( m_OutputStream.is_open()) {this->FormatSmart(m_OutputStream, logMessage);}
- if (logMessage.category == "USNavigationLogging")
+ if (logMessage.Category == "USNavigationLogging")
{
- m_lastNavigationMessages.push_back(logMessage.message);
- m_allNavigationMessages.push_back(logMessage.message);
+ m_lastNavigationMessages.push_back(logMessage.Message);
+ m_allNavigationMessages.push_back(logMessage.Message);
}
}
std::vector<std::string> mitk::USNavigationLoggingBackend::GetNavigationMessages()
{
return m_lastNavigationMessages;
}
void mitk::USNavigationLoggingBackend::WriteCSVFileWithNavigationMessages(std::string filename)
{
std::ofstream csvStream;
csvStream.open(filename.c_str());
if ( ! csvStream.is_open() ) {MITK_ERROR("USNavigationLoggingBackend") << "File '" << filename << "' cannot be opened for logging."; return;}
for (std::size_t i = 0; i < m_allNavigationMessages.size(); i++)
{
csvStream << m_allNavigationMessages.at(i) << "\n";
}
csvStream.close();
}
void mitk::USNavigationLoggingBackend::ClearNavigationMessages()
{
m_lastNavigationMessages = std::vector<std::string>();
}
-mbilog::OutputType mitk::USNavigationLoggingBackend::GetOutputType() const
+mitk::LogBackendBase::OutputType mitk::USNavigationLoggingBackend::GetOutputType() const
{
- return mbilog::File;
+ return OutputType::File;
}
diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.h b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.h
index f9474362f7..092e749657 100644
--- a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.h
+++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/IO/mitkUSNavigationLoggingBackend.h
@@ -1,70 +1,69 @@
/*============================================================================
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 mitkUSNavigationLoggingBackend_h
#define mitkUSNavigationLoggingBackend_h
#include <fstream>
#include <vector>
-#include "mbilogExports.h"
-#include "mbilogTextBackendBase.h"
-#include "mbilogLogMessage.h"
-#include "mbilogLoggingTypes.h"
+#include <mitkLogBackendText.h>
+#include <mitkLogMessage.h>
+#include <mitkLogLevel.h>
namespace mitk {
/**
- * \brief Backend for the mbi logging mechanism. This backend writes all messages to the given file.
+ * \brief Backend for the MITK log mechanism. This backend writes all messages to the given file.
*/
- class USNavigationLoggingBackend : public mbilog::TextBackendBase
+ class USNavigationLoggingBackend : public LogBackendText
{
public:
USNavigationLoggingBackend();
~USNavigationLoggingBackend() override;
/** \brief Set file path und name for the output file.
* The file will be opened and all log messages will be directed there from then on.
*
* \throws mitk::Exception if the file cannot be opened
*/
void SetOutputFileName(std::string filename);
/** \brief This method is called by the mbi logging mechanism if the object is registered in
* the mbi logging mechanism and a logging message is emitted. The method formats the
* logging messages to a normal string (depending on formatting mode) and writes it to std::cout.
*
* \param logMessage Logging message.
*/
- void ProcessMessage(const mbilog::LogMessage &logMessage ) override;
+ void ProcessMessage(const LogMessage &logMessage ) override;
/** @return Returns all messages of the category "USNavigationLogging" since the last call of ClearNavigationMessages(). */
std::vector<std::string> GetNavigationMessages();
/** Writes a CSV file containing all stored navigation messages to the given output filename.
*/
void WriteCSVFileWithNavigationMessages(std::string filename);
/** Clears the internally stored navigation messages of the category "USNavigationLogging". */
void ClearNavigationMessages();
- mbilog::OutputType GetOutputType(void) const override;
+ OutputType GetOutputType() const override;
private:
std::ofstream m_OutputStream;
std::vector<std::string> m_lastNavigationMessages;
std::vector<std::string> m_allNavigationMessages;
};
} // namespace mitk
#endif
diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp
index 4fdc111e1b..2842412f7e 100644
--- a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp
+++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp
@@ -1,800 +1,800 @@
/*============================================================================
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 "QmitkUSNavigationMarkerPlacement.h"
#include "ui_QmitkUSNavigationMarkerPlacement.h"
#include "NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h"
#include "NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h"
#include "NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h"
#include "NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h"
#include "NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h"
#include "NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h"
#include "SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h"
#include "mitkAbstractUltrasoundTrackerDevice.h"
#include "mitkIRenderingManager.h"
#include "mitkNodeDisplacementFilter.h"
#include "mitkTrackedUltrasound.h"
#include <mitkIOUtil.h>
#include "IO/mitkUSNavigationStepTimer.h"
#include <QDateTime>
#include <QDir>
#include <QInputDialog>
#include <QMessageBox>
#include <QSignalMapper>
#include <QTimer>
#include "QmitkRenderWindow.h"
#include "QmitkStdMultiWidget.h"
#include "QmitkStdMultiWidgetEditor.h"
#include "mitkCameraController.h"
#include "mitkLayoutAnnotationRenderer.h"
#include <vtkSmartPointer.h>
// scene serialization
#include <mitkConvert2Dto3DImageFilter.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkSceneIO.h>
#include <mitkSurface.h>
const std::string QmitkUSNavigationMarkerPlacement::VIEW_ID = "org.mitk.views.usmarkerplacement";
const char *QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR = "Tumour";
const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE = "Target Surface";
const char *QmitkUSNavigationMarkerPlacement::DATANAME_ZONES = "Zones";
const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS = "Targets";
const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS_PATHS = "Target Paths";
const char *QmitkUSNavigationMarkerPlacement::DATANAME_REACHED_TARGETS = "Reached Targets";
QmitkUSNavigationMarkerPlacement::QmitkUSNavigationMarkerPlacement()
: m_Parent(nullptr),
m_UpdateTimer(new QTimer(this)),
m_ImageAndNavigationDataLoggingTimer(new QTimer(this)),
m_StdMultiWidget(nullptr),
m_CombinedModality(nullptr),
m_ReinitAlreadyDone(false),
m_IsExperimentRunning(false),
m_CurrentApplicationName(),
m_NavigationStepTimer(mitk::USNavigationStepTimer::New()),
m_IconRunning(QPixmap(":/USNavigation/record.png")),
m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")),
m_ResultsDirectory(),
m_ExperimentName(),
m_ExperimentResultsSubDirectory(),
m_NavigationStepNames(),
m_LoggingBackend(),
m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()),
m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()),
m_TargetNodeDisplacementFilter(nullptr),
m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()),
m_ToolVisualizationFilter(nullptr),
m_AblationZonesVector(),
m_NeedleIndex(0),
m_MarkerIndex(1),
m_SceneNumber(1),
m_WarnOverlay(mitk::TextAnnotation2D::New()),
m_NavigationDataSource(nullptr),
m_CurrentStorage(nullptr),
m_ImageStreamNode(nullptr),
ui(new Ui::QmitkUSNavigationMarkerPlacement)
{
connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
connect(
m_ImageAndNavigationDataLoggingTimer, SIGNAL(timeout()), this, SLOT(OnImageAndNavigationDataLoggingTimeout()));
// scale running (and not running) icon the specific height
m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation);
m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation);
}
QmitkUSNavigationMarkerPlacement::~QmitkUSNavigationMarkerPlacement()
{
this->GetDataStorage()->Remove(m_InstrumentNode);
delete ui;
}
void QmitkUSNavigationMarkerPlacement::OnChangeAblationZone(int id, int newSize)
{
if ((static_cast<int>(m_AblationZonesVector.size()) < id) || (id < 0))
{
return;
}
MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize;
// create a vtk sphere with given radius
vtkSmartPointer<vtkSphereSource> vtkSphere = vtkSmartPointer<vtkSphereSource>::New();
vtkSphere->SetRadius(newSize / 2);
vtkSphere->SetCenter(0, 0, 0);
vtkSphere->SetPhiResolution(20);
vtkSphere->SetThetaResolution(20);
vtkSphere->Update();
mitk::Surface::Pointer zoneSurface = dynamic_cast<mitk::Surface *>(m_AblationZonesVector.at(id)->GetData());
zoneSurface->SetVtkPolyData(vtkSphere->GetOutput());
}
void QmitkUSNavigationMarkerPlacement::OnAddAblationZone(int size)
{
m_AblationZonesDisplacementFilter->SetInitialReferencePose(
m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex));
mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New();
mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition();
MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin;
mitk::Surface::Pointer zone = mitk::Surface::New();
// create a vtk sphere with given radius
vtkSmartPointer<vtkSphereSource> vtkSphere = vtkSmartPointer<vtkSphereSource>::New();
vtkSphere->SetRadius(size / 2);
vtkSphere->SetCenter(0, 0, 0);
vtkSphere->SetPhiResolution(20);
vtkSphere->SetThetaResolution(20);
vtkSphere->Update();
zone->SetVtkPolyData(vtkSphere->GetOutput());
// set vtk sphere and origin to data node (origin must be set
// again, because of the new sphere set as data)
NewAblationZone->SetData(zone);
NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin);
mitk::Color SphereColor = mitk::Color();
// default color
SphereColor[0] = 102;
SphereColor[1] = 0;
SphereColor[2] = 204;
NewAblationZone->SetColor(SphereColor);
NewAblationZone->SetOpacity(0.3);
// set name of zone
std::stringstream name;
name << "Ablation Zone" << m_AblationZonesVector.size();
NewAblationZone->SetName(name.str());
// add zone to filter
m_AblationZonesDisplacementFilter->AddNode(NewAblationZone);
m_AblationZonesVector.push_back(NewAblationZone);
this->GetDataStorage()->Add(NewAblationZone);
}
void QmitkUSNavigationMarkerPlacement::CreateQtPartControl(QWidget *parent)
{
m_Parent = parent;
ui->setupUi(parent);
connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment()));
connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment()));
connect(ui->m_enableNavigationLayout, SIGNAL(clicked()), this, SLOT(OnChangeLayoutClicked()));
connect(ui->m_RenderWindowSelection, SIGNAL(valueChanged(int)), this, SLOT(OnRenderWindowSelection()));
connect(ui->m_RefreshView, SIGNAL(clicked()), this, SLOT(OnRefreshView()));
m_BaseNode = this->GetDataStorage()->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE);
if (m_BaseNode.IsNull())
{
m_BaseNode = mitk::DataNode::New();
m_BaseNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_BASENODE);
this->GetDataStorage()->Add(m_BaseNode);
}
connect(ui->m_CtToUsRegistrationWidget, SIGNAL(GetCursorPosition()), this, SLOT(OnGetCursorPosition()));
connect(ui->m_CtToUsRegistrationWidget, SIGNAL(ActualizeCtToUsRegistrationWidget()), this, SLOT(OnActualizeCtToUsRegistrationWidget()));
connect(ui->m_initializeCtToUsRegistration, SIGNAL(clicked()), this, SLOT(OnInitializeCtToUsRegistration()));
connect(ui->m_initializeTargetMarking, SIGNAL(clicked()), this, SLOT(OnInitializeTargetMarking()));
connect(ui->m_initializeCritStructureMarking, SIGNAL(clicked()), this, SLOT(OnInitializeCriticalStructureMarking()));
connect(ui->m_initializeNavigation, SIGNAL(clicked()), this, SLOT(OnInitializeNavigation()));
// indicate that no experiment is running at start
ui->runningLabel->setPixmap(m_IconNotRunning);
connect(ui->m_settingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer<mitk::DataNode>)),
this, SLOT(OnSettingsChanged(itk::SmartPointer<mitk::DataNode>)));
}
void QmitkUSNavigationMarkerPlacement::ReInitializeSettingsNodesAndImageStream()
{
//If update timer is not stopped (signals stopped), setting the m_CombinedModality
// will cause a crash of the workbench in some times.
m_UpdateTimer->blockSignals(true);
m_UpdateTimer->stop();
m_SettingsNode = mitk::DataNode::New();
ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true);
InitImageStream();
m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality();
// Having set the m_CombinedModality reactivate the update timer again
m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second
m_UpdateTimer->blockSignals(false);
}
void QmitkUSNavigationMarkerPlacement::OnGetCursorPosition()
{
auto centroid = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetSelectedPosition();
ui->m_CtToUsRegistrationWidget->OnCalculateTRE(centroid);
}
void QmitkUSNavigationMarkerPlacement::OnActualizeCtToUsRegistrationWidget()
{
m_SettingsNode = mitk::DataNode::New();
ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true);
this->InitImageStream();
if (ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality().IsNull())
{
return;
}
ui->m_CtToUsRegistrationWidget->SetCombinedModality(
ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality());
m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality();
if (!m_StdMultiWidget)
{
// try to get the standard multi widget if it couldn't be got before
mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast<QmitkStdMultiWidgetEditor *>(renderWindowPart);
// if there is a standard multi widget now, disable the level window and
// change the layout to 2D up and 3d down
if (multiWidgetEditor)
{
m_StdMultiWidget = dynamic_cast<QmitkStdMultiWidget *>(multiWidgetEditor->GetMultiWidget());
multiWidgetEditor->ShowLevelWindowWidget(false);
SetTwoWindowView();
}
}
else
{
this->OnRefreshView();
}
m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second
}
void QmitkUSNavigationMarkerPlacement::OnInitializeCtToUsRegistration()
{
ui->m_CtToUsRegistrationWidget->SetDataStorage(this->GetDataStorage());
ui->m_CtToUsRegistrationWidget->OnSettingsChanged(m_SettingsNode);
ui->m_CtToUsRegistrationWidget->OnActivateStep();
ui->m_CtToUsRegistrationWidget->OnStartStep();
ui->m_CtToUsRegistrationWidget->Update();
}
void QmitkUSNavigationMarkerPlacement::OnInitializeTargetMarking()
{
ReInitializeSettingsNodesAndImageStream();
ui->m_TargetMarkingWidget->SetCombinedModality(m_CombinedModality);
ui->m_TargetMarkingWidget->SetDataStorage(this->GetDataStorage());
ui->m_TargetMarkingWidget->OnSettingsChanged(m_SettingsNode);
ui->m_TargetMarkingWidget->OnActivateStep();
ui->m_TargetMarkingWidget->OnStartStep();
ui->m_TargetMarkingWidget->Update();
}
void QmitkUSNavigationMarkerPlacement::OnInitializeCriticalStructureMarking()
{
ReInitializeSettingsNodesAndImageStream();
ui->m_CriticalStructuresWidget->SetCombinedModality(m_CombinedModality);
ui->m_CriticalStructuresWidget->SetDataStorage(this->GetDataStorage());
ui->m_CriticalStructuresWidget->OnSettingsChanged(m_SettingsNode);
ui->m_CriticalStructuresWidget->OnActivateStep();
ui->m_CriticalStructuresWidget->OnStartStep();
ui->m_CriticalStructuresWidget->Update();
}
void QmitkUSNavigationMarkerPlacement::OnInitializeNavigation()
{
ReInitializeSettingsNodesAndImageStream();
ui->m_NavigationWidget->SetCombinedModality(m_CombinedModality);
ui->m_NavigationWidget->SetDataStorage(this->GetDataStorage());
ui->m_NavigationWidget->OnSettingsChanged(m_SettingsNode);
ui->m_NavigationWidget->OnActivateStep();
ui->m_NavigationWidget->OnStartStep();
ui->m_NavigationWidget->Update();
// test if it is tracked US, if yes add visualization filter
if (m_CombinedModality->GetIsTrackedUltrasoundActive())
{
m_InstrumentNode = mitk::DataNode::New();
m_InstrumentNode->SetName("Tracked US Instrument");
m_InstrumentNode->SetData(
m_CombinedModality->GetNavigationDataSource()->GetToolMetaData(0)->GetToolSurface()->Clone());
this->GetDataStorage()->Add(m_InstrumentNode);
m_ToolVisualizationFilter = mitk::NavigationDataObjectVisualizationFilter::New();
m_ToolVisualizationFilter->ConnectTo(m_CombinedModality->GetNavigationDataSource());
m_ToolVisualizationFilter->SetRepresentationObject(0, m_InstrumentNode->GetData()); //caution: currently hard coded that instrument has id 0
//set dummy objects to avoid spamming of console
mitk::Surface::Pointer dummyObject = mitk::Surface::New();
m_ToolVisualizationFilter->SetRepresentationObject(1, dummyObject.GetPointer());
m_ToolVisualizationFilter->SetRepresentationObject(2, dummyObject.GetPointer());
}
}
void QmitkUSNavigationMarkerPlacement::InitImageStream()
{
if (m_ImageStreamNode.IsNull())
{
m_ImageStreamNode = mitk::DataNode::New();
m_ImageStreamNode->SetName("US Navigation Viewing Stream");
this->GetDataStorage()->Add(m_ImageStreamNode);
}
}
void QmitkUSNavigationMarkerPlacement::OnCombinedModalityPropertyChanged(const std::string &key, const std::string &)
{
if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH)
{
m_ReinitAlreadyDone = false;
this->ReinitOnImage();
if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus())
{
mitk::LayoutAnnotationRenderer::AddAnnotation(
m_WarnOverlay.GetPointer(), "stdmulti.widget0", mitk::LayoutAnnotationRenderer::TopLeft);
MITK_WARN << "No calibration available for the selected ultrasound image depth.";
}
}
}
void QmitkUSNavigationMarkerPlacement::SetFocus()
{
this->ReinitOnImage();
}
void QmitkUSNavigationMarkerPlacement::OnTimeout()
{
if (m_CombinedModality.IsNull())
return;
m_CombinedModality->Modified(); // shouldn't be nessecary ... fix in abstract ultrasound tracker device!
m_CombinedModality->Update();
if (m_ToolVisualizationFilter.IsNotNull())
{
m_ToolVisualizationFilter->Update();
}
ui->m_CtToUsRegistrationWidget->Update();
ui->m_TargetMarkingWidget->Update();
ui->m_CriticalStructuresWidget->Update();
ui->m_NavigationWidget->Update();
mitk::Image::Pointer image = m_CombinedModality->GetOutput();
// make sure that always the current image is set to the data node
if (image.IsNotNull() && m_ImageStreamNode->GetData() != image.GetPointer() && image->IsInitialized())
{
m_ImageStreamNode->SetData(image);
}
if (!m_StdMultiWidget)
{
// try to get the standard multi widget if it couldn't be got before
mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast<QmitkStdMultiWidgetEditor*>(renderWindowPart);
// if there is a standard multi widget now, disable the level window and
// change the layout to 2D up and 3d down
if (multiWidgetEditor)
{
m_StdMultiWidget = dynamic_cast<QmitkStdMultiWidget*>(multiWidgetEditor->GetMultiWidget());
multiWidgetEditor->ShowLevelWindowWidget(false);
SetTwoWindowView();
}
this->CreateOverlays();
}
if (m_CombinedModality.IsNotNull() && !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing
{
m_AblationZonesDisplacementFilter->Update();
// update the 3D window only every fourth time to speed up the rendering (at least in 2D)
this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS);
// make sure that a reinit was performed on the image
this->ReinitOnImage();
}
}
void QmitkUSNavigationMarkerPlacement::OnEnableNavigationLayout()
{
MITK_INFO << "Navigation Layout";
// try to get the standard multi widget if it couldn't be got before
mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast<QmitkStdMultiWidgetEditor*>(renderWindowPart);
// if there is a standard multi widget now, disable the level window and
// change the layout to 2D up and 3d down
if (multiWidgetEditor)
{
m_StdMultiWidget = dynamic_cast<QmitkStdMultiWidget*>(multiWidgetEditor->GetMultiWidget());
multiWidgetEditor->ShowLevelWindowWidget(false);
SetTwoWindowView();
}
}
void QmitkUSNavigationMarkerPlacement::OnRenderWindowSelection()
{
SetTwoWindowView();
}
void QmitkUSNavigationMarkerPlacement::OnRefreshView()
{
if (!ui->m_enableNavigationLayout->isChecked())
OnResetStandardLayout();
else
{
// Reinit the US Image Stream (this might be broken if there was a global reinit somewhere...)
try
{
mitk::RenderingManager::GetInstance()->InitializeViews( // Reinit
this
->GetDataStorage() // GetDataStorage
->GetNamedNode("US Viewing Stream - Image 0")
->GetData()
->GetTimeGeometry()); // GetNode
}
catch (...)
{
MITK_DEBUG << "No reinit possible";
}
SetTwoWindowView();
}
}
void QmitkUSNavigationMarkerPlacement::SetTwoWindowView()
{
if (m_StdMultiWidget)
{
int i, j, k;
switch (this->ui->m_RenderWindowSelection->value())
{
case 1:
mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToCaudal();
i = 1;
j = 2; // other windows
k = 0;
break;
case 2:
mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToSinister();
i = 0;
j = 2;
k = 1;
break;
case 3:
mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToAnterior();
i = 1;
j = 0;
k = 2;
break;
default:
return;
}
// get the render window which is defined by index "k" and set it as "current render window widget"
// chose the layout that will set the current 2D window as top render window and the 3D windows as bottom render window
auto renderWindowWidget = m_StdMultiWidget->GetRenderWindowWidget(m_StdMultiWidget->GetNameFromIndex(k));
m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetCurrentRenderWindowWidget(renderWindowWidget.get());
m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetOneTop3DBottomLayout();
////Crosshair invisible in 3D view
this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")
->SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")
->SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(k) + ".plane")
->SetBoolProperty("visible", true, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4")));
this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")
->SetIntProperty("Crosshair.Gap Size", 0);
this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")
->SetIntProperty("Crosshair.Gap Size", 0);
}
}
void QmitkUSNavigationMarkerPlacement::OnResetStandardLayout()
{
if (m_StdMultiWidget)
{
//reset render windows
m_StdMultiWidget->SetCrosshairVisibility(true);
m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetDefaultLayout();
}
}
void QmitkUSNavigationMarkerPlacement::OnChangeLayoutClicked()
{
if (ui->m_enableNavigationLayout->isChecked())
OnEnableNavigationLayout();
else
OnResetStandardLayout();
}
void QmitkUSNavigationMarkerPlacement::OnImageAndNavigationDataLoggingTimeout()
{
// update filter for logging navigation data and ultrasound images
if (m_CombinedModality.IsNotNull())
{
m_NavigationDataRecorder->Update();
// get last messages for logging filer and store them
std::vector<std::string> messages = m_LoggingBackend.GetNavigationMessages();
std::string composedMessage = "";
for (std::size_t i = 0; i < messages.size(); i++)
{
composedMessage += messages.at(i);
}
m_USImageLoggingFilter->AddMessageToCurrentImage(composedMessage);
m_LoggingBackend.ClearNavigationMessages();
// update logging filter
m_USImageLoggingFilter->Update();
}
}
void QmitkUSNavigationMarkerPlacement::OnStartExperiment()
{
// get name for the experiment by a QInputDialog
bool ok;
if (m_ExperimentName.isEmpty())
{ // default: current date
m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" +
QString::number(QDateTime::currentDateTime().date().month()) + "_" +
QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" +
QString::number(QDateTime::currentDateTime().time().hour()) + "." +
QString::number(QDateTime::currentDateTime().time().minute());
}
m_ExperimentName = QInputDialog::getText(
m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok);
MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString();
if (ok && !m_ExperimentName.isEmpty())
{
// display error message and call the function recursively if a directory
// with the given name already exists
QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName);
if (experimentResultsDir.exists())
{
QMessageBox::critical(
m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name.");
this->OnStartExperiment();
}
else
{
QDir(m_ResultsDirectory).mkdir(m_ExperimentName);
m_ExperimentResultsSubDirectory = m_ResultsDirectory + QDir::separator() + m_ExperimentName;
// experiment is running now
ui->runningLabel->setPixmap(m_IconRunning);
// (re)start timer for navigation step durations
m_NavigationStepTimer->Reset();
m_NavigationStepTimer->SetOutputFileName(
QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString());
m_NavigationStepTimer->SetActiveIndex(0, "Initialization");
ui->finishExperimentButton->setEnabled(true);
ui->startExperimentButton->setDisabled(true);
// initialize and register logging backend
QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt";
m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString());
- mbilog::RegisterBackend(&m_LoggingBackend);
+ mitk::RegisterBackend(&m_LoggingBackend);
// initialize and start navigation data recorder form xml recording
m_NavigationDataRecorder->StartRecording();
m_IsExperimentRunning = true;
m_ImageAndNavigationDataLoggingTimer->start(1000);
}
}
}
void QmitkUSNavigationMarkerPlacement::OnFinishExperiment()
{
this->WaitCursorOn();
MITK_INFO("USNavigationLogging") << "Experiment finished!";
MITK_INFO("USNavigationLogging") << "Position/Orientation of needle tip: "
<< (dynamic_cast<mitk::NavigationData *>(
m_CombinedModality->GetTrackingDeviceDataSource()->GetOutput(0)))
->GetPosition();
MITK_INFO("USNavigationLogging")
<< "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition();
MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration();
m_ImageAndNavigationDataLoggingTimer->stop();
ui->runningLabel->setPixmap(m_IconNotRunning);
m_NavigationStepTimer->Stop();
ui->finishExperimentButton->setDisabled(true);
ui->startExperimentButton->setEnabled(true);
MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString();
// save ultrasound images to the file system
QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream");
m_USImageLoggingFilter->Update();
m_USImageLoggingFilter->SetImageFilesExtension(".jpg");
m_USImageLoggingFilter->SaveImages(
QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString());
m_USImageLoggingFilter = mitk::USImageLoggingFilter::New();
m_NavigationDataRecorder->StopRecording();
// Write data to csv and xml file
mitk::IOUtil::Save(
m_NavigationDataRecorder->GetNavigationDataSet(),
(QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.xml").toStdString().c_str()));
mitk::IOUtil::Save(
m_NavigationDataRecorder->GetNavigationDataSet(),
(QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.csv").toStdString().c_str()));
// write logged navigation data messages to separate file
std::stringstream csvNavigationMessagesFilename;
csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1()
<< "CSVNavigationMessagesLogFile.csv";
MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: "
<< csvNavigationMessagesFilename.str();
m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str());
- mbilog::UnregisterBackend(&m_LoggingBackend);
+ mitk::UnregisterBackend(&m_LoggingBackend);
m_IsExperimentRunning = false;
m_ImageAndNavigationDataLoggingTimer->stop();
m_CombinedModality = nullptr;
// reset scene number for next experiment
m_SceneNumber = 1;
this->WaitCursorOff();
MITK_INFO("USNavigationLogging") << "Finished!";
}
void QmitkUSNavigationMarkerPlacement::OnSettingsChanged(itk::SmartPointer<mitk::DataNode> settings)
{
// initialize gui according to the experiment mode setting
bool experimentMode = false;
settings->GetBoolProperty("settings.experiment-mode", experimentMode);
ui->startExperimentButton->setVisible(experimentMode);
ui->finishExperimentButton->setVisible(experimentMode);
ui->runningLabel->setVisible(experimentMode);
if (experimentMode && !m_IsExperimentRunning)
{
ui->runningLabel->setPixmap(m_IconNotRunning);
}
else if (!experimentMode)
{
if (m_IsExperimentRunning)
{
this->OnFinishExperiment();
}
}
// get the results directory from the settings and use home directory if
// there is no results directory configured
std::string resultsDirectory;
if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory))
{
m_ResultsDirectory = QString::fromStdString(resultsDirectory);
}
else
{
m_ResultsDirectory = QDir::homePath();
}
// make sure that the results directory exists
QDir resultsDirectoryQDir = QDir(m_ResultsDirectory);
if (!resultsDirectoryQDir.exists())
{
resultsDirectoryQDir.mkpath(m_ResultsDirectory);
}
MITK_INFO("USNavigation") << "Results Directory: " << m_ResultsDirectory.toStdString();
}
void QmitkUSNavigationMarkerPlacement::ReinitOnImage()
{
if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull())
{
// make sure that the output is already calibrated correctly
// (if the zoom level was changed recently)
m_CombinedModality->Modified();
m_CombinedModality->Update();
mitk::Image::Pointer image = m_CombinedModality->GetOutput();
if (image.IsNotNull() && image->IsInitialized())
{
// make a reinit on the ultrasound image
mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart();
if (renderWindowPart != nullptr && image->GetTimeGeometry()->IsValid())
{
renderWindowPart->GetRenderingManager()->InitializeViews(image->GetTimeGeometry());
}
this->RequestRenderWindowUpdate();
m_ReinitAlreadyDone = true;
}
}
}
void QmitkUSNavigationMarkerPlacement::Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes)
{
for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it)
{
if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0)
{
// convert image to 3d image if it is 2d at the moment
mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(it->Value()->GetData());
if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable())
{
mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New();
convert2DTo3DImageFilter->SetInput(image);
convert2DTo3DImageFilter->Update();
it->Value()->SetData(convert2DTo3DImageFilter->GetOutput());
}
}
}
}
void QmitkUSNavigationMarkerPlacement::CreateOverlays()
{
// initialize warning overlay (and do not display it, yet)
m_WarnOverlay->SetText("Warning: No calibration available for current depth.");
// set position and font size for the text overlay
// (nonesense postition as a layouter is used, but it ignored
// the overlay without setting a position here)
mitk::Point2D overlayPosition;
overlayPosition.SetElement(0, -50.0f);
overlayPosition.SetElement(1, -50.0f);
m_WarnOverlay->SetPosition2D(overlayPosition);
m_WarnOverlay->SetFontSize(22);
m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red
}
void QmitkUSNavigationMarkerPlacement::UpdateToolStorage()
{
if (m_NavigationDataSource.IsNull())
{
m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource();
}
if (m_NavigationDataSource.IsNull())
{
MITK_WARN << "Found an invalid navigation data source object!";
}
us::ModuleContext *context = us::GetModuleContext();
std::string id = m_NavigationDataSource->US_PROPKEY_ID;
std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")";
// Get Storage
std::vector<us::ServiceReference<mitk::NavigationToolStorage>> refs =
context->GetServiceReferences<mitk::NavigationToolStorage>();
m_CurrentStorage = context->GetService(refs.front());
if (m_CurrentStorage.IsNull())
{
MITK_WARN << "Found an invalid storage object!";
}
else if (m_CurrentStorage->GetToolCount() !=
m_NavigationDataSource->GetNumberOfOutputs()) // there is something wrong with the storage
{
MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This "
"storage won't be used because it isn't the right one.";
m_CurrentStorage = nullptr;
}
}
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp
index 33ea45cd1a..82feb76914 100644
--- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp
+++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp
@@ -1,1437 +1,1437 @@
/*============================================================================
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.
============================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkMITKIGTTrackingToolboxView.h"
// Qt
#include <QMessageBox>
#include <QSettings>
-#include <qfiledialog.h>
+#include <QFileDialog>
// MITK
#include <mitkNavigationToolStorageDeserializer.h>
#include <mitkTrackingVolumeGenerator.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNavigationToolStorageSerializer.h>
#include <mitkIOUtil.h>
-#include <mitkLog.h>
+#include <mitkLogBackend.h>
#include <mitkTrackingDeviceTypeCollection.h>
#include <mitkUnspecifiedTrackingTypeInformation.h>
#include <mitkNeedleProjectionFilter.h>
//for exceptions
#include <mitkIGTException.h>
#include <mitkIGTIOException.h>
#include "mitkPluginActivator.h"
const std::string QmitkMITKIGTTrackingToolboxView::VIEW_ID = "org.mitk.views.mitkigttrackingtoolbox";
QmitkMITKIGTTrackingToolboxView::QmitkMITKIGTTrackingToolboxView()
: QmitkAbstractView()
, m_Controls(nullptr)
, m_DeviceTypeCollection(nullptr)
, m_ToolProjectionNode(nullptr)
{
m_TrackingLoggingTimer = new QTimer(this);
m_TrackingRenderTimer = new QTimer(this);
m_TimeoutTimer = new QTimer(this);
m_tracking = false;
m_connected = false;
m_logging = false;
m_ShowHideToolAxis = false;
m_loggedFrames = 0;
m_SimpleModeEnabled = false;
m_NeedleProjectionFilter = mitk::NeedleProjectionFilter::New();
//create filename for autosaving of tool storage
- QString loggingPathWithoutFilename = QString(mitk::LoggingBackend::GetLogFile().c_str());
+ auto loggingPathWithoutFilename = QString::fromStdString(mitk::LogBackend::GetLogFile());
if (!loggingPathWithoutFilename.isEmpty()) //if there already is a path for the MITK logging file use this one
{
//extract path from path+filename (if someone knows a better way to do this feel free to change it)
- int lengthOfFilename = QFileInfo(QString::fromStdString(mitk::LoggingBackend::GetLogFile())).fileName().size();
+ int lengthOfFilename = QFileInfo(QString::fromStdString(mitk::LogBackend::GetLogFile())).fileName().size();
loggingPathWithoutFilename.resize(loggingPathWithoutFilename.size() - lengthOfFilename);
m_AutoSaveFilename = loggingPathWithoutFilename + "TrackingToolboxAutoSave.IGTToolStorage";
}
else //if not: use a temporary path from IOUtil
{
m_AutoSaveFilename = QString(mitk::IOUtil::GetTempPath().c_str()) + "TrackingToolboxAutoSave.IGTToolStorage";
}
MITK_INFO("IGT Tracking Toolbox") << "Filename for auto saving of IGT ToolStorages: " << m_AutoSaveFilename.toStdString();
//! [Thread 1]
//initialize worker thread
m_WorkerThread = new QThread();
m_Worker = new QmitkMITKIGTTrackingToolboxViewWorker();
//! [Thread 1]
ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext();
if (pluginContext)
{
QString interfaceName = QString::fromStdString(us_service_interface_iid<mitk::TrackingDeviceTypeCollection>());
QList<ctkServiceReference> serviceReference = pluginContext->getServiceReferences(interfaceName);
if (serviceReference.size() > 0)
{
m_DeviceTypeServiceReference = serviceReference.at(0);
const ctkServiceReference& r = serviceReference.at(0);
m_DeviceTypeCollection = pluginContext->getService<mitk::TrackingDeviceTypeCollection>(r);
}
else
{
MITK_INFO << "No Tracking Device Collection!";
}
}
}
QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView()
{
this->StoreUISettings();
m_TrackingLoggingTimer->stop();
m_TrackingRenderTimer->stop();
m_TimeoutTimer->stop();
delete m_TrackingLoggingTimer;
delete m_TrackingRenderTimer;
delete m_TimeoutTimer;
try
{
//! [Thread 2]
// wait for thread to finish
m_WorkerThread->terminate();
m_WorkerThread->wait();
//clean up worker thread
if (m_WorkerThread) { delete m_WorkerThread; }
if (m_Worker) { delete m_Worker; }
//! [Thread 2]
//remove the tracking volume
this->GetDataStorage()->Remove(m_TrackingVolumeNode);
//unregister microservices
if (m_toolStorage) { m_toolStorage->UnRegisterMicroservice(); }
if (m_IGTLMessageProvider.IsNotNull()){ m_IGTLMessageProvider->UnRegisterMicroservice(); }
}
catch (std::exception& e) { MITK_WARN << "Unexpected exception during clean up of tracking toolbox view: " << e.what(); }
catch (...) { MITK_WARN << "Unexpected unknown error during clean up of tracking toolbox view!"; }
//store tool storage and UI settings for persistence
this->AutoSaveToolStorage();
this->StoreUISettings();
m_DeviceTypeCollection = nullptr;
mitk::PluginActivator::GetContext()->ungetService(m_DeviceTypeServiceReference);
}
void QmitkMITKIGTTrackingToolboxView::CreateQtPartControl(QWidget *parent)
{
// build up qt view, unless already done
if (!m_Controls)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkMITKIGTTrackingToolboxViewControls;
m_Controls->setupUi(parent);
//create connections
connect(m_Controls->m_LoadTools, SIGNAL(clicked()), this, SLOT(OnLoadTools()));
connect(m_Controls->m_ConnectDisconnectButton, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect()));
connect(m_Controls->m_StartStopTrackingButton, SIGNAL(clicked()), this, SLOT(OnStartStopTracking()));
connect(m_Controls->m_ConnectSimpleMode, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect()));
connect(m_Controls->m_StartTrackingSimpleMode, SIGNAL(clicked()), this, SLOT(OnStartStopTracking()));
connect(m_Controls->m_FreezeUnfreezeTrackingButton, SIGNAL(clicked()), this, SLOT(OnFreezeUnfreezeTracking()));
connect(m_TrackingLoggingTimer, SIGNAL(timeout()), this, SLOT(UpdateLoggingTrackingTimer()));
connect(m_TrackingRenderTimer, SIGNAL(timeout()), this, SLOT(UpdateRenderTrackingTimer()));
connect(m_TimeoutTimer, SIGNAL(timeout()), this, SLOT(OnTimeOut()));
connect(m_Controls->m_ChooseFile, SIGNAL(clicked()), this, SLOT(OnChooseFileClicked()));
connect(m_Controls->m_StartLogging, SIGNAL(clicked()), this, SLOT(StartLogging()));
connect(m_Controls->m_StopLogging, SIGNAL(clicked()), this, SLOT(StopLogging()));
connect(m_Controls->m_VolumeSelectionBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(OnTrackingVolumeChanged(QString)));
connect(m_Controls->m_ShowTrackingVolume, SIGNAL(clicked()), this, SLOT(OnShowTrackingVolumeChanged()));
connect(m_Controls->m_AutoDetectTools, SIGNAL(clicked()), this, SLOT(OnAutoDetectTools()));
connect(m_Controls->m_ResetTools, SIGNAL(clicked()), this, SLOT(OnResetTools()));
connect(m_Controls->m_AddSingleTool, SIGNAL(clicked()), this, SLOT(OnAddSingleTool()));
connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(NavigationToolFinished()), this, SLOT(OnAddSingleToolFinished()));
connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(Canceled()), this, SLOT(OnAddSingleToolCanceled()));
connect(m_Controls->m_CsvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension()));
connect(m_Controls->m_XmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension()));
connect(m_Controls->m_UseDifferentUpdateRates, SIGNAL(clicked()), this, SLOT(OnToggleDifferentUpdateRates()));
connect(m_Controls->m_RenderUpdateRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangeRenderUpdateRate()));
connect(m_Controls->m_DisableAllTimers, SIGNAL(stateChanged(int)), this, SLOT(EnableDisableTimerButtons(int)));
connect(m_Controls->m_advancedUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode()));
connect(m_Controls->m_SimpleUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode()));
connect(m_Controls->showHideToolProjectionCheckBox, SIGNAL(clicked()), this, SLOT(OnShowHideToolProjectionClicked()));
connect(m_Controls->showHideToolAxisCheckBox, SIGNAL(clicked()), this, SLOT(OnShowHideToolAxisClicked()));
connect(m_Controls->m_toolselector, SIGNAL(currentIndexChanged(int)), this, SLOT(SelectToolProjection(int)));
//connections for the tracking device configuration widget
connect(m_Controls->m_ConfigurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged()));
//! [Thread 3]
//connect worker thread
connect(m_Worker, SIGNAL(AutoDetectToolsFinished(bool, QString)), this, SLOT(OnAutoDetectToolsFinished(bool, QString)));
connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), this, SLOT(OnConnectFinished(bool, QString)));
connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), this, SLOT(OnStartTrackingFinished(bool, QString)));
connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), this, SLOT(OnStopTrackingFinished(bool, QString)));
connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), this, SLOT(OnDisconnectFinished(bool, QString)));
connect(m_WorkerThread, SIGNAL(started()), m_Worker, SLOT(ThreadFunc()));
connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnConnected(bool)));
connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnDisconnected(bool)));
connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnStartTracking(bool)));
connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnStopTracking(bool)));
//Add Listener, so that we know when the toolStorage changed.
std::string m_Filter = "(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.NavigationToolStorage" + ")";
mitk::PluginActivator::GetContext()->connectServiceListener(this, "OnToolStorageChanged", QString(m_Filter.c_str()));
//move the worker to the thread
m_Worker->moveToThread(m_WorkerThread);
//! [Thread 3]
//initialize widgets
m_Controls->m_TrackingToolsStatusWidget->SetShowPositions(true);
m_Controls->m_TrackingToolsStatusWidget->SetTextAlignment(Qt::AlignLeft);
m_Controls->m_simpleWidget->setVisible(false);
//initialize tracking volume node
m_TrackingVolumeNode = mitk::DataNode::New();
m_TrackingVolumeNode->SetName("TrackingVolume");
m_TrackingVolumeNode->SetBoolProperty("Backface Culling", true);
mitk::Color red;
red.SetRed(1);
m_TrackingVolumeNode->SetColor(red);
//initialize buttons
m_Controls->m_AutoDetectTools->setVisible(false); //only visible if supported by tracking device
m_Controls->m_StartStopTrackingButton->setEnabled(false);
m_Controls->m_StartTrackingSimpleMode->setEnabled(false);
m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false);
//initialize warning labels
m_Controls->m_RenderWarningLabel->setVisible(false);
m_Controls->m_TrackingFrozenLabel->setVisible(false);
//initialize projection buttons
//first it is disabled when the tool is connected check box for projection and axis is enabled
m_Controls->showHideToolAxisCheckBox->setEnabled(false);
m_Controls->showHideToolProjectionCheckBox->setEnabled(false);
m_Controls->m_toolselector->setEnabled(false);
//Update List of available models for selected tool.
std::vector<mitk::TrackingDeviceData> Compatibles;
if ((m_Controls == nullptr) || //check all these stuff for NULL, latterly this causes crashes from time to time
(m_Controls->m_ConfigurationWidget == nullptr) ||
(m_Controls->m_ConfigurationWidget->GetTrackingDevice().IsNull()))
{
MITK_ERROR << "Couldn't get current tracking device or an object is nullptr, something went wrong!";
return;
}
else
{
Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType());
}
m_Controls->m_VolumeSelectionBox->clear();
for (std::size_t i = 0; i < Compatibles.size(); i++)
{
m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str());
}
//initialize tool storage
m_toolStorage = mitk::NavigationToolStorage::New(GetDataStorage());
m_toolStorage->SetName("TrackingToolbox Default Storage");
m_toolStorage->RegisterAsMicroservice();
//set home directory as default path for logfile
m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(QDir::homePath()) + QDir::separator() + "logfile.csv");
//tracking device may be changed already by the persistence of the
//QmitkTrackingDeciveConfigurationWidget
this->OnTrackingDeviceChanged();
this->LoadUISettings();
//add tracking volume node only to data storage
this->GetDataStorage()->Add(m_TrackingVolumeNode);
if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0);
else m_TrackingVolumeNode->SetOpacity(0.25);
//Update List of available models for selected tool.
m_Controls->m_VolumeSelectionBox->clear();
for (std::size_t i = 0; i < Compatibles.size(); i++)
{
m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str());
}
}
}
void QmitkMITKIGTTrackingToolboxView::OnLoadTools()
{
//read in filename
QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Tool Storage"), "/", tr("Tool Storage Files (*.IGTToolStorage)"));
if (filename.isNull()) return;
//read tool storage from disk
std::string errorMessage = "";
mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage());
// try-catch block for exceptions
try
{
this->ReplaceCurrentToolStorage(myDeserializer->Deserialize(filename.toStdString()), filename.toStdString());
}
catch (mitk::IGTException&)
{
std::string errormessage = "Error during loading the tool storage file. Please only load tool storage files created with the NavigationToolManager view.";
QMessageBox::warning(nullptr, "Tool Storage Loading Error", errormessage.c_str());
return;
}
if (m_toolStorage->isEmpty())
{
errorMessage = myDeserializer->GetErrorMessage();
MessageBox(errorMessage);
return;
}
//update label
UpdateToolStorageLabel(filename);
//update tool preview
m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels();
m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage);
//save filename for persistent storage
m_ToolStorageFilename = filename;
}
void QmitkMITKIGTTrackingToolboxView::OnResetTools()
{
//remove data nodes of surfaces from data storage to clean up
for (unsigned int i = 0; i < m_toolStorage->GetToolCount(); i++)
{
this->GetDataStorage()->Remove(m_toolStorage->GetTool(i)->GetDataNode());
}
this->ReplaceCurrentToolStorage(mitk::NavigationToolStorage::New(GetDataStorage()), "TrackingToolbox Default Storage");
m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels();
QString toolLabel = QString("<none>");
m_Controls->m_ToolLabel->setText(toolLabel);
m_ToolStorageFilename = "";
RemoveAllToolProjections();
}
void QmitkMITKIGTTrackingToolboxView::OnStartStopTracking()
{
if (!m_connected)
{
MITK_WARN << "Can't start tracking if no device is connected. Aborting";
return;
}
if (m_tracking) { OnStopTracking(); }
else { OnStartTracking(); }
}
void QmitkMITKIGTTrackingToolboxView::OnFreezeUnfreezeTracking()
{
if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Freeze Tracking")
{
m_Worker->GetTrackingDeviceSource()->Freeze();
m_Controls->m_FreezeUnfreezeTrackingButton->setText("Unfreeze Tracking");
m_Controls->m_TrackingFrozenLabel->setVisible(true);
}
else if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Unfreeze Tracking")
{
m_Worker->GetTrackingDeviceSource()->UnFreeze();
m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking");
m_Controls->m_TrackingFrozenLabel->setVisible(false);
}
}
void QmitkMITKIGTTrackingToolboxView::ShowToolProjection(int index)
{
mitk::DataNode::Pointer toolnode = m_toolStorage->GetTool(index)->GetDataNode();
QString ToolProjectionName = "ToolProjection" + QString::number(index);
m_ToolProjectionNode = this->GetDataStorage()->GetNamedNode(ToolProjectionName.toStdString());
//If node does not exist, create the node for the Pointset
if (m_ToolProjectionNode.IsNull())
{
m_ToolProjectionNode = mitk::DataNode::New();
m_ToolProjectionNode->SetName(ToolProjectionName.toStdString());
if (index < static_cast<int>(m_NeedleProjectionFilter->GetNumberOfInputs()))
{
m_NeedleProjectionFilter->SelectInput(index);
m_NeedleProjectionFilter->Update();
m_ToolProjectionNode->SetData(m_NeedleProjectionFilter->GetProjection());
m_ToolProjectionNode->SetBoolProperty("show contour", true);
this->GetDataStorage()->Add(m_ToolProjectionNode, toolnode);
}
// this->FireNodeSelected(node);
}
else
{
m_ToolProjectionNode->SetBoolProperty("show contour", true);
}
}
void QmitkMITKIGTTrackingToolboxView::RemoveAllToolProjections()
{
for (size_t i = 0; i < m_toolStorage->GetToolCount(); i++)
{
QString toolProjectionName = "ToolProjection" + QString::number(i);
mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode(toolProjectionName.toStdString());
//Deactivate and hide the tool projection
if (!node.IsNull())
{
this->GetDataStorage()->Remove(node);
}
}
}
void QmitkMITKIGTTrackingToolboxView::SelectToolProjection(int idx)
{
if (m_Controls->showHideToolProjectionCheckBox->isChecked())
{
//Deactivate and hide the tool projection
if (!m_ToolProjectionNode.IsNull())
{
this->GetDataStorage()->Remove(m_ToolProjectionNode);
}
if (m_NeedleProjectionFilter.IsNotNull())
{
m_NeedleProjectionFilter->Update();
}
//Refresh the view and the status widget
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// Show the tool projection for the currently selected tool
ShowToolProjection(idx);
}
}
void QmitkMITKIGTTrackingToolboxView::OnShowHideToolProjectionClicked()
{
int index = m_Controls->m_toolselector->currentIndex();
//Activate and show the tool projection
if (m_Controls->showHideToolProjectionCheckBox->isChecked())
{
ShowToolProjection(index);
m_Controls->showHideToolAxisCheckBox->setEnabled(true);
}
else
{
RemoveAllToolProjections();
m_Controls->showHideToolAxisCheckBox->setEnabled(false);
}
if(m_NeedleProjectionFilter->GetNumberOfInputs())
{
m_NeedleProjectionFilter->Update();
}
//Refresh the view and the status widget
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// m_Controls->m_TrackingToolsStatusWidget->Refresh();
}
void QmitkMITKIGTTrackingToolboxView::OnShowHideToolAxisClicked()
{
if( !m_ShowHideToolAxis )
{
//Activate and show the tool axis
m_NeedleProjectionFilter->ShowToolAxis(true);
m_ShowHideToolAxis = true;
}
else
{
//Deactivate and hide the tool axis
m_NeedleProjectionFilter->ShowToolAxis(false);
m_NeedleProjectionFilter->GetProjection()->RemovePointIfExists(2);
m_ShowHideToolAxis = false;
}
//Update the filter
if(m_NeedleProjectionFilter->GetNumberOfInputs())
{
m_NeedleProjectionFilter->Update();
}
//Refresh the view and the status widget
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// m_Controls->m_TrackingToolsStatusWidget->Refresh();
}
void QmitkMITKIGTTrackingToolboxView::OnConnectDisconnect()
{
if (m_connected) { OnDisconnect(); }
else { OnConnect(); }
}
void QmitkMITKIGTTrackingToolboxView::OnConnect()
{
MITK_DEBUG << "Connect Clicked";
//check if everything is ready to start tracking
if (this->m_toolStorage.IsNull())
{
MessageBox("Error: No Tools Loaded Yet!");
return;
}
else if (this->m_toolStorage->GetToolCount() == 0)
{
MessageBox("Error: No Way To Track Without Tools!");
return;
}
//parse tracking device data
mitk::TrackingDeviceData data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified();
QString qstr = m_Controls->m_VolumeSelectionBox->currentText();
if ((!qstr.isNull()) || (!qstr.isEmpty())) {
std::string str = qstr.toStdString();
data = m_DeviceTypeCollection->GetDeviceDataByName(str); //Data will be set later, after device generation
}
//! [Thread 4]
//initialize worker thread
m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eConnectDevice);
m_Worker->SetTrackingDevice(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice());
m_Worker->SetInverseMode(m_Controls->m_InverseMode->isChecked());
m_Worker->SetNavigationToolStorage(this->m_toolStorage);
m_Worker->SetTrackingDeviceData(data);
//start worker thread
m_WorkerThread->start();
//! [Thread 4]
//enable checkboxes for projection and tool axis
m_Controls->showHideToolAxisCheckBox->setEnabled(true);
m_Controls->showHideToolProjectionCheckBox->setEnabled(true);
m_Controls->m_toolselector->setEnabled(true);
//disable buttons
this->m_Controls->m_MainWidget->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::EnableDisableTimerButtons(int enable)
{
bool enableBool = enable;
m_Controls->m_UpdateRateOptionsGroupBox->setEnabled(!enableBool);
m_Controls->m_RenderWarningLabel->setVisible(enableBool);
}
void QmitkMITKIGTTrackingToolboxView::OnConnectFinished(bool success, QString errorMessage)
{
m_WorkerThread->quit();
m_WorkerThread->wait();
//enable buttons
this->m_Controls->m_MainWidget->setEnabled(true);
if (!success)
{
MITK_WARN << errorMessage.toStdString();
MessageBox(errorMessage.toStdString());
return;
}
//! [Thread 6]
//get data from worker thread
m_TrackingDeviceData = m_Worker->GetTrackingDeviceData();
m_ToolVisualizationFilter = m_Worker->GetToolVisualizationFilter();
if( m_ToolVisualizationFilter.IsNotNull() )
{
//Connect the NeedleProjectionFilter to the ToolVisualizationFilter as third filter of the IGT pipeline
m_NeedleProjectionFilter->ConnectTo(m_ToolVisualizationFilter);
if (m_Controls->showHideToolProjectionCheckBox->isChecked())
{
ShowToolProjection(m_Controls->m_toolselector->currentIndex());
}
}
//! [Thread 6]
//enable/disable Buttons
DisableOptionsButtons();
DisableTrackingConfigurationButtons();
m_Controls->m_TrackingControlLabel->setText("Status: connected");
m_Controls->m_ConnectDisconnectButton->setText("Disconnect");
m_Controls->m_ConnectSimpleMode->setText("Disconnect");
m_Controls->m_StartStopTrackingButton->setEnabled(true);
m_Controls->m_StartTrackingSimpleMode->setEnabled(true);
m_connected = true;
//During connection, thi sourceID of the tool storage changed. However, Microservice can't be updated on a different thread.
//UpdateMicroservice is necessary to use filter to get the right storage belonging to a source.
//Don't do it before m_connected is true, as we don't want to call content of OnToolStorageChanged.
m_toolStorage->UpdateMicroservice();
}
void QmitkMITKIGTTrackingToolboxView::OnDisconnect()
{
m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eDisconnectDevice);
m_WorkerThread->start();
m_Controls->m_MainWidget->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::OnDisconnectFinished(bool success, QString errorMessage)
{
m_WorkerThread->quit();
m_WorkerThread->wait();
m_Controls->m_MainWidget->setEnabled(true);
if (!success)
{
MITK_WARN << errorMessage.toStdString();
MessageBox(errorMessage.toStdString());
return;
}
//enable/disable Buttons
m_Controls->m_StartStopTrackingButton->setEnabled(false);
m_Controls->m_StartTrackingSimpleMode->setEnabled(false);
EnableOptionsButtons();
EnableTrackingConfigurationButtons();
m_Controls->m_TrackingControlLabel->setText("Status: disconnected");
m_Controls->m_ConnectDisconnectButton->setText("Connect");
m_Controls->m_ConnectSimpleMode->setText("Connect");
m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking");
m_Controls->m_TrackingFrozenLabel->setVisible(false);
m_connected = false;
}
void QmitkMITKIGTTrackingToolboxView::OnStartTracking()
{
//show tracking volume
this->OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText());
//Reset the view to a defined start. Do it here and not in OnStartTrackingFinished, to give other tracking devices the chance to reset the view to a different direction.
this->GlobalReinit();
m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStartTracking);
m_WorkerThread->start();
this->m_Controls->m_MainWidget->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::OnStartTrackingFinished(bool success, QString errorMessage)
{
//! [Thread 5]
m_WorkerThread->quit();
m_WorkerThread->wait();
//! [Thread 5]
this->m_Controls->m_MainWidget->setEnabled(true);
if (!success)
{
MessageBox(errorMessage.toStdString());
MITK_WARN << errorMessage.toStdString();
return;
}
if (!(m_Controls->m_DisableAllTimers->isChecked()))
{
if (m_Controls->m_UseDifferentUpdateRates->isChecked())
{
if (m_Controls->m_RenderUpdateRate->value() != 0)
m_TrackingRenderTimer->start(1000 / (m_Controls->m_RenderUpdateRate->value()));
m_TrackingLoggingTimer->start(1000 / (m_Controls->m_LogUpdateRate->value()));
}
else
{
m_TrackingRenderTimer->start(1000 / (m_Controls->m_UpdateRate->value()));
m_TrackingLoggingTimer->start(1000 / (m_Controls->m_UpdateRate->value()));
}
}
m_Controls->m_TrackingControlLabel->setText("Status: tracking");
//connect the tool visualization widget
for (std::size_t i = 0; i < m_Worker->GetTrackingDeviceSource()->GetNumberOfOutputs(); i++)
{
m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_Worker->GetTrackingDeviceSource()->GetOutput(i));
}
m_Controls->m_TrackingToolsStatusWidget->ShowStatusLabels();
if (m_Controls->m_ShowToolQuaternions->isChecked()) { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(true); }
else { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(false); }
//if activated enable open IGT link microservice
if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked())
{
//create convertion filter
m_IGTLConversionFilter = mitk::NavigationDataToIGTLMessageFilter::New();
m_IGTLConversionFilter->SetName("IGT Tracking Toolbox");
QString dataModeSelection = this->m_Controls->m_OpenIGTLinkDataFormat->currentText();
if (dataModeSelection == "TDATA")
{
m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg);
}
else if (dataModeSelection == "TRANSFORM")
{
m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg);
}
else if (dataModeSelection == "QTDATA")
{
m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTDataMsg);
}
else if (dataModeSelection == "POSITION")
{
m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTransMsg);
}
m_IGTLConversionFilter->ConnectTo(m_ToolVisualizationFilter);
m_IGTLConversionFilter->RegisterAsMicroservice();
//create server and message provider
m_IGTLServer = mitk::IGTLServer::New(false);
m_IGTLServer->SetName("Tracking Toolbox IGTL Server");
m_IGTLMessageProvider = mitk::IGTLMessageProvider::New();
m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer);
m_IGTLMessageProvider->RegisterAsMicroservice();
}
m_tracking = true;
m_Controls->m_ConnectDisconnectButton->setEnabled(false);
m_Controls->m_StartStopTrackingButton->setText("Stop Tracking");
m_Controls->m_StartTrackingSimpleMode->setText("Stop\nTracking");
m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(true);
}
void QmitkMITKIGTTrackingToolboxView::OnStopTracking()
{
if (!m_tracking) return;
for (unsigned int i = 0; i < m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); i++)
{
mitk::NavigationData::Pointer currentTool = m_ToolVisualizationFilter->GetOutput(i);
if (currentTool->IsDataValid())
{
this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_INVALID);
}
}
//refresh view and status widget
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
m_TrackingRenderTimer->stop();
m_TrackingLoggingTimer->stop();
m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStopTracking);
m_WorkerThread->start();
m_Controls->m_MainWidget->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::OnStopTrackingFinished(bool success, QString errorMessage)
{
m_WorkerThread->quit();
m_WorkerThread->wait();
m_Controls->m_MainWidget->setEnabled(true);
if (!success)
{
MessageBox(errorMessage.toStdString());
MITK_WARN << errorMessage.toStdString();
return;
}
m_Controls->m_TrackingControlLabel->setText("Status: connected");
if (m_logging) StopLogging();
m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels();
m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage);
m_tracking = false;
m_Controls->m_StartStopTrackingButton->setText("Start Tracking");
m_Controls->m_StartTrackingSimpleMode->setText("Start\nTracking");
m_Controls->m_ConnectDisconnectButton->setEnabled(true);
m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false);
//unregister open IGT link micro service
if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked())
{
m_IGTLConversionFilter->UnRegisterMicroservice();
m_IGTLMessageProvider->UnRegisterMicroservice();
}
}
void QmitkMITKIGTTrackingToolboxView::OnTrackingDeviceChanged()
{
mitk::TrackingDeviceType Type;
if (m_Controls->m_ConfigurationWidget->GetTrackingDevice().IsNotNull())
{
Type = m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType();
//enable controls because device is valid
m_Controls->m_TrackingToolsFrame->setEnabled(true);
m_Controls->m_TrackingControlsFrame->setEnabled(true);
}
else
{
Type = mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName();
MessageBox("Error: This tracking device is not included in this project. Please make sure that the device is installed and activated in your MITK build.");
m_Controls->m_TrackingToolsFrame->setEnabled(false);
m_Controls->m_TrackingControlsFrame->setEnabled(false);
return;
}
// Code to enable/disable device specific buttons
if (m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable())
{
m_Controls->m_AutoDetectTools->setVisible(true);
}
else
{
m_Controls->m_AutoDetectTools->setVisible(false);
}
m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable());
// Code to select appropriate tracking volume for current type
std::vector<mitk::TrackingDeviceData> Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(Type);
m_Controls->m_VolumeSelectionBox->clear();
for (std::size_t i = 0; i < Compatibles.size(); i++)
{
m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str());
}
}
void QmitkMITKIGTTrackingToolboxView::OnTrackingVolumeChanged(QString qstr)
{
if (qstr.isNull()) return;
if (qstr.isEmpty()) return;
mitk::TrackingVolumeGenerator::Pointer volumeGenerator = mitk::TrackingVolumeGenerator::New();
std::string str = qstr.toStdString();
mitk::TrackingDeviceData data = m_DeviceTypeCollection->GetDeviceDataByName(str);
m_TrackingDeviceData = data;
volumeGenerator->SetTrackingDeviceData(data);
volumeGenerator->Update();
mitk::Surface::Pointer volumeSurface = volumeGenerator->GetOutput();
m_TrackingVolumeNode->SetData(volumeSurface);
if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0);
else m_TrackingVolumeNode->SetOpacity(0.25);
GlobalReinit();
}
void QmitkMITKIGTTrackingToolboxView::OnShowTrackingVolumeChanged()
{
if (m_Controls->m_ShowTrackingVolume->isChecked())
{
OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText());
m_TrackingVolumeNode->SetOpacity(0.25);
}
else
{
m_TrackingVolumeNode->SetOpacity(0.0);
}
}
void QmitkMITKIGTTrackingToolboxView::OnAutoDetectTools()
{
if (m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable())
{
DisableTrackingConfigurationButtons();
m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eAutoDetectTools);
m_Worker->SetTrackingDevice(m_Controls->m_ConfigurationWidget->GetTrackingDevice().GetPointer());
m_Worker->SetDataStorage(this->GetDataStorage());
m_WorkerThread->start();
m_TimeoutTimer->start(30000);
//disable controls until worker thread is finished
this->m_Controls->m_MainWidget->setEnabled(false);
}
}
void QmitkMITKIGTTrackingToolboxView::OnAutoDetectToolsFinished(bool success, QString errorMessage)
{
//Check, if the thread is running. There might have been a timeOut inbetween and this causes crashes...
if (m_WorkerThread->isRunning())
{
m_TimeoutTimer->stop();
m_WorkerThread->quit();
m_WorkerThread->wait();
}
//enable controls again
this->m_Controls->m_MainWidget->setEnabled(true);
EnableTrackingConfigurationButtons();
if (!success)
{
MITK_WARN << errorMessage.toStdString();
MessageBox(errorMessage.toStdString());
EnableTrackingConfigurationButtons();
return;
}
mitk::NavigationToolStorage::Pointer autoDetectedStorage = m_Worker->GetNavigationToolStorage();
//save detected tools
std::string _autoDetectText;
_autoDetectText = "Autodetected ";
_autoDetectText.append(this->m_TrackingDeviceData.Line); //This is the device name as string of the current TrackingDevice.
_autoDetectText.append(" Storage");
this->ReplaceCurrentToolStorage(autoDetectedStorage, _autoDetectText);
//auto save the new storage to hard disc (for persistence)
AutoSaveToolStorage();
//update label
QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools (Auto Detected)";
m_Controls->m_ToolLabel->setText(toolLabel);
//update tool preview
m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels();
m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage);
EnableTrackingConfigurationButtons();
//print a logging message about the detected tools
switch (m_toolStorage->GetToolCount())
{
case 0:
MITK_INFO("IGT Tracking Toolbox") << "Found no tools. Empty ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString();
break;
case 1:
MITK_INFO("IGT Tracking Toolbox") << "Found one tool. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString();
break;
default:
MITK_INFO("IGT Tracking Toolbox") << "Found " << m_toolStorage->GetToolCount() << " tools. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString();
}
}
void QmitkMITKIGTTrackingToolboxView::MessageBox(std::string s)
{
QMessageBox msgBox;
msgBox.setText(s.c_str());
msgBox.exec();
}
void QmitkMITKIGTTrackingToolboxView::UpdateRenderTrackingTimer()
{
//update filter
m_ToolVisualizationFilter->Update();
MITK_DEBUG << "Number of outputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedOutputs();
MITK_DEBUG << "Number of inputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedInputs();
//update tool colors to show tool status
for (unsigned int i = 0; i < m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); i++)
{
mitk::NavigationData::Pointer currentTool = m_ToolVisualizationFilter->GetOutput(i);
if (currentTool->IsDataValid())
{
this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_VALID);
}
else
{
this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_WARNING);
}
}
//Update the NeedleProjectionFilter
if( m_NeedleProjectionFilter.IsNotNull() )
{
m_NeedleProjectionFilter->Update();
}
//refresh view and status widget
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
m_Controls->m_TrackingToolsStatusWidget->Refresh();
}
void QmitkMITKIGTTrackingToolboxView::UpdateLoggingTrackingTimer()
{
//update logging
if (m_logging)
{
this->m_loggingFilter->Update();
m_loggedFrames = this->m_loggingFilter->GetNumberOfRecordedSteps();
this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: " + QString::number(m_loggedFrames));
//check if logging stopped automatically
if ((m_loggedFrames > 1) && (!m_loggingFilter->GetRecording())){ StopLogging(); }
}
//refresh status widget
m_Controls->m_TrackingToolsStatusWidget->Refresh();
}
void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked()
{
QDir currentPath = QFileInfo(m_Controls->m_LoggingFileName->text()).dir();
// if no path was selected (QDir would select current working dir then) or the
// selected path does not exist -> use home directory
if (currentPath == QDir() || !currentPath.exists())
{
currentPath = QDir(QDir::homePath());
}
QString filename = QFileDialog::getSaveFileName(nullptr, tr("Choose Logging File"), currentPath.absolutePath(), "*.*");
if (filename == "") return;
this->m_Controls->m_LoggingFileName->setText(filename);
this->OnToggleFileExtension();
}
// bug-16470: toggle file extension after clicking on radio button
void QmitkMITKIGTTrackingToolboxView::OnToggleFileExtension()
{
QString currentInputText = this->m_Controls->m_LoggingFileName->text();
QString currentFile = QFileInfo(currentInputText).baseName();
QDir currentPath = QFileInfo(currentInputText).dir();
if (currentFile.isEmpty())
{
currentFile = "logfile";
}
// Setting currentPath to default home path when currentPath is empty or it does not exist
if (currentPath == QDir() || !currentPath.exists())
{
currentPath = QDir::homePath();
}
// check if csv radio button is clicked
if (this->m_Controls->m_CsvFormat->isChecked())
{
// you needn't add a seperator to the input text when currentpath is the rootpath
if (currentPath.isRoot())
{
this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".csv");
}
else
{
this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".csv");
}
}
// check if xml radio button is clicked
else if (this->m_Controls->m_XmlFormat->isChecked())
{
// you needn't add a seperator to the input text when currentpath is the rootpath
if (currentPath.isRoot())
{
this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".xml");
}
else
{
this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".xml");
}
}
}
void QmitkMITKIGTTrackingToolboxView::OnToggleAdvancedSimpleMode()
{
if (m_SimpleModeEnabled)
{
m_Controls->m_simpleWidget->setVisible(false);
m_Controls->m_MainWidget->setVisible(true);
m_Controls->m_SimpleUI->setChecked(false);
m_SimpleModeEnabled = false;
}
else
{
m_Controls->m_simpleWidget->setVisible(true);
m_Controls->m_MainWidget->setVisible(false);
m_SimpleModeEnabled = true;
}
}
void QmitkMITKIGTTrackingToolboxView::OnToggleDifferentUpdateRates()
{
if (m_Controls->m_UseDifferentUpdateRates->isChecked())
{
if (m_Controls->m_RenderUpdateRate->value() == 0)
m_Controls->m_RenderWarningLabel->setVisible(true);
else
m_Controls->m_RenderWarningLabel->setVisible(false);
m_Controls->m_UpdateRate->setEnabled(false);
m_Controls->m_OptionsUpdateRateLabel->setEnabled(false);
m_Controls->m_RenderUpdateRate->setEnabled(true);
m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(true);
m_Controls->m_LogUpdateRate->setEnabled(true);
m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(true);
}
else
{
m_Controls->m_RenderWarningLabel->setVisible(false);
m_Controls->m_UpdateRate->setEnabled(true);
m_Controls->m_OptionsUpdateRateLabel->setEnabled(true);
m_Controls->m_RenderUpdateRate->setEnabled(false);
m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false);
m_Controls->m_LogUpdateRate->setEnabled(false);
m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false);
}
}
void QmitkMITKIGTTrackingToolboxView::OnChangeRenderUpdateRate()
{
if (m_Controls->m_RenderUpdateRate->value() == 0)
m_Controls->m_RenderWarningLabel->setVisible(true);
else
m_Controls->m_RenderWarningLabel->setVisible(false);
}
void QmitkMITKIGTTrackingToolboxView::StartLogging()
{
if (m_ToolVisualizationFilter.IsNull())
{
MessageBox("Cannot activate logging without a connected device. Configure and connect a tracking device first.");
return;
}
if (!m_logging)
{
//initialize logging filter
m_loggingFilter = mitk::NavigationDataRecorder::New();
m_loggingFilter->SetRecordOnlyValidData(m_Controls->m_SkipInvalidData->isChecked());
m_loggingFilter->ConnectTo(m_ToolVisualizationFilter);
if (m_Controls->m_LoggingLimit->isChecked()){ m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value()); }
//start filter with try-catch block for exceptions
try
{
m_loggingFilter->StartRecording();
}
catch (mitk::IGTException&)
{
std::string errormessage = "Error during start recording. Recorder already started recording?";
QMessageBox::warning(nullptr, "IGTPlayer: Error", errormessage.c_str());
m_loggingFilter->StopRecording();
return;
}
//update labels / logging variables
this->m_Controls->m_LoggingLabel->setText("Logging ON");
this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: 0");
m_loggedFrames = 0;
m_logging = true;
DisableLoggingButtons();
}
}
void QmitkMITKIGTTrackingToolboxView::StopLogging()
{
if (m_logging)
{
//stop logging
m_loggingFilter->StopRecording();
m_logging = false;
//update GUI
this->m_Controls->m_LoggingLabel->setText("Logging OFF");
EnableLoggingButtons();
//write the results to a file
if (m_Controls->m_CsvFormat->isChecked())
{
mitk::IOUtil::Save(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString());
}
else if (m_Controls->m_XmlFormat->isChecked())
{
mitk::IOUtil::Save(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString());
}
}
}
void QmitkMITKIGTTrackingToolboxView::SetFocus()
{
}
void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool()
{
QString Identifier = "Tool#";
QString Name = "NewTool";
if (m_toolStorage.IsNotNull()) {
Identifier += QString::number(m_toolStorage->GetToolCount());
Name += QString::number(m_toolStorage->GetToolCount());
}
else {
Identifier += "0";
Name += "0";
}
m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(), Identifier.toStdString(), Name.toStdString());
m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType(), false);
m_Controls->m_TrackingToolsWidget->setCurrentIndex(1);
//disable tracking volume during tool editing
lastTrackingVolumeState = m_Controls->m_ShowTrackingVolume->isChecked();
if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click();
GlobalReinit();
}
void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolFinished()
{
m_Controls->m_TrackingToolsWidget->setCurrentIndex(0);
if (this->m_toolStorage.IsNull())
{
//this shouldn't happen!
MITK_WARN << "No ToolStorage available, cannot add tool, aborting!";
return;
}
m_toolStorage->AddTool(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool());
m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage);
m_Controls->m_ToolLabel->setText("<manually added>");
//displya in tool selector
// m_Controls->m_toolselector->addItem(QString::fromStdString(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool()->GetToolName()));
//auto save current storage for persistence
MITK_INFO << "Auto saving manually added tools for persistence.";
AutoSaveToolStorage();
//enable tracking volume again
if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click();
GlobalReinit();
}
void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolCanceled()
{
m_Controls->m_TrackingToolsWidget->setCurrentIndex(0);
//enable tracking volume again
if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click();
GlobalReinit();
}
void QmitkMITKIGTTrackingToolboxView::GlobalReinit()
{
// get all nodes that have not set "includeInBoundingBox" to false
mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false)));
mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred);
// calculate bounding geometry of these nodes
auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible");
// initialize the views to the bounding geometry
mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
}
void QmitkMITKIGTTrackingToolboxView::DisableLoggingButtons()
{
m_Controls->m_StartLogging->setEnabled(false);
m_Controls->m_LoggingFileName->setEnabled(false);
m_Controls->m_ChooseFile->setEnabled(false);
m_Controls->m_LoggingLimit->setEnabled(false);
m_Controls->m_LoggedFramesLimit->setEnabled(false);
m_Controls->m_CsvFormat->setEnabled(false);
m_Controls->m_XmlFormat->setEnabled(false);
m_Controls->m_SkipInvalidData->setEnabled(false);
m_Controls->m_StopLogging->setEnabled(true);
}
void QmitkMITKIGTTrackingToolboxView::EnableLoggingButtons()
{
m_Controls->m_StartLogging->setEnabled(true);
m_Controls->m_LoggingFileName->setEnabled(true);
m_Controls->m_ChooseFile->setEnabled(true);
m_Controls->m_LoggingLimit->setEnabled(true);
m_Controls->m_LoggedFramesLimit->setEnabled(true);
m_Controls->m_CsvFormat->setEnabled(true);
m_Controls->m_XmlFormat->setEnabled(true);
m_Controls->m_SkipInvalidData->setEnabled(true);
m_Controls->m_StopLogging->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::DisableOptionsButtons()
{
m_Controls->m_ShowTrackingVolume->setEnabled(false);
m_Controls->m_UseDifferentUpdateRates->setEnabled(false);
m_Controls->m_UpdateRate->setEnabled(false);
m_Controls->m_OptionsUpdateRateLabel->setEnabled(false);
m_Controls->m_RenderUpdateRate->setEnabled(false);
m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false);
m_Controls->m_LogUpdateRate->setEnabled(false);
m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false);
m_Controls->m_DisableAllTimers->setEnabled(false);
m_Controls->m_OtherOptionsGroupBox->setEnabled(false);
m_Controls->m_EnableOpenIGTLinkMicroService->setEnabled(false);
m_Controls->m_OpenIGTLinkDataFormat->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons()
{
m_Controls->m_ShowTrackingVolume->setEnabled(true);
m_Controls->m_UseDifferentUpdateRates->setEnabled(true);
m_Controls->m_DisableAllTimers->setEnabled(true);
m_Controls->m_OtherOptionsGroupBox->setEnabled(true);
m_Controls->m_EnableOpenIGTLinkMicroService->setEnabled(true);
m_Controls->m_OpenIGTLinkDataFormat->setEnabled(true);
OnToggleDifferentUpdateRates();
}
void QmitkMITKIGTTrackingToolboxView::EnableTrackingControls()
{
m_Controls->m_TrackingControlsFrame->setEnabled(true);
}
void QmitkMITKIGTTrackingToolboxView::DisableTrackingControls()
{
m_Controls->m_TrackingControlsFrame->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::EnableTrackingConfigurationButtons()
{
m_Controls->m_AutoDetectTools->setEnabled(true);
m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable());
m_Controls->m_LoadTools->setEnabled(true);
m_Controls->m_ResetTools->setEnabled(true);
}
void QmitkMITKIGTTrackingToolboxView::DisableTrackingConfigurationButtons()
{
m_Controls->m_AutoDetectTools->setEnabled(false);
m_Controls->m_AddSingleTool->setEnabled(false);
m_Controls->m_LoadTools->setEnabled(false);
m_Controls->m_ResetTools->setEnabled(false);
}
void QmitkMITKIGTTrackingToolboxView::ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName)
{
//first: get rid of the old one
//don't reset if there is no tool storage. BugFix #17793
if (m_toolStorage.IsNotNull()){
m_toolStorage->UnLockStorage(); //only to be sure...
m_toolStorage->UnRegisterMicroservice();
m_toolStorage = nullptr;
}
//now: replace by the new one
m_toolStorage = newStorage;
m_toolStorage->SetName(newStorageName);
m_toolStorage->RegisterAsMicroservice();
}
void QmitkMITKIGTTrackingToolboxView::OnTimeOut()
{
MITK_WARN << "TimeOut. Quitting the thread...";
m_WorkerThread->quit();
//only if we can't quit use terminate.
if (!m_WorkerThread->wait(1000))
{
MITK_ERROR << "Can't quit the thread. Terminating... Might cause further problems, be careful!";
m_WorkerThread->terminate();
m_WorkerThread->wait();
}
m_TimeoutTimer->stop();
}
void QmitkMITKIGTTrackingToolboxView::OnToolStorageChanged(const ctkServiceEvent event)
{
//don't listen to any changes during connection, toolStorage is locked anyway, so this are only changes of e.g. sourceID which are not relevant for the widget.
if (!m_connected && (event.getType() == ctkServiceEvent::MODIFIED))
{
m_Controls->m_ConfigurationWidget->OnToolStorageChanged();
m_Controls->m_toolselector->clear();
for (size_t i = 0; i < m_toolStorage->GetToolCount(); i++)
{
m_Controls->m_toolselector->addItem(QString::fromStdString(m_toolStorage->GetTool(i)->GetToolName()));
}
}
}
//! [StoreUISettings]
void QmitkMITKIGTTrackingToolboxView::StoreUISettings()
{
// persistence service does not directly work in plugins for now
// -> using QSettings
QSettings settings;
settings.beginGroup(QString::fromStdString(VIEW_ID));
MITK_DEBUG << "Store UI settings";
// set the values of some widgets and attrbutes to the QSettings
settings.setValue("ShowTrackingVolume", QVariant(m_Controls->m_ShowTrackingVolume->isChecked()));
settings.setValue("toolStorageFilename", QVariant(m_ToolStorageFilename));
settings.setValue("VolumeSelectionBox", QVariant(m_Controls->m_VolumeSelectionBox->currentIndex()));
settings.setValue("SimpleModeEnabled", QVariant(m_SimpleModeEnabled));
settings.setValue("OpenIGTLinkDataFormat", QVariant(m_Controls->m_OpenIGTLinkDataFormat->currentIndex()));
settings.setValue("EnableOpenIGTLinkMicroService", QVariant(m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()));
settings.endGroup();
}
//! [StoreUISettings]
//! [LoadUISettings]
void QmitkMITKIGTTrackingToolboxView::LoadUISettings()
{
// persistence service does not directly work in plugins for now -> using QSettings
QSettings settings;
settings.beginGroup(QString::fromStdString(VIEW_ID));
// set some widgets and attributes by the values from the QSettings
m_Controls->m_ShowTrackingVolume->setChecked(settings.value("ShowTrackingVolume", false).toBool());
m_Controls->m_EnableOpenIGTLinkMicroService->setChecked(settings.value("EnableOpenIGTLinkMicroService", true).toBool());
m_Controls->m_VolumeSelectionBox->setCurrentIndex(settings.value("VolumeSelectionBox", 0).toInt());
m_Controls->m_OpenIGTLinkDataFormat->setCurrentIndex(settings.value("OpenIGTLinkDataFormat", 0).toInt());
m_ToolStorageFilename = settings.value("toolStorageFilename", QVariant("")).toString();
if (settings.value("SimpleModeEnabled", false).toBool()) { this->OnToggleAdvancedSimpleMode(); }
settings.endGroup();
//! [LoadUISettings]
//! [LoadToolStorage]
// try to deserialize the tool storage from the given tool storage file name
if (!m_ToolStorageFilename.isEmpty())
{
// try-catch block for exceptions
try
{
mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage());
m_toolStorage->UnRegisterMicroservice();
m_toolStorage = myDeserializer->Deserialize(m_ToolStorageFilename.toStdString());
m_toolStorage->RegisterAsMicroservice();
//update label
UpdateToolStorageLabel(m_ToolStorageFilename);
//update tool preview
m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels();
m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage);
}
catch (const mitk::IGTException& e)
{
MITK_WARN("QmitkMITKIGTTrackingToolBoxView") << "Error during restoring tools. Problems with file (" << m_ToolStorageFilename.toStdString() << "), please check the file? Error message: "<<e.GetDescription();
this->OnResetTools(); //if there where errors reset the tool storage to avoid problems later on
}
}
//! [LoadToolStorage]
}
void QmitkMITKIGTTrackingToolboxView::UpdateToolStorageLabel(QString pathOfLoadedStorage)
{
QFileInfo myPath(pathOfLoadedStorage); //use this to seperate filename from path
QString toolLabel = myPath.fileName();
if (toolLabel.size() > 45) //if the tool storage name is to long trimm the string
{
toolLabel.resize(40);
toolLabel += "[...]";
}
m_Controls->m_ToolLabel->setText(toolLabel);
}
void QmitkMITKIGTTrackingToolboxView::AutoSaveToolStorage()
{
m_ToolStorageFilename = m_AutoSaveFilename;
mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New();
mySerializer->Serialize(m_ToolStorageFilename.toStdString(), m_toolStorage);
}
diff --git a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp
index a57eab8f0e..6d4155a084 100644
--- a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp
+++ b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp
@@ -1,512 +1,512 @@
/*============================================================================
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 "QmitkImageCropperView.h"
#include <mitkBoundingShapeCropper.h>
#include <mitkImageStatisticsHolder.h>
#include <mitkInteractionConst.h>
#include <mitkITKImageImport.h>
#include <mitkLabelSetImage.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateFunction.h>
#include <mitkRenderingManager.h>
#include <usModuleRegistry.h>
#include <QMessageBox>
const std::string QmitkImageCropperView::VIEW_ID = "org.mitk.views.qmitkimagecropper";
QmitkImageCropperView::QmitkImageCropperView(QObject *)
: m_ParentWidget(nullptr)
, m_BoundingShapeInteractor(nullptr)
, m_CropOutsideValue(0)
{
CreateBoundingShapeInteractor(false);
}
QmitkImageCropperView::~QmitkImageCropperView()
{
//disable interactor
if (m_BoundingShapeInteractor != nullptr)
{
m_BoundingShapeInteractor->SetDataNode(nullptr);
m_BoundingShapeInteractor->EnableInteraction(false);
}
}
void QmitkImageCropperView::CreateQtPartControl(QWidget *parent)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls.setupUi(parent);
m_Controls.imageSelectionWidget->SetDataStorage(GetDataStorage());
m_Controls.imageSelectionWidget->SetNodePredicate(
mitk::NodePredicateAnd::New(mitk::TNodePredicateDataType<mitk::Image>::New(),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))));
m_Controls.imageSelectionWidget->SetSelectionIsOptional(true);
m_Controls.imageSelectionWidget->SetAutoSelectNewNodes(true);
m_Controls.imageSelectionWidget->SetEmptyInfo(QString("Please select an image node"));
m_Controls.imageSelectionWidget->SetPopUpTitel(QString("Select image node"));
connect(m_Controls.imageSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged,
this, &QmitkImageCropperView::OnImageSelectionChanged);
m_Controls.boundingBoxSelectionWidget->SetDataStorage(GetDataStorage());
m_Controls.boundingBoxSelectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New(
mitk::TNodePredicateDataType<mitk::GeometryData>::New(),
mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))));
m_Controls.boundingBoxSelectionWidget->SetSelectionIsOptional(true);
m_Controls.boundingBoxSelectionWidget->SetAutoSelectNewNodes(true);
m_Controls.boundingBoxSelectionWidget->SetEmptyInfo(QString("Please select a bounding box"));
m_Controls.boundingBoxSelectionWidget->SetPopUpTitel(QString("Select bounding box node"));
connect(m_Controls.boundingBoxSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged,
this, &QmitkImageCropperView::OnBoundingBoxSelectionChanged);
connect(m_Controls.buttonCreateNewBoundingBox, SIGNAL(clicked()), this, SLOT(OnCreateNewBoundingBox()));
connect(m_Controls.buttonCropping, SIGNAL(clicked()), this, SLOT(OnCropping()));
connect(m_Controls.buttonMasking, SIGNAL(clicked()), this, SLOT(OnMasking()));
auto lambda = [this]()
{
m_Controls.groupImageSettings->setVisible(!m_Controls.groupImageSettings->isVisible());
};
connect(m_Controls.buttonAdvancedSettings, &ctkExpandButton::clicked, this, lambda);
connect(m_Controls.spinBoxOutsidePixelValue, SIGNAL(valueChanged(int)), this, SLOT(OnSliderValueChanged(int)));
SetDefaultGUI();
m_ParentWidget = parent;
this->OnImageSelectionChanged(m_Controls.imageSelectionWidget->GetSelectedNodes());
this->OnBoundingBoxSelectionChanged(m_Controls.boundingBoxSelectionWidget->GetSelectedNodes());
}
void QmitkImageCropperView::OnImageSelectionChanged(QList<mitk::DataNode::Pointer>)
{
bool rotationEnabled = false;
m_Controls.labelWarningRotation->setVisible(false);
auto imageNode = m_Controls.imageSelectionWidget->GetSelectedNode();
if (imageNode.IsNull())
{
SetDefaultGUI();
return;
}
auto image = dynamic_cast<mitk::Image*>(imageNode->GetData());
if (nullptr != image)
{
if (image->GetDimension() < 3)
{
QMessageBox::warning(nullptr,
tr("Invalid image selected"),
tr("ImageCropper only works with 3 or more dimensions."),
QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
SetDefaultGUI();
return;
}
m_ParentWidget->setEnabled(true);
m_Controls.buttonCreateNewBoundingBox->setEnabled(true);
vtkSmartPointer<vtkMatrix4x4> imageMat = image->GetGeometry()->GetVtkMatrix();
// check whether the image geometry is rotated; if so, no pixel aligned cropping or masking can be performed
if ((imageMat->GetElement(1, 0) == 0.0) && (imageMat->GetElement(0, 1) == 0.0) &&
(imageMat->GetElement(1, 2) == 0.0) && (imageMat->GetElement(2, 1) == 0.0) &&
(imageMat->GetElement(2, 0) == 0.0) && (imageMat->GetElement(0, 2) == 0.0))
{
rotationEnabled = false;
m_Controls.labelWarningRotation->setVisible(false);
}
else
{
rotationEnabled = true;
m_Controls.labelWarningRotation->setStyleSheet(" QLabel { color: rgb(255, 0, 0) }");
m_Controls.labelWarningRotation->setVisible(true);
}
this->CreateBoundingShapeInteractor(rotationEnabled);
if (itk::IOPixelEnum::SCALAR == image->GetPixelType().GetPixelType())
{
// Might be changed with the upcoming new image statistics plugin
//(recomputation might be very expensive for large images ;) )
auto statistics = image->GetStatistics();
auto minPixelValue = statistics->GetScalarValueMin();
auto maxPixelValue = statistics->GetScalarValueMax();
if (minPixelValue < std::numeric_limits<int>::min())
{
minPixelValue = std::numeric_limits<int>::min();
}
if (maxPixelValue > std::numeric_limits<int>::max())
{
maxPixelValue = std::numeric_limits<int>::max();
}
m_Controls.spinBoxOutsidePixelValue->setEnabled(true);
m_Controls.spinBoxOutsidePixelValue->setMaximum(static_cast<int>(maxPixelValue));
m_Controls.spinBoxOutsidePixelValue->setMinimum(static_cast<int>(minPixelValue));
m_Controls.spinBoxOutsidePixelValue->setValue(static_cast<int>(minPixelValue));
}
else
{
m_Controls.spinBoxOutsidePixelValue->setEnabled(false);
}
unsigned int dim = image->GetDimension();
if (dim < 2 || dim > 4)
{
m_ParentWidget->setEnabled(false);
}
if (m_Controls.boundingBoxSelectionWidget->GetSelectedNode().IsNotNull())
{
m_Controls.buttonCropping->setEnabled(true);
m_Controls.buttonMasking->setEnabled(true);
m_Controls.buttonAdvancedSettings->setEnabled(true);
m_Controls.groupImageSettings->setEnabled(true);
}
}
}
void QmitkImageCropperView::OnBoundingBoxSelectionChanged(QList<mitk::DataNode::Pointer>)
{
auto boundingBoxNode = m_Controls.boundingBoxSelectionWidget->GetSelectedNode();
if (boundingBoxNode.IsNull())
{
SetDefaultGUI();
m_BoundingShapeInteractor->EnableInteraction(false);
m_BoundingShapeInteractor->SetDataNode(nullptr);
if (m_Controls.imageSelectionWidget->GetSelectedNode().IsNotNull())
{
m_Controls.buttonCreateNewBoundingBox->setEnabled(true);
}
return;
}
auto boundingBox = dynamic_cast<mitk::GeometryData*>(boundingBoxNode->GetData());
if (nullptr != boundingBox)
{
// node newly selected
boundingBoxNode->SetVisibility(true);
m_BoundingShapeInteractor->EnableInteraction(true);
m_BoundingShapeInteractor->SetDataNode(boundingBoxNode);
mitk::RenderingManager::GetInstance()->InitializeViews();
if (m_Controls.imageSelectionWidget->GetSelectedNode().IsNotNull())
{
m_Controls.buttonCropping->setEnabled(true);
m_Controls.buttonMasking->setEnabled(true);
m_Controls.buttonAdvancedSettings->setEnabled(true);
m_Controls.groupImageSettings->setEnabled(true);
}
}
}
void QmitkImageCropperView::OnCreateNewBoundingBox()
{
auto imageNode = m_Controls.imageSelectionWidget->GetSelectedNode();
if (imageNode.IsNull())
{
return;
}
if (nullptr == imageNode->GetData())
{
return;
}
QString name = QString::fromStdString(imageNode->GetName() + " Bounding Shape");
auto boundingShape = this->GetDataStorage()->GetNode(mitk::NodePredicateFunction::New([&name](const mitk::DataNode *node)
{
return 0 == node->GetName().compare(name.toStdString());
}));
if (nullptr != boundingShape)
{
name = this->AdaptBoundingObjectName(name);
}
// get current timestep to support 3d+t images
auto renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN);
- const auto timePoint = renderWindowPart->GetSelectedTimePoint();
+ const mitk::TimePointType timePoint = renderWindowPart->GetSelectedTimePoint();
const auto imageGeometry = imageNode->GetData()->GetTimeGeometry()->GetGeometryForTimePoint(timePoint);
auto boundingBox = mitk::GeometryData::New();
boundingBox->SetGeometry(static_cast<mitk::Geometry3D*>(this->InitializeWithImageGeometry(imageGeometry)));
auto boundingBoxNode = mitk::DataNode::New();
boundingBoxNode->SetData(boundingBox);
boundingBoxNode->SetProperty("name", mitk::StringProperty::New(name.toStdString()));
boundingBoxNode->SetProperty("color", mitk::ColorProperty::New(1.0, 1.0, 1.0));
boundingBoxNode->SetProperty("opacity", mitk::FloatProperty::New(0.6));
boundingBoxNode->SetProperty("layer", mitk::IntProperty::New(99));
boundingBoxNode->AddProperty("handle size factor", mitk::DoubleProperty::New(1.0 / 40.0));
boundingBoxNode->SetBoolProperty("pickable", true);
if (!this->GetDataStorage()->Exists(boundingBoxNode))
{
GetDataStorage()->Add(boundingBoxNode, imageNode);
}
m_Controls.boundingBoxSelectionWidget->SetCurrentSelectedNode(boundingBoxNode);
}
void QmitkImageCropperView::OnCropping()
{
this->ProcessImage(false);
}
void QmitkImageCropperView::OnMasking()
{
this->ProcessImage(true);
}
void QmitkImageCropperView::OnSliderValueChanged(int slidervalue)
{
m_CropOutsideValue = slidervalue;
}
void QmitkImageCropperView::CreateBoundingShapeInteractor(bool rotationEnabled)
{
if (m_BoundingShapeInteractor.IsNull())
{
m_BoundingShapeInteractor = mitk::BoundingShapeInteractor::New();
m_BoundingShapeInteractor->LoadStateMachine("BoundingShapeInteraction.xml", us::ModuleRegistry::GetModule("MitkBoundingShape"));
m_BoundingShapeInteractor->SetEventConfig("BoundingShapeMouseConfig.xml", us::ModuleRegistry::GetModule("MitkBoundingShape"));
}
m_BoundingShapeInteractor->SetRotationEnabled(rotationEnabled);
}
mitk::Geometry3D::Pointer QmitkImageCropperView::InitializeWithImageGeometry(const mitk::BaseGeometry* geometry) const
{
// convert a BaseGeometry into a Geometry3D (otherwise IO is not working properly)
if (geometry == nullptr)
mitkThrow() << "Geometry is not valid.";
auto boundingGeometry = mitk::Geometry3D::New();
boundingGeometry->SetBounds(geometry->GetBounds());
boundingGeometry->SetImageGeometry(geometry->GetImageGeometry());
boundingGeometry->SetOrigin(geometry->GetOrigin());
boundingGeometry->SetSpacing(geometry->GetSpacing());
boundingGeometry->SetIndexToWorldTransform(geometry->GetIndexToWorldTransform()->Clone());
boundingGeometry->Modified();
return boundingGeometry;
}
void QmitkImageCropperView::ProcessImage(bool mask)
{
auto renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN);
const auto timePoint = renderWindowPart->GetSelectedTimePoint();
auto imageNode = m_Controls.imageSelectionWidget->GetSelectedNode();
if (imageNode.IsNull())
{
QMessageBox::information(nullptr, "Warning", "Please load and select an image before starting image processing.");
return;
}
auto boundingBoxNode = m_Controls.boundingBoxSelectionWidget->GetSelectedNode();
if (boundingBoxNode.IsNull())
{
QMessageBox::information(nullptr, "Warning", "Please load and select a cropping object before starting image processing.");
return;
}
if (!imageNode->GetData()->GetTimeGeometry()->IsValidTimePoint(timePoint))
{
QMessageBox::information(nullptr, "Warning", "Please select a time point that is within the time bounds of the selected image.");
return;
}
const auto timeStep = imageNode->GetData()->GetTimeGeometry()->TimePointToTimeStep(timePoint);
auto image = dynamic_cast<mitk::Image*>(imageNode->GetData());
auto boundingBox = dynamic_cast<mitk::GeometryData*>(boundingBoxNode->GetData());
if (nullptr != image && nullptr != boundingBox)
{
// Check if initial node name is already in box name
std::string imagePrefix = "";
if (boundingBoxNode->GetName().find(imageNode->GetName()) != 0)
{
imagePrefix = imageNode->GetName() + "_";
}
QString imageName;
if (mask)
{
imageName = QString::fromStdString(imagePrefix + boundingBoxNode->GetName() + "_masked");
}
else
{
imageName = QString::fromStdString(imagePrefix + boundingBoxNode->GetName() + "_cropped");
}
if (m_Controls.checkBoxCropTimeStepOnly->isChecked())
{
imageName = imageName + "_T" + QString::number(timeStep);
}
// image and bounding shape ok, set as input
auto croppedImageNode = mitk::DataNode::New();
auto cutter = mitk::BoundingShapeCropper::New();
cutter->SetGeometry(boundingBox);
// adjustable in advanced settings
cutter->SetUseWholeInputRegion(mask); //either mask (mask=true) or crop (mask=false)
cutter->SetOutsideValue(m_CropOutsideValue);
cutter->SetUseCropTimeStepOnly(m_Controls.checkBoxCropTimeStepOnly->isChecked());
cutter->SetCurrentTimeStep(timeStep);
// TODO: Add support for MultiLayer (right now only Mulitlabel support)
auto labelsetImageInput = dynamic_cast<mitk::LabelSetImage*>(image);
if (nullptr != labelsetImageInput)
{
cutter->SetInput(labelsetImageInput);
// do the actual cutting
try
{
cutter->Update();
}
catch (const itk::ExceptionObject& e)
{
std::string message = std::string("The Cropping filter could not process because of: \n ") + e.GetDescription();
QMessageBox::warning(nullptr, tr("Cropping not possible!"), tr(message.c_str()),
QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
return;
}
auto labelSetImage = mitk::LabelSetImage::New();
labelSetImage->InitializeByLabeledImage(cutter->GetOutput());
for (unsigned int i = 0; i < labelsetImageInput->GetNumberOfLayers(); i++)
{
labelSetImage->AddLabelSetToLayer(i, labelsetImageInput->GetLabelSet(i));
}
croppedImageNode->SetData(labelSetImage);
croppedImageNode->SetProperty("name", mitk::StringProperty::New(imageName.toStdString()));
//add cropping result to the current data storage as child node to the image node
if (!m_Controls.checkOverwriteImage->isChecked())
{
if (!this->GetDataStorage()->Exists(croppedImageNode))
{
this->GetDataStorage()->Add(croppedImageNode, imageNode);
}
}
else // original image will be overwritten by the result image and the bounding box of the result is adjusted
{
imageNode->SetData(labelSetImage);
imageNode->Modified();
// Adjust coordinate system by doing a reinit on
auto tempDataStorage = mitk::DataStorage::SetOfObjects::New();
tempDataStorage->InsertElement(0, imageNode);
// initialize the views to the bounding geometry
auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(tempDataStorage);
mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
}
}
else
{
cutter->SetInput(image);
// do the actual cutting
try
{
cutter->Update();
}
catch (const itk::ExceptionObject& e)
{
std::string message = std::string("The Cropping filter could not process because of: \n ") + e.GetDescription();
QMessageBox::warning(nullptr, tr("Cropping not possible!"), tr(message.c_str()),
QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
return;
}
//add cropping result to the current data storage as child node to the image node
if (!m_Controls.checkOverwriteImage->isChecked())
{
croppedImageNode->SetData(cutter->GetOutput());
croppedImageNode->SetProperty("name", mitk::StringProperty::New(imageName.toStdString()));
croppedImageNode->SetProperty("color", mitk::ColorProperty::New(1.0, 1.0, 1.0));
mitk::LevelWindow levelWindow;
imageNode->GetLevelWindow(levelWindow);
croppedImageNode->SetLevelWindow(levelWindow);
if (!this->GetDataStorage()->Exists(croppedImageNode))
{
this->GetDataStorage()->Add(croppedImageNode, imageNode);
imageNode->SetVisibility(mask); // Give the user a visual clue that something happened when image was cropped
}
}
else // original image will be overwritten by the result image and the bounding box of the result is adjusted
{
mitk::LevelWindow levelWindow;
imageNode->GetLevelWindow(levelWindow);
imageNode->SetData(cutter->GetOutput());
imageNode->SetLevelWindow(levelWindow);
// Adjust coordinate system by doing a reinit on
auto tempDataStorage = mitk::DataStorage::SetOfObjects::New();
tempDataStorage->InsertElement(0, imageNode);
// initialize the views to the bounding geometry
auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(tempDataStorage);
mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
}
}
}
else
{
QMessageBox::information(nullptr, "Warning", "Please load and select an image before starting image processing.");
}
}
void QmitkImageCropperView::SetDefaultGUI()
{
m_Controls.buttonCreateNewBoundingBox->setEnabled(false);
m_Controls.buttonCropping->setEnabled(false);
m_Controls.buttonMasking->setEnabled(false);
m_Controls.buttonAdvancedSettings->setEnabled(false);
m_Controls.groupImageSettings->setEnabled(false);
m_Controls.groupImageSettings->setVisible(false);
m_Controls.checkOverwriteImage->setChecked(false);
m_Controls.checkBoxCropTimeStepOnly->setChecked(false);
}
QString QmitkImageCropperView::AdaptBoundingObjectName(const QString& name) const
{
unsigned int counter = 2;
QString newName = QString("%1 %2").arg(name).arg(counter);
while (nullptr != this->GetDataStorage()->GetNode(mitk::NodePredicateFunction::New([&newName](const mitk::DataNode *node)
{
return 0 == node->GetName().compare(newName.toStdString());
})))
{
newName = QString("%1 %2").arg(name).arg(++counter);
}
return newName;
}
diff --git a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp
index e3d982e82d..d491d7b227 100644
--- a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp
+++ b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorView.cpp
@@ -1,457 +1,455 @@
/*============================================================================
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 "QmitkImageNavigatorView.h"
#include <itkSpatialOrientationAdapter.h>
#include <QmitkStepperAdapter.h>
#include <QmitkRenderWindow.h>
#include <mitkTimeGeometry.h>
+#include <mitkTimeNavigationController.h>
#include <berryConstants.h>
#include <mitkPlaneGeometry.h>
const std::string QmitkImageNavigatorView::VIEW_ID = "org.mitk.views.imagenavigator";
QmitkImageNavigatorView::QmitkImageNavigatorView()
: m_AxialStepperAdapter(nullptr)
, m_SagittalStepperAdapter(nullptr)
, m_CoronalStepperAdapter(nullptr)
, m_TimeStepperAdapter(nullptr)
, m_Parent(nullptr)
, m_IRenderWindowPart(nullptr)
{
}
QmitkImageNavigatorView::~QmitkImageNavigatorView()
{
}
void QmitkImageNavigatorView::CreateQtPartControl(QWidget *parent)
{
// create GUI widgets
m_Parent = parent;
m_Controls.setupUi(parent);
connect(m_Controls.m_XWorldCoordinateSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnMillimetreCoordinateValueChanged()));
connect(m_Controls.m_YWorldCoordinateSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnMillimetreCoordinateValueChanged()));
connect(m_Controls.m_ZWorldCoordinateSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnMillimetreCoordinateValueChanged()));
m_Parent->setEnabled(false);
mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart();
this->RenderWindowPartActivated(renderPart);
+
+ auto* timeController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+
+ if (m_TimeStepperAdapter)
+ {
+ m_TimeStepperAdapter->deleteLater();
+ }
+
+ m_TimeStepperAdapter = new QmitkStepperAdapter(m_Controls.m_TimeSliceNavigationWidget,
+ timeController->GetStepper());
+ m_Controls.m_TimeSliceNavigationWidget->setEnabled(true);
+ m_Controls.m_TimeLabel->setEnabled(true);
+ connect(m_TimeStepperAdapter, SIGNAL(Refetch()), this, SLOT(OnRefetch()));
}
void QmitkImageNavigatorView::SetFocus ()
{
m_Controls.m_XWorldCoordinateSpinBox->setFocus();
}
void QmitkImageNavigatorView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (this->m_IRenderWindowPart != renderWindowPart)
{
this->m_IRenderWindowPart = renderWindowPart;
this->m_Parent->setEnabled(true);
QmitkRenderWindow* renderWindow = renderWindowPart->GetQmitkRenderWindow("axial");
if (renderWindow)
{
if (m_AxialStepperAdapter)
m_AxialStepperAdapter->deleteLater();
m_AxialStepperAdapter = new QmitkStepperAdapter(m_Controls.m_AxialSliceNavigationWidget,
- renderWindow->GetSliceNavigationController()->GetSlice());
+ renderWindow->GetSliceNavigationController()->GetStepper());
m_Controls.m_AxialSliceNavigationWidget->setEnabled(true);
m_Controls.m_AxialLabel->setEnabled(true);
m_Controls.m_ZWorldCoordinateSpinBox->setEnabled(true);
connect(m_AxialStepperAdapter, SIGNAL(Refetch()), this, SLOT(OnRefetch()));
}
else
{
m_Controls.m_AxialSliceNavigationWidget->setEnabled(false);
m_Controls.m_AxialLabel->setEnabled(false);
m_Controls.m_ZWorldCoordinateSpinBox->setEnabled(false);
}
renderWindow = renderWindowPart->GetQmitkRenderWindow("sagittal");
if (renderWindow)
{
if (m_SagittalStepperAdapter)
m_SagittalStepperAdapter->deleteLater();
m_SagittalStepperAdapter = new QmitkStepperAdapter(m_Controls.m_SagittalSliceNavigationWidget,
- renderWindow->GetSliceNavigationController()->GetSlice());
+ renderWindow->GetSliceNavigationController()->GetStepper());
m_Controls.m_SagittalSliceNavigationWidget->setEnabled(true);
m_Controls.m_SagittalLabel->setEnabled(true);
m_Controls.m_YWorldCoordinateSpinBox->setEnabled(true);
connect(m_SagittalStepperAdapter, SIGNAL(Refetch()), this, SLOT(OnRefetch()));
}
else
{
m_Controls.m_SagittalSliceNavigationWidget->setEnabled(false);
m_Controls.m_SagittalLabel->setEnabled(false);
m_Controls.m_YWorldCoordinateSpinBox->setEnabled(false);
}
renderWindow = renderWindowPart->GetQmitkRenderWindow("coronal");
if (renderWindow)
{
if (m_CoronalStepperAdapter)
m_CoronalStepperAdapter->deleteLater();
m_CoronalStepperAdapter = new QmitkStepperAdapter(m_Controls.m_CoronalSliceNavigationWidget,
- renderWindow->GetSliceNavigationController()->GetSlice());
+ renderWindow->GetSliceNavigationController()->GetStepper());
m_Controls.m_CoronalSliceNavigationWidget->setEnabled(true);
m_Controls.m_CoronalLabel->setEnabled(true);
m_Controls.m_XWorldCoordinateSpinBox->setEnabled(true);
connect(m_CoronalStepperAdapter, SIGNAL(Refetch()), this, SLOT(OnRefetch()));
}
else
{
m_Controls.m_CoronalSliceNavigationWidget->setEnabled(false);
m_Controls.m_CoronalLabel->setEnabled(false);
m_Controls.m_XWorldCoordinateSpinBox->setEnabled(false);
}
- mitk::SliceNavigationController* timeController = renderWindowPart->GetTimeNavigationController();
- if (timeController)
- {
- if (m_TimeStepperAdapter)
- m_TimeStepperAdapter->deleteLater();
- m_TimeStepperAdapter = new QmitkStepperAdapter(m_Controls.m_TimeSliceNavigationWidget,
- timeController->GetTime());
- m_Controls.m_TimeSliceNavigationWidget->setEnabled(true);
- m_Controls.m_TimeLabel->setEnabled(true);
- }
- else
- {
- m_Controls.m_TimeSliceNavigationWidget->setEnabled(false);
- m_Controls.m_TimeLabel->setEnabled(false);
- }
-
this->OnRefetch();
}
}
void QmitkImageNavigatorView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/)
{
m_IRenderWindowPart = nullptr;
m_Parent->setEnabled(false);
}
int QmitkImageNavigatorView::GetSizeFlags(bool width)
{
if(!width)
{
return berry::Constants::MIN | berry::Constants::MAX | berry::Constants::FILL;
}
else
{
return 0;
}
}
int QmitkImageNavigatorView::ComputePreferredSize(bool width, int /*availableParallel*/, int /*availablePerpendicular*/, int preferredResult)
{
if(width==false)
{
return 200;
}
else
{
return preferredResult;
}
}
int QmitkImageNavigatorView::GetClosestAxisIndex(mitk::Vector3D normal)
{
// cos(theta) = normal . axis
// cos(theta) = (a, b, c) . (d, e, f)
// cos(theta) = (a, b, c) . (1, 0, 0) = a
// cos(theta) = (a, b, c) . (0, 1, 0) = b
// cos(theta) = (a, b, c) . (0, 0, 1) = c
double absCosThetaWithAxis[3];
for (int i = 0; i < 3; i++)
{
absCosThetaWithAxis[i] = fabs(normal[i]);
}
int largestIndex = 0;
double largestValue = absCosThetaWithAxis[0];
for (int i = 1; i < 3; i++)
{
if (absCosThetaWithAxis[i] > largestValue)
{
largestValue = absCosThetaWithAxis[i];
largestIndex = i;
}
}
return largestIndex;
}
void QmitkImageNavigatorView::SetBorderColors()
{
if (m_IRenderWindowPart)
{
QString decoColor;
QmitkRenderWindow* renderWindow = m_IRenderWindowPart->GetQmitkRenderWindow("axial");
if (renderWindow)
{
decoColor = GetDecorationColorOfGeometry(renderWindow);
mitk::PlaneGeometry::ConstPointer geometry = renderWindow->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (geometry.IsNotNull())
{
mitk::Vector3D normal = geometry->GetNormal();
int axis = this->GetClosestAxisIndex(normal);
this->SetBorderColor(axis, decoColor);
}
}
renderWindow = m_IRenderWindowPart->GetQmitkRenderWindow("sagittal");
if (renderWindow)
{
decoColor = GetDecorationColorOfGeometry(renderWindow);
mitk::PlaneGeometry::ConstPointer geometry = renderWindow->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (geometry.IsNotNull())
{
mitk::Vector3D normal = geometry->GetNormal();
int axis = this->GetClosestAxisIndex(normal);
this->SetBorderColor(axis, decoColor);
}
}
renderWindow = m_IRenderWindowPart->GetQmitkRenderWindow("coronal");
if (renderWindow)
{
decoColor = GetDecorationColorOfGeometry(renderWindow);
mitk::PlaneGeometry::ConstPointer geometry = renderWindow->GetSliceNavigationController()->GetCurrentPlaneGeometry();
if (geometry.IsNotNull())
{
mitk::Vector3D normal = geometry->GetNormal();
int axis = this->GetClosestAxisIndex(normal);
this->SetBorderColor(axis, decoColor);
}
}
}
}
QString QmitkImageNavigatorView::GetDecorationColorOfGeometry(QmitkRenderWindow* renderWindow)
{
QColor color;
float rgb[3] = {1.0f, 1.0f, 1.0f};
float rgbMax = 255.0f;
mitk::BaseRenderer::GetInstance(renderWindow->GetVtkRenderWindow())->GetCurrentWorldPlaneGeometryNode()->GetColor(rgb);
color.setRed(static_cast<int>(rgb[0]*rgbMax + 0.5));
color.setGreen(static_cast<int>(rgb[1]*rgbMax + 0.5));
color.setBlue(static_cast<int>(rgb[2]*rgbMax + 0.5));
QString colorAsString = QString(color.name());
return colorAsString;
}
void QmitkImageNavigatorView::SetBorderColor(int axis, QString colorAsStyleSheetString)
{
if (axis == 0)
{
this->SetBorderColor(m_Controls.m_XWorldCoordinateSpinBox, colorAsStyleSheetString);
}
else if (axis == 1)
{
this->SetBorderColor(m_Controls.m_YWorldCoordinateSpinBox, colorAsStyleSheetString);
}
else if (axis == 2)
{
this->SetBorderColor(m_Controls.m_ZWorldCoordinateSpinBox, colorAsStyleSheetString);
}
}
void QmitkImageNavigatorView::SetBorderColor(QDoubleSpinBox *spinBox, QString colorAsStyleSheetString)
{
assert(spinBox);
spinBox->setStyleSheet(QString("border: 2px solid ") + colorAsStyleSheetString + ";");
}
void QmitkImageNavigatorView::OnMillimetreCoordinateValueChanged()
{
if (m_IRenderWindowPart)
{
mitk::TimeGeometry::ConstPointer geometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldTimeGeometry();
if (geometry.IsNotNull())
{
mitk::Point3D positionInWorldCoordinates;
positionInWorldCoordinates[0] = m_Controls.m_XWorldCoordinateSpinBox->value();
positionInWorldCoordinates[1] = m_Controls.m_YWorldCoordinateSpinBox->value();
positionInWorldCoordinates[2] = m_Controls.m_ZWorldCoordinateSpinBox->value();
m_IRenderWindowPart->SetSelectedPosition(positionInWorldCoordinates);
}
}
}
void QmitkImageNavigatorView::OnRefetch()
{
if (nullptr == m_IRenderWindowPart)
{
return;
}
mitk::TimeGeometry::ConstPointer timeGeometry = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetInputWorldTimeGeometry();
if (timeGeometry.IsNull())
{
return;
}
- SetVisibilityOfTimeSlider(timeGeometry->CountTimeSteps());
- mitk::TimeStepType timeStep = m_IRenderWindowPart->GetActiveQmitkRenderWindow()->GetSliceNavigationController()->GetTime()->GetPos();
+ const auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ this->SetVisibilityOfTimeSlider(timeNavigationController->GetStepper()->GetSteps());
+ const mitk::TimeStepType timeStep = timeNavigationController->GetSelectedTimeStep();
mitk::BaseGeometry::Pointer geometry = timeGeometry->GetGeometryForTimeStep(timeStep);
if (geometry.IsNotNull())
{
mitk::BoundingBox::BoundsArrayType bounds = geometry->GetBounds();
mitk::Point3D cornerPoint1InIndexCoordinates;
cornerPoint1InIndexCoordinates[0] = bounds[0];
cornerPoint1InIndexCoordinates[1] = bounds[2];
cornerPoint1InIndexCoordinates[2] = bounds[4];
mitk::Point3D cornerPoint2InIndexCoordinates;
cornerPoint2InIndexCoordinates[0] = bounds[1];
cornerPoint2InIndexCoordinates[1] = bounds[3];
cornerPoint2InIndexCoordinates[2] = bounds[5];
if (!geometry->GetImageGeometry())
{
cornerPoint1InIndexCoordinates[0] += 0.5;
cornerPoint1InIndexCoordinates[1] += 0.5;
cornerPoint1InIndexCoordinates[2] += 0.5;
cornerPoint2InIndexCoordinates[0] -= 0.5;
cornerPoint2InIndexCoordinates[1] -= 0.5;
cornerPoint2InIndexCoordinates[2] -= 0.5;
}
mitk::Point3D crossPositionInWorldCoordinates = m_IRenderWindowPart->GetSelectedPosition();
mitk::Point3D cornerPoint1InWorldCoordinates;
mitk::Point3D cornerPoint2InWorldCoordinates;
geometry->IndexToWorld(cornerPoint1InIndexCoordinates, cornerPoint1InWorldCoordinates);
geometry->IndexToWorld(cornerPoint2InIndexCoordinates, cornerPoint2InWorldCoordinates);
m_Controls.m_XWorldCoordinateSpinBox->blockSignals(true);
m_Controls.m_YWorldCoordinateSpinBox->blockSignals(true);
m_Controls.m_ZWorldCoordinateSpinBox->blockSignals(true);
m_Controls.m_XWorldCoordinateSpinBox->setMinimum(
std::min(cornerPoint1InWorldCoordinates[0], cornerPoint2InWorldCoordinates[0]));
m_Controls.m_YWorldCoordinateSpinBox->setMinimum(
std::min(cornerPoint1InWorldCoordinates[1], cornerPoint2InWorldCoordinates[1]));
m_Controls.m_ZWorldCoordinateSpinBox->setMinimum(
std::min(cornerPoint1InWorldCoordinates[2], cornerPoint2InWorldCoordinates[2]));
m_Controls.m_XWorldCoordinateSpinBox->setMaximum(
std::max(cornerPoint1InWorldCoordinates[0], cornerPoint2InWorldCoordinates[0]));
m_Controls.m_YWorldCoordinateSpinBox->setMaximum(
std::max(cornerPoint1InWorldCoordinates[1], cornerPoint2InWorldCoordinates[1]));
m_Controls.m_ZWorldCoordinateSpinBox->setMaximum(
std::max(cornerPoint1InWorldCoordinates[2], cornerPoint2InWorldCoordinates[2]));
m_Controls.m_XWorldCoordinateSpinBox->setValue(crossPositionInWorldCoordinates[0]);
m_Controls.m_YWorldCoordinateSpinBox->setValue(crossPositionInWorldCoordinates[1]);
m_Controls.m_ZWorldCoordinateSpinBox->setValue(crossPositionInWorldCoordinates[2]);
m_Controls.m_XWorldCoordinateSpinBox->blockSignals(false);
m_Controls.m_YWorldCoordinateSpinBox->blockSignals(false);
m_Controls.m_ZWorldCoordinateSpinBox->blockSignals(false);
/// Calculating 'inverse direction' property.
mitk::AffineTransform3D::MatrixType matrix = geometry->GetIndexToWorldTransform()->GetMatrix();
matrix.GetVnlMatrix().normalize_columns();
mitk::AffineTransform3D::MatrixType::InternalMatrixType inverseMatrix = matrix.GetInverse();
for (int worldAxis = 0; worldAxis < 3; ++worldAxis)
{
QmitkRenderWindow *renderWindow = worldAxis == 0 ? m_IRenderWindowPart->GetQmitkRenderWindow("sagittal") :
worldAxis == 1 ? m_IRenderWindowPart->GetQmitkRenderWindow("coronal") :
m_IRenderWindowPart->GetQmitkRenderWindow("axial");
if (renderWindow)
{
const mitk::BaseGeometry* rendererGeometry = renderWindow->GetRenderer()->GetCurrentWorldGeometry();
/// Because of some problems with the current way of event signalling,
/// 'Modified' events are sent out from the stepper while the renderer
/// does not have a geometry yet. Therefore, we do a nullptr check here.
/// See bug T22122. This check can be resolved after T22122 got fixed.
if (rendererGeometry)
{
int dominantAxis =
itk::Function::Max3(inverseMatrix[0][worldAxis], inverseMatrix[1][worldAxis], inverseMatrix[2][worldAxis]);
bool referenceGeometryAxisInverted = inverseMatrix[dominantAxis][worldAxis] < 0;
bool rendererZAxisInverted = rendererGeometry->GetAxisVector(2)[worldAxis] < 0;
/// `referenceGeometryAxisInverted` tells if the direction of the corresponding axis
/// of the reference geometry is flipped compared to the 'world direction' or not.
///
/// `rendererZAxisInverted` tells if direction of the renderer geometry z axis is
/// flipped compared to the 'world direction' or not. This is the same as the indexing
/// direction in the slice navigation controller and matches the 'top' property when
/// initialising the renderer planes. (If 'top' was true then the direction is
/// inverted.)
///
/// The world direction can be +1 ('up') that means right, anterior or superior, or
/// it can be -1 ('down') that means left, posterior or inferior, respectively.
///
/// If these two do not match, we have to invert the index between the slice navigation
/// controller and the slider navigator widget, so that the user can see and control
/// the index according to the reference geometry, rather than the slice navigation
/// controller. The index in the slice navigation controller depends on in which way
/// the reference geometry has been resliced for the renderer, and it does not necessarily
/// match neither the world direction, nor the direction of the corresponding axis of
/// the reference geometry. Hence, it is a merely internal information that should not
/// be exposed to the GUI.
///
/// So that one can navigate in the same world direction by dragging the slider
/// right, regardless of the direction of the corresponding axis of the reference
/// geometry, we invert the direction of the controls if the reference geometry axis
/// is inverted but the direction is not ('inversDirection' is false) or the other
/// way around.
bool inverseDirection = referenceGeometryAxisInverted != rendererZAxisInverted;
QmitkSliceNavigationWidget* sliceNavigationWidget =
worldAxis == 0 ? m_Controls.m_SagittalSliceNavigationWidget :
worldAxis == 1 ? m_Controls.m_CoronalSliceNavigationWidget :
m_Controls.m_AxialSliceNavigationWidget;
sliceNavigationWidget->SetInverseDirection(inverseDirection);
// This should be a preference (see T22254)
// bool invertedControls = referenceGeometryAxisInverted != inverseDirection;
// navigatorWidget->SetInvertedControls(invertedControls);
}
}
}
}
this->SetBorderColors();
}
-
void QmitkImageNavigatorView::SetVisibilityOfTimeSlider(std::size_t timeSteps)
{
m_Controls.m_TimeSliceNavigationWidget->setVisible(timeSteps > 1);
m_Controls.m_TimeLabel->setVisible(timeSteps > 1);
}
diff --git a/Plugins/org.mitk.gui.qt.matchpoint.framereg/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.matchpoint.framereg/documentation/UserManual/Manual.dox
index ed515cb4ea..71c6ba122d 100644
--- a/Plugins/org.mitk.gui.qt.matchpoint.framereg/documentation/UserManual/Manual.dox
+++ b/Plugins/org.mitk.gui.qt.matchpoint.framereg/documentation/UserManual/Manual.dox
@@ -1,55 +1,55 @@
/**
\page org_mitk_views_matchpoint_framereg The MatchPoint Frame Correction View
\imageMacro{"map_framereg_icon_doc.svg", "Icon of the MatchPoint Algorithm Control", 3}
\tableofcontents
\section MAP_FRAME_Introduction Introduction
This view offers the user a way to use a selected registration algorithm in order to apply a frame correction to a selected 3D+t image.
This is for example useful if you have a dynamic image with motion artifacts in some time points and you want to reduce/remove these motion artifacts.
\section MAP_FRAME_Usage Usage
\imageMacro{"map_framereg_example.png" , "Example screenshot of the view.", 15}
To use the view, a 3D+t image must be selected and a registration algorithm must be loaded. For the selection of an algorithm please see \ref org_mitk_views_matchpoint_algorithm_browser .\n
The correction is performed such that every time frame of the image is registered to the first time frame. And the corrected time frames are mapped to the same geometry as the first frame.\n
If an algorithm is loaded and an input images is selected, the view will automatically switch to the <i>Execution</i> tab.
\subsection MAP_FRAME_Usage_selection Algorithm selection tab
\imageMacro{map_step1_selection.png, "Details of the algorithm selection tab.", 6}
In this tab, you can load the algorithm selected in the MatchPoint Algorithm Browser. In the area below the selection button the profile information of the registration algorithm is displayed.
For a detailed description of the profile characteristics the user is referred to \ref org_mitk_views_matchpoint_algorithm_browser .\n
When clicking the <i>Load selected algorithm</i> button, the selected algorithm will be used by the view for the frame correction and the name of the algorithm will be displayed in the text field <i>Loaded algorithm</i> at the top of the view.\n
At this point, it has no effect if you change the the selection in the algorithm browser. The view will keep the loaded algorithm until you choose to load another one.
\subsection MAP_FRAME_Usage_exec Execution tab
\imageMacro{map_step2_execution.png, "Details of the execution tab.", 6}
In this tab you can specify a name for the correction job (this will determine the names of the result nodes in the data manager).\n
Clicking the <i>Start</i> button will trigger the correction process.
\subsection MAP_FRAME_Usage_settings Settings tab
\imageMacro{map_step3_settings.png, "Details of the settings tab.", 6}
In this tab, you can configure the \ref MAP_FRAME_Mapper_Settings which are used for the corrected frames, or parameterize the loaded algorithm (before it starts), if it offers any possibility to do so.
\subsubsection MAP_FRAME_Mapper_Settings Mapping settings
For the mapping of corrected images, you have several settings available:\n
-\li <b>Allow undefined pixels</b> 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 <i>padding value</i>.
-\li <b>Allow error pixels</b> 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 <i>error value</i>.
-\li <b>Interpolator</b> Set to choose the interpolation strategy that should be used for mapping. See details at \ref MAP_FRAME_Interpolation .
+\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 <i>padding value</i>.
+\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. These pixels will get the <i>error value</i>.
+\li Interpolator: Set to choose the interpolation strategy that should be used for mapping. See details at \ref MAP_FRAME_Interpolation .
\subsubsection MAP_FRAME_Interpolation Interpolation
You can choose from the following interpolation strategies:\n
-\li <b>Nearest Neighbour</b> Use the value of the nearest pixel. Fastest, but high interpolation errors for gray value images. Right choice for label images or masks.
-\li <b>Linear"</b> Fast linear interpolation with often sufficient quality. Tends to blur edges.
-\li <b>BSpline (3rd order)</b> Good trade off between time and quality.
-\li <b>Windowed Sinc (Hamming)</b> Good interpolation quality but very time consuming.
-\li <b>Windowed Sinc (Welch)</b> Good interpolation quality but very time consuming.
+\li Nearest Neighbour: 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.
\subsection MAP_FRAME_Usage_frame_selection Frame selection tab
\imageMacro{map_step4_frameselection.png, "Details of the frame selection tab.", 6}
In this tab you can specify the frames of the currently selected image that should be corrected. As default all frames of an image will be selected.
If you only select specific frames, these frames will be corrected whilst all other frames will be just copied unchanged.
*/
diff --git a/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.cpp b/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.cpp
index 85044298f9..3026cd148c 100644
--- a/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.cpp
+++ b/Plugins/org.mitk.gui.qt.matchpoint.mapper/src/internal/QmitkMatchPointMapper.cpp
@@ -1,584 +1,559 @@
/*============================================================================
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 "org_mitk_gui_qt_matchpoint_mapper_Activator.h"
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Mitk
#include <mitkImageAccessByItk.h>
#include <mitkStatusBar.h>
#include "mitkImageMappingHelper.h"
#include "mitkMAPRegistrationWrapper.h"
#include "mitkMatchPointPropertyTags.h"
#include "mitkRegistrationHelper.h"
#include <mitkResultNodeGenerationHelper.h>
#include <mitkUIDHelper.h>
#include <mitkMAPAlgorithmHelper.h>
#include <mitkResultNodeGenerationHelper.h>
#include <mitkNodePredicateFunction.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateDataProperty.h>
// Qmitk
#include "QmitkMatchPointMapper.h"
// Qt
#include <QMessageBox>
#include <QFileDialog>
#include <QErrorMessage>
#include <QThreadPool>
const std::string QmitkMatchPointMapper::VIEW_ID = "org.mitk.views.matchpoint.mapper";
QmitkMatchPointMapper::QmitkMatchPointMapper()
: m_Parent(nullptr), m_preparedForBinaryInput(false)
{
}
void QmitkMatchPointMapper::SetFocus()
{
//m_Controls.buttonPerformImageProcessing->setFocus();
}
void QmitkMatchPointMapper::CreateConnections()
{
connect(m_Controls.registrationNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkMatchPointMapper::OnRegNodeSelectionChanged);
connect(m_Controls.inputNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkMatchPointMapper::OnInputNodeSelectionChanged);
connect(m_Controls.referenceNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkMatchPointMapper::OnReferenceNodeSelectionChanged);
connect(m_Controls.m_cbManualRef, SIGNAL(clicked()), this, SLOT(OnManualRefChecked()));
connect(m_Controls.m_cbLinkFactors, SIGNAL(clicked()), this, SLOT(OnLinkSampleFactorChecked()));
connect(m_Controls.m_sbXFactor, SIGNAL(valueChanged(double)), this, SLOT(OnXFactorChanged(double)));
connect(m_Controls.m_pbMap, SIGNAL(clicked()), this, SLOT(OnMapBtnPushed()));
connect(m_Controls.m_pbRefine, SIGNAL(clicked()), this, SLOT(OnRefineBtnPushed()));
}
void QmitkMatchPointMapper::Error(QString msg)
{
mitk::StatusBar::GetInstance()->DisplayErrorText(msg.toLatin1());
MITK_ERROR << msg.toStdString().c_str();
m_Controls.m_teLog->append(QStringLiteral("<font color='red'><b>") + msg + QStringLiteral("</b></font>"));
}
void QmitkMatchPointMapper::CreateQtPartControl(QWidget* parent)
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls.setupUi(parent);
m_Parent = parent;
this->m_Controls.registrationNodeSelector->SetDataStorage(this->GetDataStorage());
this->m_Controls.registrationNodeSelector->SetSelectionIsOptional(true);
this->m_Controls.inputNodeSelector->SetDataStorage(this->GetDataStorage());
this->m_Controls.inputNodeSelector->SetSelectionIsOptional(false);
this->m_Controls.referenceNodeSelector->SetDataStorage(this->GetDataStorage());
this->m_Controls.referenceNodeSelector->SetSelectionIsOptional(false);
this->m_Controls.registrationNodeSelector->SetInvalidInfo("Select valid registration.");
this->m_Controls.registrationNodeSelector->SetEmptyInfo("Assuming identity mapping. Select registration to change.");
this->m_Controls.registrationNodeSelector->SetPopUpTitel("Select registration.");
this->m_Controls.registrationNodeSelector->SetPopUpHint("Select a registration object that should be used for the mapping of the input data. If no registration is selected, identity will be assumed for the mapping.");
this->m_Controls.inputNodeSelector->SetInvalidInfo("Select input data.");
this->m_Controls.inputNodeSelector->SetPopUpTitel("Select input data.");
this->m_Controls.inputNodeSelector->SetPopUpHint("Select the input data for the mapping. (Images or point sets are supported so far).");
this->m_Controls.referenceNodeSelector->SetInvalidInfo("Select the reference image.");
this->m_Controls.referenceNodeSelector->SetPopUpTitel("Select the reference image.");
this->m_Controls.referenceNodeSelector->SetPopUpHint("Select the reference image that specifies the target geometrie the input should be mapped into.");
this->ConfigureRegNodePredicate();
this->ConfigureNodePredicates();
// show first page
m_Controls.m_tabs->setCurrentIndex(0);
this->CreateConnections();
this->CheckInputs();
this->ConfigureProgressInfos();
this->ConfigureMappingControls();
}
/** Method checks if the currently selected reg node has a direct kernel that
* can be decomposed in a rotation matrix and a offset. If this is true, true
* is returned. In all other cases false is returned.*/
bool QmitkMatchPointMapper::IsAbleToRefineGeometry() const
{
bool result = false;
if (this->m_spSelectedRegNode.IsNotNull())
{
const mitk::MAPRegistrationWrapper* wrapper = dynamic_cast<const mitk::MAPRegistrationWrapper*>
(this->m_spSelectedRegNode->GetData());
//if the helper does not return null, we can refine the geometry.
result = mitk::MITKRegistrationHelper::getAffineMatrix(wrapper, false).IsNotNull();
}
return result;
}
bool QmitkMatchPointMapper::IsBinaryInput() const
{
auto maskPredicate = mitk::MITKRegistrationHelper::MaskNodePredicate();
bool result = false;
if(this->m_spSelectedInputNode.IsNotNull())
{
result = maskPredicate->CheckNode(this->m_spSelectedInputNode);
}
return result;
}
bool QmitkMatchPointMapper::IsPointSetInput() const
{
bool result = false;
if (this->m_spSelectedInputNode.IsNotNull())
{
result = dynamic_cast<const mitk::PointSet*>(this->m_spSelectedInputNode->GetData()) != nullptr;
}
return result;
}
mitk::DataNode::Pointer QmitkMatchPointMapper::GetAutoRefNodeByReg()
{
mitk::DataNode::Pointer spResult = nullptr;
if (this->m_spSelectedRegNode.IsNotNull() && this->m_spSelectedRegNode->GetData())
{
std::string nodeName;
mitk::BaseProperty* uidProp = m_spSelectedRegNode->GetData()->GetProperty(mitk::Prop_RegAlgTargetData);
if (uidProp)
{
//search for the target node
mitk::NodePredicateDataProperty::Pointer predicate = mitk::NodePredicateDataProperty::New(mitk::Prop_UID,
uidProp);
spResult = this->GetDataStorage()->GetNode(predicate);
}
}
if (spResult.IsNull() && this->m_spSelectedInputNode.IsNotNull())
{
//no really reference is available -> use the input as reference
spResult = this->m_spSelectedInputNode;
if (this->m_spSelectedRefNode != spResult)
{
m_Controls.m_teLog->append(
QStringLiteral("<font color='gray'><i>Cannot determine reference automatically. Use input image as reference.</i></font>"));
}
}
return spResult;
}
void QmitkMatchPointMapper::ConfigureRegNodePredicate(const mitk::DataNode* input)
{
mitk::NodePredicateBase::ConstPointer nodePredicate = mitk::MITKRegistrationHelper::RegNodePredicate();
if (input != nullptr)
{
unsigned int dimension = 0;
auto inputImage = dynamic_cast<mitk::Image*>(input->GetData());
auto pointset = dynamic_cast<const mitk::PointSet*>(input->GetData());
if (inputImage)
{
dimension = inputImage->GetDimension();
if (inputImage->GetTimeSteps() > 1)
{
//images has multiple time steps -> remove one dimension.
dimension -= 1;
}
}
else if (pointset)
{
dimension = 3;
}
auto dimCheck = [dimension](const mitk::DataNode * node)
{
const mitk::MAPRegistrationWrapper* wrapper = dynamic_cast < const mitk::MAPRegistrationWrapper* >(node->GetData());
return wrapper != nullptr && wrapper->GetMovingDimensions() == dimension;
};
mitk::NodePredicateFunction::Pointer hasCorrectDim = mitk::NodePredicateFunction::New(dimCheck);
nodePredicate = mitk::NodePredicateAnd::New(nodePredicate, hasCorrectDim).GetPointer();
}
this->m_Controls.registrationNodeSelector->SetNodePredicate(nodePredicate);
}
std::function<bool(const mitk::DataNode *)> GenerateDimCheckLambda(unsigned int dim)
{
auto dimCheck = [dim](const mitk::DataNode * node)
{
auto inputImage = dynamic_cast<mitk::Image*>(node->GetData());
return inputImage != nullptr &&
(inputImage->GetDimension() == dim ||
(inputImage->GetDimension() == dim + 1 && inputImage->GetTimeSteps()>1));
};
return dimCheck;
}
void QmitkMatchPointMapper::ConfigureNodePredicates(const mitk::DataNode* reg)
{
auto isImage = mitk::MITKRegistrationHelper::ImageNodePredicate();
auto isPointSet = mitk::MITKRegistrationHelper::PointSetNodePredicate();
auto isData = mitk::NodePredicateOr::New(isImage, isPointSet);
mitk::NodePredicateBase::ConstPointer inputPredicate = isData.GetPointer();
mitk::NodePredicateBase::ConstPointer refPredicate = isImage.GetPointer();
if (reg != nullptr)
{
const mitk::MAPRegistrationWrapper* wrapper = dynamic_cast <const mitk::MAPRegistrationWrapper*>(reg->GetData());
if (wrapper != nullptr)
{
auto movingDim = wrapper->GetMovingDimensions();
auto dimCheck = GenerateDimCheckLambda(movingDim);
auto hasCorrectDim = mitk::NodePredicateFunction::New(dimCheck);
if (movingDim == 3)
{
//Remark: Point sets are always 3D
auto is3DInput = mitk::NodePredicateOr::New(isPointSet, mitk::NodePredicateAnd::New(isImage, hasCorrectDim));
inputPredicate = is3DInput.GetPointer();
}
else
{
auto is2DInput = mitk::NodePredicateAnd::New(isImage, hasCorrectDim);
inputPredicate = is2DInput.GetPointer();
}
auto targetDim = wrapper->GetTargetDimensions();
auto targetDimCheck = GenerateDimCheckLambda(targetDim);
auto hasCorrectTargetDim = mitk::NodePredicateFunction::New(targetDimCheck);
auto isRef = mitk::NodePredicateAnd::New(isImage, hasCorrectTargetDim);
refPredicate = isRef;
}
}
this->m_Controls.inputNodeSelector->SetNodePredicate(inputPredicate);
this->m_Controls.referenceNodeSelector->SetNodePredicate(refPredicate);
}
void QmitkMatchPointMapper::CheckInputs()
{
this->m_spSelectedRegNode = this->m_Controls.registrationNodeSelector->GetSelectedNode();
this->m_spSelectedInputNode = this->m_Controls.inputNodeSelector->GetSelectedNode();
this->m_spSelectedRefNode = this->m_Controls.referenceNodeSelector->GetSelectedNode();
if (!(m_Controls.m_cbManualRef->isChecked()))
{
auto autoRefNode = this->GetAutoRefNodeByReg();
if (this->m_spSelectedRefNode != autoRefNode)
{
this->m_spSelectedRefNode = autoRefNode;
QmitkSingleNodeSelectionWidget::NodeList selection;
if (this->m_spSelectedRefNode.IsNotNull())
{
selection.append(this->m_spSelectedRefNode);
}
this->m_Controls.referenceNodeSelector->SetCurrentSelection(selection);
}
}
if (this->m_spSelectedRefNode.IsNotNull() && this->m_spSelectedRefNode->GetData()
&& this->m_spSelectedRefNode->GetData()->GetTimeSteps() > 1)
{
m_Controls.m_teLog->append(
QStringLiteral("<font color='gray'><i>Selected reference image has multiple time steps. Only geometry of time step 1 is used as reference.</i></font>"));
}
}
void QmitkMatchPointMapper::ConfigureMappingControls()
{
bool validInput = m_spSelectedInputNode.IsNotNull();
bool validRef = m_spSelectedRefNode.IsNotNull();
this->m_Controls.referenceNodeSelector->setEnabled(this->m_Controls.m_cbManualRef->isChecked());
this->m_Controls.m_pbMap->setEnabled(validInput && validRef);
this->m_Controls.m_pbRefine->setEnabled(validInput && this->IsAbleToRefineGeometry() && !this->IsPointSetInput());
if (validInput)
{
if (m_spSelectedRegNode.IsNotNull())
{
this->m_Controls.m_leMappedName->setText(tr("mapped_") + QString::fromStdString(m_spSelectedInputNode->GetName())
+ tr("_by_") + QString::fromStdString(m_spSelectedRegNode->GetName()));
}
else
{
this->m_Controls.m_leMappedName->setText(tr("resampled_") + QString::fromStdString(m_spSelectedInputNode->GetName()));
}
}
else
{
this->m_Controls.m_leMappedName->setText(tr("mappedData"));
}
if (this->IsBinaryInput() != this->m_preparedForBinaryInput)
{
if (this->IsBinaryInput())
{
m_Controls.m_teLog->append(
QStringLiteral("<font color='gray'><i>Binary input (mask) detected. Preparing for mask mapping (default interpolation: nearest neigbour; padding value: 0)</i></font>"));
this->m_Controls.m_comboInterpolator->setCurrentIndex(0);
this->m_Controls.m_sbErrorValue->setValue(0);
this->m_Controls.m_sbPaddingValue->setValue(0);
}
else
{
this->m_Controls.m_comboInterpolator->setCurrentIndex(1);
}
this->m_preparedForBinaryInput = this->IsBinaryInput();
}
OnLinkSampleFactorChecked();
}
void QmitkMatchPointMapper::ConfigureProgressInfos()
{
}
void QmitkMatchPointMapper::OnRegNodeSelectionChanged(QList<mitk::DataNode::Pointer> nodes)
{
mitk::DataNode::Pointer regNode;
if (!nodes.isEmpty())
{
regNode = nodes.front();
}
this->ConfigureNodePredicates(regNode);
this->CheckInputs();
this->ConfigureMappingControls();
}
void QmitkMatchPointMapper::OnInputNodeSelectionChanged(QList<mitk::DataNode::Pointer> nodes)
{
mitk::DataNode::Pointer inputNode;
if (!nodes.isEmpty())
{
inputNode = nodes.front();
}
this->ConfigureRegNodePredicate(inputNode);
this->CheckInputs();
this->ConfigureMappingControls();
}
void QmitkMatchPointMapper::OnReferenceNodeSelectionChanged(QList<mitk::DataNode::Pointer> /*nodes*/)
{
this->CheckInputs();
this->ConfigureMappingControls();
}
void QmitkMatchPointMapper::OnManualRefChecked()
{
this->CheckInputs();
this->ConfigureMappingControls();
}
void QmitkMatchPointMapper::OnLinkSampleFactorChecked()
{
this->m_Controls.m_sbYFactor->setEnabled(!(this->m_Controls.m_cbLinkFactors->isChecked()));
this->m_Controls.m_sbZFactor->setEnabled(!(this->m_Controls.m_cbLinkFactors->isChecked()));
if (m_Controls.m_cbLinkFactors->isChecked())
{
this->m_Controls.m_sbYFactor->setValue(this->m_Controls.m_sbXFactor->value());
this->m_Controls.m_sbZFactor->setValue(this->m_Controls.m_sbXFactor->value());
}
}
void QmitkMatchPointMapper::OnMapBtnPushed()
{
SpawnMappingJob();
}
void QmitkMatchPointMapper::OnRefineBtnPushed()
{
SpawnMappingJob(true);
}
void QmitkMatchPointMapper::SpawnMappingJob(bool doGeometryRefinement)
{
if (m_Controls.m_checkClearLog->checkState() == Qt::Checked)
{
this->m_Controls.m_teLog->clear();
}
/////////////////////////
//create job and put it into the thread pool
QmitkMappingJob* pJob = new QmitkMappingJob();
pJob->setAutoDelete(true);
pJob->m_spInputData = this->m_spSelectedInputNode->GetData();
pJob->m_InputDataUID = mitk::EnsureUID(this->m_spSelectedInputNode->GetData());
pJob->m_doGeometryRefinement = doGeometryRefinement;
pJob->m_spRegNode = m_spSelectedRegNode;
if (m_spSelectedRegNode.IsNull())
{
pJob->m_spRegNode = mitk::DataNode::New();
pJob->m_spRegNode->SetData(mitk::GenerateIdentityRegistration3D().GetPointer());
pJob->m_spRegNode->SetName("Auto_Generated_Identity_Transform");
m_Controls.m_teLog->append(
QStringLiteral("<font color='gray'><i>No registration selected. Preforming mapping with identity transform</i></font>"));
}
if (!doGeometryRefinement)
{
pJob->m_spRefGeometry = m_spSelectedRefNode->GetData()->GetGeometry()->Clone().GetPointer();
//check for super/sub sampling
if (m_Controls.m_groupActivateSampling->isChecked())
{
- //change the pixel count and spacing of the geometry
- mitk::BaseGeometry::BoundsArrayType geoBounds = pJob->m_spRefGeometry->GetBounds();
- auto oldSpacing = pJob->m_spRefGeometry->GetSpacing();
- mitk::Vector3D geoSpacing;
-
- geoSpacing[0] = oldSpacing[0] / m_Controls.m_sbXFactor->value();
- geoSpacing[1] = oldSpacing[1] / m_Controls.m_sbYFactor->value();
- geoSpacing[2] = oldSpacing[2] / m_Controls.m_sbZFactor->value();
-
- geoBounds[1] = geoBounds[1] * m_Controls.m_sbXFactor->value();
- geoBounds[3] = geoBounds[3] * m_Controls.m_sbYFactor->value();
- geoBounds[5] = geoBounds[5] * m_Controls.m_sbZFactor->value();
-
- pJob->m_spRefGeometry->SetBounds(geoBounds);
- pJob->m_spRefGeometry->SetSpacing(geoSpacing);
-
- auto oldOrigin = pJob->m_spRefGeometry->GetOrigin();
-
- //if we change the spacing we must also correct the origin to ensure
- //that the voxel matrix still covers the same space. This is due the fact
- //that the origin is not in the corner of the voxel matrix, but in the center
- // of the voxel that is in the corner.
- mitk::Point3D newOrigin;
- for (mitk::Point3D::SizeType i = 0; i < 3; ++i)
- {
- newOrigin[i] = 0.5* (geoSpacing[i] - oldSpacing[i]) + oldOrigin[i];
- }
-
- pJob->m_spRefGeometry->SetOrigin(newOrigin);
+ pJob->m_spRefGeometry = mitk::ImageMappingHelper::GenerateSuperSampledGeometry(pJob->m_spRefGeometry,
+ m_Controls.m_sbXFactor->value(),
+ m_Controls.m_sbYFactor->value(),
+ m_Controls.m_sbZFactor->value());
}
}
pJob->m_MappedName = m_Controls.m_leMappedName->text().toStdString();
pJob->m_allowUndefPixels = m_Controls.m_groupAllowUndefPixels->isChecked();
pJob->m_paddingValue = m_Controls.m_sbPaddingValue->value();
pJob->m_allowUnregPixels = m_Controls.m_groupAllowUnregPixels->isChecked();
pJob->m_errorValue = m_Controls.m_sbErrorValue->value();
pJob->m_InterpolatorLabel = m_Controls.m_comboInterpolator->currentText().toStdString();
switch (m_Controls.m_comboInterpolator->currentIndex())
{
case 0:
pJob->m_InterpolatorType = mitk::ImageMappingInterpolator::NearestNeighbor;
break;
case 1:
pJob->m_InterpolatorType = mitk::ImageMappingInterpolator::Linear;
break;
case 2:
pJob->m_InterpolatorType = mitk::ImageMappingInterpolator::BSpline_3;
break;
case 3:
pJob->m_InterpolatorType = mitk::ImageMappingInterpolator::WSinc_Hamming;
break;
case 4:
pJob->m_InterpolatorType = mitk::ImageMappingInterpolator::WSinc_Welch;
break;
}
connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnMapJobError(QString)));
connect(pJob, SIGNAL(MapResultIsAvailable(mitk::BaseData::Pointer, const QmitkMappingJob*)), this,
SLOT(OnMapResultIsAvailable(mitk::BaseData::Pointer, const QmitkMappingJob*)),
Qt::BlockingQueuedConnection);
connect(pJob, SIGNAL(AlgorithmInfo(QString)), this, SLOT(OnMappingInfo(QString)));
m_Controls.m_teLog->append(QStringLiteral("<b><font color='blue'>Started mapping job. Name: ") +
m_Controls.m_leMappedName->text() + QStringLiteral("</font></b>"));
QThreadPool* threadPool = QThreadPool::globalInstance();
threadPool->start(pJob);
}
void QmitkMatchPointMapper::OnMapJobError(QString err)
{
Error(err);
}
void QmitkMatchPointMapper::OnMapResultIsAvailable(mitk::BaseData::Pointer spMappedData,
const QmitkMappingJob* job)
{
m_Controls.m_teLog->append(QStringLiteral("<b><font color='blue'>Mapped entity stored. Name: ") +
QString::fromStdString(job->m_MappedName) + QStringLiteral("</font></b>"));
mitk::DataNode::Pointer spMappedNode = mitk::generateMappedResultNode(job->m_MappedName,
spMappedData, job->GetRegistration()->getRegistrationUID(), job->m_InputDataUID,
job->m_doGeometryRefinement, job->m_InterpolatorLabel);
this->GetDataStorage()->Add(spMappedNode);
auto* renderWindowPart = this->GetRenderWindowPart();
if (nullptr != renderWindowPart)
renderWindowPart->RequestUpdate();
this->CheckInputs();
this->ConfigureMappingControls();
}
void QmitkMatchPointMapper::OnMappingInfo(QString info)
{
m_Controls.m_teLog->append(QStringLiteral("<font color='gray'><i>") + info + QStringLiteral("</i></font>"));
}
void QmitkMatchPointMapper::OnXFactorChanged(double d)
{
if (m_Controls.m_cbLinkFactors->isChecked())
{
this->m_Controls.m_sbYFactor->setValue(d);
this->m_Controls.m_sbZFactor->setValue(d);
}
}
diff --git a/Plugins/org.mitk.gui.qt.mitkworkbench.intro/src/internal/QmitkMitkWorkbenchIntroPlugin.cpp b/Plugins/org.mitk.gui.qt.mitkworkbench.intro/src/internal/QmitkMitkWorkbenchIntroPlugin.cpp
index f78e96fb19..3cd9c4737c 100644
--- a/Plugins/org.mitk.gui.qt.mitkworkbench.intro/src/internal/QmitkMitkWorkbenchIntroPlugin.cpp
+++ b/Plugins/org.mitk.gui.qt.mitkworkbench.intro/src/internal/QmitkMitkWorkbenchIntroPlugin.cpp
@@ -1,59 +1,59 @@
/*============================================================================
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 "QmitkMitkWorkbenchIntroPlugin.h"
#include "QmitkMitkWorkbenchIntroPart.h"
#include "QmitkMitkWorkbenchIntroPreferencePage.h"
#include <mitkVersion.h>
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
#include <service/cm/ctkConfigurationAdmin.h>
#include <service/cm/ctkConfiguration.h>
#include <QFileInfo>
#include <QDateTime>
#include <usModuleInitialization.h>
US_INITIALIZE_MODULE
QmitkMitkWorkbenchIntroPlugin* QmitkMitkWorkbenchIntroPlugin::inst = nullptr;
QmitkMitkWorkbenchIntroPlugin::QmitkMitkWorkbenchIntroPlugin()
{
inst = this;
}
QmitkMitkWorkbenchIntroPlugin::~QmitkMitkWorkbenchIntroPlugin()
{
}
QmitkMitkWorkbenchIntroPlugin* QmitkMitkWorkbenchIntroPlugin::GetDefault()
{
return inst;
}
void QmitkMitkWorkbenchIntroPlugin::start(ctkPluginContext* context)
{
berry::AbstractUICTKPlugin::start(context);
this->context = context;
BERRY_REGISTER_EXTENSION_CLASS(QmitkMitkWorkbenchIntroPart, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkMitkWorkbenchIntroPreferencePage, context)
}
ctkPluginContext* QmitkMitkWorkbenchIntroPlugin::GetPluginContext() const
{
return context;
}
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.cpp
index 4b97be0319..55d3bc0f52 100644
--- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.cpp
+++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkMovieMakerView.cpp
@@ -1,698 +1,705 @@
/*============================================================================
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 "QmitkMovieMakerView.h"
#include <ui_QmitkMovieMakerView.h>
#include "QmitkAnimationItemDelegate.h"
#include "QmitkOrbitAnimationItem.h"
#include "QmitkOrbitAnimationWidget.h"
#include "QmitkSliceAnimationItem.h"
#include "QmitkSliceAnimationWidget.h"
#include "QmitkTimeSliceAnimationItem.h"
#include "QmitkTimeSliceAnimationWidget.h"
#include <mitkVideoRecorder.h>
#include <QFileDialog>
#include <QMenu>
#include <QMessageBox>
#include <QThread>
#include <QTimer>
#include <array>
namespace
{
QmitkAnimationItem* CreateDefaultAnimation(const QString& widgetKey)
{
if (widgetKey == "Orbit")
return new QmitkOrbitAnimationItem;
if (widgetKey == "Slice")
return new QmitkSliceAnimationItem;
if (widgetKey == "Time")
return new QmitkTimeSliceAnimationItem;
return nullptr;
}
class EncodingThread : public QThread
{
public:
EncodingThread(mitk::VideoRecorder* videoRecorder, QObject* parent = nullptr)
: QThread(parent),
m_VideoRecorder(videoRecorder)
{
}
~EncodingThread() override = default;
private:
void run() override
{
- m_VideoRecorder->StopRecording();
+ try
+ {
+ m_VideoRecorder->StopRecording();
+ }
+ catch (const mitk::Exception& e)
+ {
+ MITK_ERROR << e.GetDescription();
+ }
}
mitk::VideoRecorder* m_VideoRecorder;
};
}
const std::string QmitkMovieMakerView::VIEW_ID = "org.mitk.views.moviemaker";
QmitkMovieMakerView::QmitkMovieMakerView()
: m_Parent(nullptr),
m_Ui(new Ui::QmitkMovieMakerView),
m_AnimationModel(nullptr),
m_AddAnimationMenu(nullptr),
m_RecordMenu(nullptr),
m_Timer(nullptr),
m_TotalDuration(0.0),
m_NumFrames(0),
m_CurrentFrame(0)
{
}
QmitkMovieMakerView::~QmitkMovieMakerView()
{
}
void QmitkMovieMakerView::CreateQtPartControl(QWidget* parent)
{
m_Parent = parent;
m_Ui->setupUi(parent);
this->InitializeAnimationWidgets();
this->InitializeAnimationTreeViewWidgets();
this->InitializePlaybackAndRecordWidgets();
this->InitializeTimer(parent);
m_Ui->animationWidgetGroupBox->setVisible(false);
}
void QmitkMovieMakerView::InitializeAnimationWidgets()
{
m_AnimationWidgets["Orbit"] = new QmitkOrbitAnimationWidget;
m_AnimationWidgets["Slice"] = new QmitkSliceAnimationWidget;
m_AnimationWidgets["Time"] = new QmitkTimeSliceAnimationWidget;
for (const auto& widget : m_AnimationWidgets)
{
if (nullptr != widget.second)
{
widget.second->setVisible(false);
m_Ui->animationWidgetGroupBoxLayout->addWidget(widget.second);
}
}
this->ConnectAnimationWidgets();
}
void QmitkMovieMakerView::InitializeAnimationTreeViewWidgets()
{
this->InitializeAnimationModel();
this->InitializeAddAnimationMenu();
this->ConnectAnimationTreeViewWidgets();
}
void QmitkMovieMakerView::InitializePlaybackAndRecordWidgets()
{
this->InitializeRecordMenu();
this->ConnectPlaybackAndRecordWidgets();
this->InitializeRecordingProgress();
}
void QmitkMovieMakerView::InitializeAnimationModel()
{
m_AnimationModel = new QStandardItemModel(m_Ui->animationTreeView);
m_AnimationModel->setHorizontalHeaderLabels(QStringList() << "Animation" << "Timeline");
m_Ui->animationTreeView->setModel(m_AnimationModel);
m_Ui->animationTreeView->setItemDelegate(new QmitkAnimationItemDelegate(m_Ui->animationTreeView));
}
void QmitkMovieMakerView::InitializeAddAnimationMenu()
{
m_AddAnimationMenu = new QMenu(m_Ui->addAnimationButton);
for(const auto& widget : m_AnimationWidgets)
m_AddAnimationMenu->addAction(widget.first);
}
void QmitkMovieMakerView::InitializeRecordMenu()
{
std::array<std::pair<QString, QString>, 4> renderWindows = {
std::make_pair(QStringLiteral("Axial"), QStringLiteral("stdmulti.widget0")),
std::make_pair(QStringLiteral("Sagittal"), QStringLiteral("stdmulti.widget1")),
std::make_pair(QStringLiteral("Coronal"), QStringLiteral("stdmulti.widget2")),
std::make_pair(QStringLiteral("3D"), QStringLiteral("stdmulti.widget3"))
};
m_RecordMenu = new QMenu(m_Ui->recordButton);
for(const auto& renderWindow : renderWindows)
{
auto* action = new QAction(m_RecordMenu);
action->setText(renderWindow.first);
action->setData(renderWindow.second);
m_RecordMenu->addAction(action);
}
}
void QmitkMovieMakerView::InitializeRecordingProgress()
{
m_Ui->recordingLabel->setEnabled(true);
m_Ui->recordingLabel->setVisible(false);
m_Ui->recordingProgressBar->setEnabled(true);
m_Ui->recordingProgressBar->setValue(0);
m_Ui->recordingProgressBar->setVisible(false);
m_Ui->encodingLabel->setEnabled(false);
m_Ui->encodingLabel->setVisible(false);
m_Ui->encodingProgressBar->setEnabled(false);
m_Ui->encodingProgressBar->setMaximum(1);
m_Ui->encodingProgressBar->setVisible(false);
}
void QmitkMovieMakerView::InitializeTimer(QWidget* parent)
{
m_Timer = new QTimer(parent);
this->OnFPSSpinBoxValueChanged(m_Ui->fpsSpinBox->value());
this->ConnectTimer();
}
void QmitkMovieMakerView::ConnectAnimationTreeViewWidgets()
{
connect(m_AnimationModel, &QStandardItemModel::rowsInserted, this, &QmitkMovieMakerView::OnAnimationTreeViewRowsInserted);
connect(m_AnimationModel, &QStandardItemModel::rowsRemoved, this, &QmitkMovieMakerView::OnAnimationTreeViewRowsRemoved);
connect(m_Ui->animationTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QmitkMovieMakerView::OnAnimationTreeViewSelectionChanged);
connect(m_Ui->moveAnimationUpButton, &QToolButton::clicked, this, &QmitkMovieMakerView::OnMoveAnimationUpButtonClicked);
connect(m_Ui->moveAnimationDownButton, &QToolButton::clicked, this, &QmitkMovieMakerView::OnMoveAnimationDownButtonClicked);
connect(m_Ui->addAnimationButton, &QToolButton::clicked, this, &QmitkMovieMakerView::OnAddAnimationButtonClicked);
connect(m_Ui->removeAnimationButton, &QToolButton::clicked, this, &QmitkMovieMakerView::OnRemoveAnimationButtonClicked);
}
void QmitkMovieMakerView::ConnectAnimationWidgets()
{
connect(m_Ui->startComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnStartComboBoxCurrentIndexChanged(int)));
connect(m_Ui->durationSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnDurationSpinBoxValueChanged(double)));
connect(m_Ui->delaySpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnDelaySpinBoxValueChanged(double)));
}
void QmitkMovieMakerView::ConnectPlaybackAndRecordWidgets()
{
connect(m_Ui->playButton, &QToolButton::toggled, this, &QmitkMovieMakerView::OnPlayButtonToggled);
connect(m_Ui->stopButton, &QToolButton::clicked, this, &QmitkMovieMakerView::OnStopButtonClicked);
connect(m_Ui->recordButton, &QToolButton::clicked, this, &QmitkMovieMakerView::OnRecordButtonClicked);
connect(m_Ui->fpsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnFPSSpinBoxValueChanged(int)));
}
void QmitkMovieMakerView::ConnectTimer()
{
connect(m_Timer, &QTimer::timeout, this, &QmitkMovieMakerView::OnTimerTimeout);
}
void QmitkMovieMakerView::SetFocus()
{
m_Ui->addAnimationButton->setFocus();
}
void QmitkMovieMakerView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
auto multiWidgetEditor = dynamic_cast<berry::Object*>(renderWindowPart);
bool isMxN = nullptr != multiWidgetEditor && multiWidgetEditor->GetClassName() == "QmitkMxNMultiWidgetEditor";
m_Parent->setDisabled(isMxN);
}
void QmitkMovieMakerView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/)
{
}
void QmitkMovieMakerView::RenderWindowPartInputChanged(mitk::IRenderWindowPart* /*renderWindowPart*/)
{
}
void QmitkMovieMakerView::OnMoveAnimationUpButtonClicked()
{
const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection();
if (!selection.isEmpty())
{
const int selectedRow = selection[0].top();
if (selectedRow > 0)
m_AnimationModel->insertRow(selectedRow - 1, m_AnimationModel->takeRow(selectedRow));
}
this->CalculateTotalDuration();
}
void QmitkMovieMakerView::OnMoveAnimationDownButtonClicked()
{
const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection();
if (!selection.isEmpty())
{
const int rowCount = m_AnimationModel->rowCount();
const int selectedRow = selection[0].top();
if (selectedRow < rowCount - 1)
m_AnimationModel->insertRow(selectedRow + 1, m_AnimationModel->takeRow(selectedRow));
}
this->CalculateTotalDuration();
}
void QmitkMovieMakerView::OnAddAnimationButtonClicked()
{
auto action = m_AddAnimationMenu->exec(QCursor::pos());
if (nullptr != action)
{
const auto key = action->text();
m_AnimationModel->appendRow(QList<QStandardItem*>()
<< new QStandardItem(key)
<< CreateDefaultAnimation(key));
m_Ui->playbackAndRecordingGroupBox->setEnabled(true);
}
}
void QmitkMovieMakerView::OnPlayButtonToggled(bool checked)
{
if (checked)
{
m_Ui->playButton->setIcon(QIcon(":/org_mitk_icons/icons/tango/scalable/actions/media-playback-pause.svg"));
m_Ui->playButton->repaint();
m_Timer->start(static_cast<int>(1000.0 / m_Ui->fpsSpinBox->value()));
}
else
{
m_Timer->stop();
m_Ui->playButton->setIcon(QIcon(":/org_mitk_icons/icons/tango/scalable/actions/media-playback-start.svg"));
m_Ui->playButton->repaint();
}
}
void QmitkMovieMakerView::OnStopButtonClicked()
{
m_Ui->playButton->setChecked(false);
m_Ui->stopButton->setEnabled(false);
m_CurrentFrame = 0;
this->RenderCurrentFrame();
}
void QmitkMovieMakerView::OnRecordButtonClicked()
{
if (0 == m_NumFrames || 0.0 == m_TotalDuration)
return;
m_VideoRecorder = std::make_unique<mitk::VideoRecorder>();
if (m_VideoRecorder->GetFFmpegPath().empty())
{
QMessageBox::information(nullptr, "Movie Maker",
"<p>Set path to FFmpeg (<a href=\"https://ffmpeg.org\">ffmpeg.org</a>) in preferences "
"(Window -> Preferences... (Ctrl+P) -> Movie Maker) to be able to record your "
"movies to video files.</p>");
return;
}
auto action = m_RecordMenu->exec(QCursor::pos());
if (nullptr == action)
return;
m_VideoRecorder->SetRenderWindowName(action->data().toString().toStdString());
m_VideoRecorder->SetFrameRate(static_cast<unsigned int>(m_Ui->fpsSpinBox->value()));
auto fileExt = QString::fromStdString(mitk::VideoRecorder::GetFileExtension(m_VideoRecorder->GetOutputFormat()));
QString outputPath = QFileDialog::getSaveFileName(nullptr, "Specify a filename", "", "Movie (*" + fileExt + ")");
if (outputPath.isEmpty())
return;
if(!outputPath.endsWith(fileExt))
outputPath += fileExt;
m_VideoRecorder->SetOutputPath(outputPath.toStdString());
m_Ui->recordButton->setEnabled(false);
m_Ui->recordingProgressBar->setMaximum(m_NumFrames);
m_Ui->recordingLabel->setVisible(true);
m_Ui->recordingProgressBar->setVisible(true);
m_Ui->encodingLabel->setVisible(true);
m_Ui->encodingProgressBar->setVisible(true);
EncodingThread* encodingThread = new EncodingThread(m_VideoRecorder.get(), m_Parent);
connect(encodingThread, &EncodingThread::finished, this, &QmitkMovieMakerView::OnEncodingFinished);
try
{
m_VideoRecorder->StartRecording();
for (m_CurrentFrame = 0; m_CurrentFrame < m_NumFrames; ++m_CurrentFrame)
{
m_Ui->recordingProgressBar->setValue(m_CurrentFrame + 1);
this->RenderCurrentFrame();
m_VideoRecorder->RecordFrame();
}
m_Ui->encodingProgressBar->setMaximum(0);
m_Ui->encodingLabel->setEnabled(true);
m_Ui->encodingProgressBar->setEnabled(true);
encodingThread->start();
}
catch (const mitk::Exception& exception)
{
if (encodingThread->isRunning())
encodingThread->terminate();
QMessageBox::critical(nullptr, "Movie Maker", exception.GetDescription());
m_VideoRecorder = nullptr;
this->OnEncodingFinished();
}
}
void QmitkMovieMakerView::OnEncodingFinished()
{
m_VideoRecorder = nullptr;
this->InitializeRecordingProgress();
m_CurrentFrame = 0;
this->RenderCurrentFrame();
m_Ui->recordButton->setEnabled(true);
}
void QmitkMovieMakerView::OnRemoveAnimationButtonClicked()
{
const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection();
if (!selection.isEmpty())
m_AnimationModel->removeRow(selection[0].top());
}
void QmitkMovieMakerView::OnAnimationTreeViewRowsInserted(const QModelIndex& parent, int start, int)
{
this->CalculateTotalDuration();
m_Ui->animationTreeView->selectionModel()->select(
m_AnimationModel->index(start, 0, parent),
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
}
void QmitkMovieMakerView::OnAnimationTreeViewRowsRemoved(const QModelIndex&, int, int)
{
this->CalculateTotalDuration();
this->UpdateWidgets();
}
void QmitkMovieMakerView::OnAnimationTreeViewSelectionChanged(const QItemSelection&, const QItemSelection&)
{
this->UpdateWidgets();
}
void QmitkMovieMakerView::OnStartComboBoxCurrentIndexChanged(int index)
{
QmitkAnimationItem* item = this->GetSelectedAnimationItem();
if (item != nullptr)
{
item->SetStartWithPrevious(index);
this->RedrawTimeline();
this->CalculateTotalDuration();
}
}
void QmitkMovieMakerView::OnDurationSpinBoxValueChanged(double value)
{
QmitkAnimationItem* item = this->GetSelectedAnimationItem();
if (item != nullptr)
{
item->SetDuration(value);
this->RedrawTimeline();
this->CalculateTotalDuration();
}
}
void QmitkMovieMakerView::OnDelaySpinBoxValueChanged(double value)
{
QmitkAnimationItem* item = this->GetSelectedAnimationItem();
if (item != nullptr)
{
item->SetDelay(value);
this->RedrawTimeline();
this->CalculateTotalDuration();
}
}
void QmitkMovieMakerView::OnFPSSpinBoxValueChanged(int value)
{
this->CalculateTotalDuration();
m_Timer->setInterval(static_cast<int>(1000.0 / value));
}
void QmitkMovieMakerView::OnTimerTimeout()
{
this->RenderCurrentFrame();
m_CurrentFrame = std::min(m_NumFrames, m_CurrentFrame + 1);
if (m_CurrentFrame >= m_NumFrames)
{
m_Ui->playButton->setChecked(false);
m_CurrentFrame = 0;
this->RenderCurrentFrame();
}
m_Ui->stopButton->setEnabled(m_CurrentFrame != 0);
}
void QmitkMovieMakerView::RenderCurrentFrame()
{
const double deltaT = m_TotalDuration / (m_NumFrames - 1);
const auto activeAnimations = this->GetActiveAnimations(m_CurrentFrame * deltaT);
for (const auto& animation : activeAnimations)
{
const auto nextActiveAnimations = this->GetActiveAnimations((m_CurrentFrame + 1) * deltaT);
bool lastFrameForAnimation = true;
for (const auto& nextAnimation : nextActiveAnimations)
{
if (nextAnimation.first == animation.first)
{
lastFrameForAnimation = false;
break;
}
}
animation.first->Animate(!lastFrameForAnimation
? animation.second
: 1.0);
}
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
void QmitkMovieMakerView::UpdateWidgets()
{
const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection();
if (selection.isEmpty())
{
m_Ui->moveAnimationUpButton->setEnabled(false);
m_Ui->moveAnimationDownButton->setEnabled(false);
m_Ui->removeAnimationButton->setEnabled(false);
m_Ui->playbackAndRecordingGroupBox->setEnabled(false);
this->HideCurrentAnimationWidget();
}
else
{
const int rowCount = m_AnimationModel->rowCount();
const int selectedRow = selection[0].top();
m_Ui->moveAnimationUpButton->setEnabled(rowCount > 1 && selectedRow != 0);
m_Ui->moveAnimationDownButton->setEnabled(rowCount > 1 && selectedRow < rowCount - 1);
m_Ui->removeAnimationButton->setEnabled(true);
m_Ui->playbackAndRecordingGroupBox->setEnabled(true);
this->ShowAnimationWidget(dynamic_cast<QmitkAnimationItem*>(m_AnimationModel->item(selectedRow, 1)));
}
this->UpdateAnimationWidgets();
}
void QmitkMovieMakerView::UpdateAnimationWidgets()
{
QmitkAnimationItem* item = this->GetSelectedAnimationItem();
if (item != nullptr)
{
m_Ui->startComboBox->setCurrentIndex(item->GetStartWithPrevious());
m_Ui->durationSpinBox->setValue(item->GetDuration());
m_Ui->delaySpinBox->setValue(item->GetDelay());
m_Ui->animationGroupBox->setEnabled(true);
}
else
{
m_Ui->animationGroupBox->setEnabled(false);
}
}
void QmitkMovieMakerView::HideCurrentAnimationWidget()
{
if (m_Ui->animationWidgetGroupBox->isVisible())
{
m_Ui->animationWidgetGroupBox->setVisible(false);
int numWidgets = m_Ui->animationWidgetGroupBoxLayout->count();
for (int i = 0; i < numWidgets; ++i)
m_Ui->animationWidgetGroupBoxLayout->itemAt(i)->widget()->setVisible(false);
}
}
void QmitkMovieMakerView::ShowAnimationWidget(QmitkAnimationItem* animationItem)
{
this->HideCurrentAnimationWidget();
if (animationItem == nullptr)
return;
const QString widgetKey = animationItem->GetWidgetKey();
auto animationWidgetIter = m_AnimationWidgets.find(widgetKey);
auto animationWidget = m_AnimationWidgets.end() != animationWidgetIter
? animationWidgetIter->second
: nullptr;
if (nullptr != animationWidget)
{
m_Ui->animationWidgetGroupBox->setTitle(widgetKey);
animationWidget->SetAnimationItem(animationItem);
animationWidget->setVisible(true);
}
m_Ui->animationWidgetGroupBox->setVisible(animationWidget != nullptr);
}
void QmitkMovieMakerView::RedrawTimeline()
{
if (m_AnimationModel->rowCount() > 1)
{
m_Ui->animationTreeView->dataChanged(
m_AnimationModel->index(0, 1),
m_AnimationModel->index(m_AnimationModel->rowCount() - 1, 1));
}
}
QmitkAnimationItem* QmitkMovieMakerView::GetSelectedAnimationItem() const
{
const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection();
return !selection.isEmpty()
? dynamic_cast<QmitkAnimationItem*>(m_AnimationModel->item(selection[0].top(), 1))
: nullptr;
}
void QmitkMovieMakerView::CalculateTotalDuration()
{
const int rowCount = m_AnimationModel->rowCount();
double totalDuration = 0.0;
double previousStart = 0.0;
for (int i = 0; i < rowCount; ++i)
{
auto item = dynamic_cast<QmitkAnimationItem*>(m_AnimationModel->item(i, 1));
if (nullptr == item)
continue;
if (item->GetStartWithPrevious())
{
totalDuration = std::max(totalDuration, previousStart + item->GetDelay() + item->GetDuration());
}
else
{
previousStart = totalDuration;
totalDuration += item->GetDelay() + item->GetDuration();
}
}
m_TotalDuration = totalDuration;
m_NumFrames = static_cast<int>(totalDuration * m_Ui->fpsSpinBox->value());
}
std::vector<std::pair<QmitkAnimationItem*, double>> QmitkMovieMakerView::GetActiveAnimations(double t) const
{
const int rowCount = m_AnimationModel->rowCount();
std::vector<std::pair<QmitkAnimationItem*, double>> activeAnimations;
double totalDuration = 0.0;
double previousStart = 0.0;
for (int i = 0; i < rowCount; ++i)
{
QmitkAnimationItem* item = dynamic_cast<QmitkAnimationItem*>(m_AnimationModel->item(i, 1));
if (item == nullptr)
continue;
if (item->GetDuration() > 0.0)
{
double start = item->GetStartWithPrevious()
? previousStart + item->GetDelay()
: totalDuration + item->GetDelay();
if (start <= t && t <= start + item->GetDuration())
activeAnimations.emplace_back(item, (t - start) / item->GetDuration());
}
if (item->GetStartWithPrevious())
{
totalDuration = std::max(totalDuration, previousStart + item->GetDelay() + item->GetDuration());
}
else
{
previousStart = totalDuration;
totalDuration += item->GetDelay() + item->GetDuration();
}
}
return activeAnimations;
}
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.cpp
index d920eaec5d..654f2696b1 100644
--- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.cpp
+++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkOrbitAnimationItem.cpp
@@ -1,70 +1,70 @@
/*============================================================================
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 "QmitkOrbitAnimationItem.h"
#include <mitkBaseRenderer.h>
QmitkOrbitAnimationItem::QmitkOrbitAnimationItem(int orbit, bool reverse, double duration, double delay, bool startWithPrevious)
: QmitkAnimationItem("Orbit", duration, delay, startWithPrevious)
{
this->SetOrbit(orbit);
this->SetReverse(reverse);
}
QmitkOrbitAnimationItem::~QmitkOrbitAnimationItem()
{
}
int QmitkOrbitAnimationItem::GetOrbit() const
{
return this->data(OrbitRole).toInt();
}
void QmitkOrbitAnimationItem::SetOrbit(int angle)
{
this->setData(angle, OrbitRole);
}
bool QmitkOrbitAnimationItem::GetReverse() const
{
return this->data(ReverseRole).toBool();
}
void QmitkOrbitAnimationItem::SetReverse(bool reverse)
{
this->setData(reverse, ReverseRole);
}
void QmitkOrbitAnimationItem::Animate(double s)
{
vtkRenderWindow* renderWindow = mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3");
if (renderWindow == nullptr)
return;
- mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(renderWindow)->GetCameraRotationController()->GetSlice();
+ mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(renderWindow)->GetCameraRotationController()->GetStepper();
if (stepper == nullptr)
return;
int newPos = this->GetReverse()
? 180 - this->GetOrbit() * s
: 180 + this->GetOrbit() * s;
while (newPos < 0)
newPos += 360;
while (newPos > 360)
newPos -= 360;
stepper->SetPos(static_cast<unsigned int>(newPos));
}
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.cpp
index c7135fcea9..23fd4aabb9 100644
--- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.cpp
+++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationItem.cpp
@@ -1,87 +1,87 @@
/*============================================================================
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 "QmitkSliceAnimationItem.h"
#include <mitkBaseRenderer.h>
QmitkSliceAnimationItem::QmitkSliceAnimationItem(int renderWindow, int from, int to, bool reverse, double duration, double delay, bool startWithPrevious)
: QmitkAnimationItem("Slice", duration, delay, startWithPrevious)
{
this->SetRenderWindow(renderWindow);
this->SetFrom(from);
this->SetTo(to);
this->SetReverse(reverse);
}
QmitkSliceAnimationItem::~QmitkSliceAnimationItem()
{
}
int QmitkSliceAnimationItem::GetRenderWindow() const
{
return this->data(RenderWindowRole).toInt();
}
void QmitkSliceAnimationItem::SetRenderWindow(int renderWindow)
{
this->setData(renderWindow, RenderWindowRole);
}
int QmitkSliceAnimationItem::GetFrom() const
{
return this->data(FromRole).toInt();
}
void QmitkSliceAnimationItem::SetFrom(int from)
{
this->setData(from, FromRole);
}
int QmitkSliceAnimationItem::GetTo() const
{
return this->data(ToRole).toInt();
}
void QmitkSliceAnimationItem::SetTo(int to)
{
this->setData(to, ToRole);
}
bool QmitkSliceAnimationItem::GetReverse() const
{
return this->data(ReverseRole).toBool();
}
void QmitkSliceAnimationItem::SetReverse(bool reverse)
{
this->setData(reverse, ReverseRole);
}
void QmitkSliceAnimationItem::Animate(double s)
{
const QString renderWindowName = QString("stdmulti.widget%1").arg(this->GetRenderWindow());
vtkRenderWindow* renderWindow = mitk::BaseRenderer::GetRenderWindowByName(renderWindowName.toStdString());
if (renderWindow == nullptr)
return;
- mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(renderWindow)->GetSliceNavigationController()->GetSlice();
+ mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(renderWindow)->GetSliceNavigationController()->GetStepper();
if (stepper == nullptr)
return;
int newPos = this->GetReverse()
? this->GetTo() - static_cast<int>((this->GetTo() - this->GetFrom()) * s)
: this->GetFrom() + static_cast<int>((this->GetTo() - this->GetFrom()) * s);
stepper->SetPos(static_cast<unsigned int>(newPos));
}
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.cpp
index bca0c6de77..49b5dcfc94 100644
--- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkSliceAnimationWidget.cpp
@@ -1,127 +1,127 @@
/*============================================================================
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 "QmitkSliceAnimationItem.h"
#include "QmitkSliceAnimationWidget.h"
#include <mitkBaseRenderer.h>
#include <ui_QmitkSliceAnimationWidget.h>
namespace
{
int GetNumberOfSlices(int renderWindow)
{
const QString renderWindowName = QString("stdmulti.widget%1").arg(renderWindow);
vtkRenderWindow* theRenderWindow = mitk::BaseRenderer::GetRenderWindowByName(renderWindowName.toStdString());
if (theRenderWindow != nullptr)
{
- mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(theRenderWindow)->GetSliceNavigationController()->GetSlice();
+ mitk::Stepper* stepper = mitk::BaseRenderer::GetInstance(theRenderWindow)->GetSliceNavigationController()->GetStepper();
if (stepper != nullptr)
return std::max(1, static_cast<int>(stepper->GetSteps()));
}
return 1;
}
}
QmitkSliceAnimationWidget::QmitkSliceAnimationWidget(QWidget* parent)
: QmitkAnimationWidget(parent),
m_Ui(new Ui::QmitkSliceAnimationWidget),
m_AnimationItem(nullptr)
{
m_Ui->setupUi(this);
connect(m_Ui->windowComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnRenderWindowChanged(int)));
connect(m_Ui->sliceRangeWidget, SIGNAL(minimumValueChanged(double)), this, SLOT(OnFromChanged(double)));
connect(m_Ui->sliceRangeWidget, SIGNAL(maximumValueChanged(double)), this, SLOT(OnToChanged(double)));
connect(m_Ui->reverseCheckBox, SIGNAL(clicked(bool)), this, SLOT(OnReverseChanged(bool)));
}
QmitkSliceAnimationWidget::~QmitkSliceAnimationWidget()
{
}
void QmitkSliceAnimationWidget::SetAnimationItem(QmitkAnimationItem* sliceAnimationItem)
{
m_AnimationItem = dynamic_cast<QmitkSliceAnimationItem*>(sliceAnimationItem);
if (nullptr == m_AnimationItem)
return;
m_Ui->windowComboBox->setCurrentIndex(m_AnimationItem->GetRenderWindow());
const int maximum = GetNumberOfSlices(m_AnimationItem->GetRenderWindow()) - 1;
const int from = std::min(m_AnimationItem->GetFrom(), maximum);
int to = std::max(from, std::min(m_AnimationItem->GetTo(), maximum));
if (0 == to)
to = maximum;
m_AnimationItem->SetFrom(from);
m_AnimationItem->SetTo(to);
m_Ui->sliceRangeWidget->setMaximum(maximum);
m_Ui->sliceRangeWidget->setValues(from, to);
m_Ui->reverseCheckBox->setChecked(m_AnimationItem->GetReverse());
}
void QmitkSliceAnimationWidget::OnRenderWindowChanged(int renderWindow)
{
if (nullptr == m_AnimationItem)
return;
const int lastSlice = static_cast<int>(GetNumberOfSlices(renderWindow) - 1);
if (lastSlice < m_AnimationItem->GetFrom())
m_AnimationItem->SetFrom(lastSlice);
if (lastSlice < m_AnimationItem->GetTo())
m_AnimationItem->SetTo(lastSlice);
m_Ui->sliceRangeWidget->setMaximum(lastSlice);
m_Ui->sliceRangeWidget->setValues(m_AnimationItem->GetFrom(), m_AnimationItem->GetTo());
if (m_AnimationItem->GetRenderWindow() != renderWindow)
m_AnimationItem->SetRenderWindow(renderWindow);
}
void QmitkSliceAnimationWidget::OnFromChanged(double from)
{
if (nullptr == m_AnimationItem)
return;
int intFrom = static_cast<int>(from);
if (m_AnimationItem->GetFrom() != intFrom)
m_AnimationItem->SetFrom(intFrom);
}
void QmitkSliceAnimationWidget::OnToChanged(double to)
{
if (nullptr == m_AnimationItem)
return;
int intTo = static_cast<int>(to);
if (m_AnimationItem->GetTo() != intTo)
m_AnimationItem->SetTo(intTo);
}
void QmitkSliceAnimationWidget::OnReverseChanged(bool reverse)
{
if (nullptr == m_AnimationItem)
return;
if (m_AnimationItem->GetReverse() != reverse)
m_AnimationItem->SetReverse(reverse);
}
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationItem.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationItem.cpp
index c2a4e7d339..eaff2baba6 100644
--- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationItem.cpp
+++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationItem.cpp
@@ -1,70 +1,72 @@
/*============================================================================
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 "QmitkTimeSliceAnimationItem.h"
-#include <mitkBaseRenderer.h>
+
+#include <mitkRenderingManager.h>
+#include <mitkTimeNavigationController.h>
QmitkTimeSliceAnimationItem::QmitkTimeSliceAnimationItem(int from, int to, bool reverse, double duration, double delay, bool startWithPrevious)
: QmitkAnimationItem("Time", duration, delay, startWithPrevious)
{
this->SetFrom(from);
this->SetTo(to);
this->SetReverse(reverse);
}
QmitkTimeSliceAnimationItem::~QmitkTimeSliceAnimationItem()
{
}
int QmitkTimeSliceAnimationItem::GetFrom() const
{
return this->data(FromRole).toInt();
}
void QmitkTimeSliceAnimationItem::SetFrom(int from)
{
this->setData(from, FromRole);
}
int QmitkTimeSliceAnimationItem::GetTo() const
{
return this->data(ToRole).toInt();
}
void QmitkTimeSliceAnimationItem::SetTo(int to)
{
this->setData(to, ToRole);
}
bool QmitkTimeSliceAnimationItem::GetReverse() const
{
return this->data(ReverseRole).toBool();
}
void QmitkTimeSliceAnimationItem::SetReverse(bool reverse)
{
this->setData(reverse, ReverseRole);
}
void QmitkTimeSliceAnimationItem::Animate(double s)
{
- mitk::Stepper* stepper = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime();
+ mitk::Stepper* stepper = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetStepper();
if (stepper == nullptr)
return;
int newPos = this->GetReverse()
? this->GetTo() - static_cast<int>((this->GetTo() - this->GetFrom()) * s)
: this->GetFrom() + static_cast<int>((this->GetTo() - this->GetFrom()) * s);
stepper->SetPos(static_cast<unsigned int>(newPos));
}
diff --git a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationWidget.cpp b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationWidget.cpp
index a5f2e52f7f..2a30581a37 100644
--- a/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.moviemaker/src/internal/QmitkTimeSliceAnimationWidget.cpp
@@ -1,99 +1,99 @@
/*============================================================================
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 "QmitkTimeSliceAnimationItem.h"
#include "QmitkTimeSliceAnimationWidget.h"
#include <mitkRenderingManager.h>
-#include <mitkSliceNavigationController.h>
+#include <mitkTimeNavigationController.h>
#include <mitkStepper.h>
#include <ui_QmitkTimeSliceAnimationWidget.h>
namespace
{
int GetNumberOfSlices()
{
- mitk::Stepper* stepper = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime();
+ mitk::Stepper* stepper = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetStepper();
if (stepper != nullptr)
return std::max(1, static_cast<int>(stepper->GetSteps()));
return 1;
}
}
QmitkTimeSliceAnimationWidget::QmitkTimeSliceAnimationWidget(QWidget* parent)
: QmitkAnimationWidget(parent),
m_Ui(new Ui::QmitkTimeSliceAnimationWidget)
{
m_Ui->setupUi(this);
connect(m_Ui->sliceRangeWidget, SIGNAL(minimumValueChanged(double)), this, SLOT(OnFromChanged(double)));
connect(m_Ui->sliceRangeWidget, SIGNAL(maximumValueChanged(double)), this, SLOT(OnToChanged(double)));
connect(m_Ui->reverseCheckBox, SIGNAL(clicked(bool)), this, SLOT(OnReverseChanged(bool)));
}
QmitkTimeSliceAnimationWidget::~QmitkTimeSliceAnimationWidget()
{
}
void QmitkTimeSliceAnimationWidget::SetAnimationItem(QmitkAnimationItem* sliceAnimationItem)
{
m_AnimationItem = dynamic_cast<QmitkTimeSliceAnimationItem*>(sliceAnimationItem);
if (nullptr == m_AnimationItem)
return;
const int maximum = GetNumberOfSlices() - 1;
const int from = std::min(m_AnimationItem->GetFrom(), maximum);
int to = std::max(from, std::min(m_AnimationItem->GetTo(), maximum));
if (0 == to)
to = maximum;
m_AnimationItem->SetFrom(from);
m_AnimationItem->SetTo(to);
m_Ui->sliceRangeWidget->setMaximum(maximum);
m_Ui->sliceRangeWidget->setValues(from, to);
m_Ui->reverseCheckBox->setChecked(m_AnimationItem->GetReverse());
}
void QmitkTimeSliceAnimationWidget::OnFromChanged(double from)
{
if (nullptr == m_AnimationItem)
return;
int intFrom = static_cast<int>(from);
if (m_AnimationItem->GetFrom() != intFrom)
m_AnimationItem->SetFrom(intFrom);
}
void QmitkTimeSliceAnimationWidget::OnToChanged(double to)
{
if (nullptr == m_AnimationItem)
return;
int intTo = static_cast<int>(to);
if (m_AnimationItem->GetTo() != intTo)
m_AnimationItem->SetTo(intTo);
}
void QmitkTimeSliceAnimationWidget::OnReverseChanged(bool reverse)
{
if (nullptr == m_AnimationItem)
return;
if (m_AnimationItem->GetReverse() != reverse)
m_AnimationItem->SetReverse(reverse);
}
diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox
index 1814f00b35..ab9068b411 100644
--- a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox
+++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox
@@ -1,27 +1,27 @@
/**
\page org_mitk_views_pharmacokinetics_curvedescriptor The Perfusion Curve Description Parameters View
\imageMacro{pharmacokinetics_curve_desc_doc.svg,"Icon of the Perfusion Curve Description Parameters View",3.0}
\tableofcontents
\section org_mitk_views_pharmacokinetics_curvedescriptor_overview Overview
In cases where data quality is not sufficient for dedicated pharmacokinetic analysis, or if global scouting of the overall image is performed to identify regions of interest, it is often advisable to use semi-quantitative measures that describe the general shape and type of the curve.
The Perfusion Curve Description Parameters View can be used to voxelwise calculate these parameters.
Currently the following parameters are offered by the tool (visualized in figure 1):
\imageMacro{pharmacokinetics_curve_desc_parameter_description.png,"Figure 1: Calculation of currently available descriptive parameters",3.0}
-- <i>area-under-the-curve (AUC)</i>: The area under the signal time curve is calculated by step-wise integration with linear interpolation between sampling points.
-- <i>area-under the first moment curve (AUMC)</i>: The area under the first moment signal time curve is calculated by step-wise integration with linear interpolation between sampling points.
+- <i>area-under-the-curve (AUC)</i>: The absolute area under the signal time curve is calculated by step-wise integration with linear interpolation between sampling points.
+- <i>area-under the first moment curve (AUMC)</i>: The absolute area under the first moment signal time curve is calculated by step-wise integration with linear interpolation between sampling points.
- <i>mean-residence-time (MRT)</i>: The mean residence time is calculated as MRT = AUMC/AUC.
- <i>time-to-peak</i>: The duration between the onset time and the time of the maximum signal of the curve.
- <i>maximum signal</i>: The overall maximum of all data points of the curve.
These parameters are usually calculated directly from the raw data signal intensities of the acquired MR image.
Alternatively, if semi-quantitative parameters should be calculated from concentration time curves, use the \ref org_mitk_views_pharmacokinetics_concentration_mri prior to the parameter calculation.
Parameters of interest can be selected from the list. Selecting a 4D image enables the <i>Calculate Parameters</i> button.
Resulting parameter maps will afterwards be added to the data manager as subnodes to the analyzed 4D image.
*/
diff --git a/Plugins/org.mitk.gui.qt.preprocessing.resampling/src/internal/QmitkPreprocessingResamplingView.cpp b/Plugins/org.mitk.gui.qt.preprocessing.resampling/src/internal/QmitkPreprocessingResamplingView.cpp
index 313a67c79c..8927b738ff 100644
--- a/Plugins/org.mitk.gui.qt.preprocessing.resampling/src/internal/QmitkPreprocessingResamplingView.cpp
+++ b/Plugins/org.mitk.gui.qt.preprocessing.resampling/src/internal/QmitkPreprocessingResamplingView.cpp
@@ -1,456 +1,453 @@
/*============================================================================
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 "QmitkPreprocessingResamplingView.h"
// QT includes (GUI)
#include <qlabel.h>
#include <qspinbox.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qradiobutton.h>
#include <qmessagebox.h>
// Berry includes (selection service)
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// MITK includes (GUI)
#include "QmitkDataNodeSelectionProvider.h"
#include "mitkDataNodeObject.h"
// MITK includes (general)
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateDimension.h"
#include "mitkNodePredicateAnd.h"
#include "mitkImageTimeSelector.h"
#include "mitkVectorImageMapper2D.h"
#include "mitkProperties.h"
#include "mitkLevelWindowProperty.h"
+#include <mitkTimeNavigationController.h>
// Includes for image casting between ITK and MITK
#include "mitkImageCast.h"
#include "mitkITKImageImport.h"
// ITK includes (general)
#include <itkVectorImage.h>
#include <itkImageFileWriter.h>
// Resampling
#include <itkResampleImageFilter.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkBSplineInterpolateImageFunction.h>
#include <itkCastImageFilter.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkShiftScaleImageFilter.h>
// STD
#include <cmath>
// Convenient Definitions
typedef itk::Image<double, 3> ImageType;
typedef itk::Image<unsigned char, 3> SegmentationImageType;
typedef itk::Image<double, 3> DoubleImageType;
typedef itk::Image<itk::Vector<float,3>, 3> VectorImageType;
typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType;
typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType2;
typedef itk::CastImageFilter< ImageType, DoubleImageType > ImagePTypeToFloatPTypeCasterType;
typedef itk::LinearInterpolateImageFunction< ImageType, double > LinearInterpolatorType;
typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestInterpolatorType;
typedef itk::BSplineInterpolateImageFunction<ImageType, double> BSplineInterpolatorType;
QmitkPreprocessingResampling::QmitkPreprocessingResampling()
: QmitkAbstractView(),
m_Controls(nullptr),
m_SelectedImageNode(nullptr),
m_TimeStepperAdapter(nullptr)
{
}
QmitkPreprocessingResampling::~QmitkPreprocessingResampling()
{
}
void QmitkPreprocessingResampling::CreateQtPartControl(QWidget *parent)
{
if (m_Controls == nullptr)
{
m_Controls = new Ui::QmitkPreprocessingResamplingViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3);
mitk::NodePredicateDataType::Pointer imagePredicate = mitk::NodePredicateDataType::New("Image");
}
m_SelectedImageNode = mitk::DataStorageSelection::New(this->GetDataStorage(), false);
// Setup Controls
this->m_Controls->cbParam4->clear();
this->m_Controls->cbParam4->insertItem(LINEAR, "Linear");
this->m_Controls->cbParam4->insertItem(NEAREST, "Nearest neighbor");
this->m_Controls->cbParam4->insertItem(SPLINE, "B-Spline");
}
void QmitkPreprocessingResampling::CreateConnections()
{
if ( m_Controls )
{
connect((QObject*)(m_Controls->btnDoIt), SIGNAL(clicked()), (QObject*) this, SLOT(StartButtonClicked()));
connect((QObject*)(m_Controls->buttonExecuteOnMultipleImages), SIGNAL(clicked()), (QObject*) this, SLOT(StartMultipleImagesButtonClicked()));
connect( (QObject*)(m_Controls->cbParam4), SIGNAL( activated(int) ), this, SLOT( SelectInterpolator(int) ) );
}
}
void QmitkPreprocessingResampling::InternalGetTimeNavigationController()
{
- auto renwin_part = GetRenderWindowPart();
- if( renwin_part != nullptr )
+ auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
+ if(nullptr != timeNavigationController)
{
- auto tnc = renwin_part->GetTimeNavigationController();
- if( tnc != nullptr )
- {
- m_TimeStepperAdapter = new QmitkStepperAdapter(m_Controls->timeSliceNavigationWidget, tnc->GetTime());
- }
+ m_TimeStepperAdapter = new QmitkStepperAdapter(m_Controls->timeSliceNavigationWidget, timeNavigationController->GetStepper());
}
}
void QmitkPreprocessingResampling::SetFocus()
{
}
//datamanager selection changed
void QmitkPreprocessingResampling::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes)
{
ResetOneImageOpPanel();
//any nodes there?
if (!nodes.empty())
{
// reset GUI
m_Controls->timeSliceNavigationWidget->setEnabled(false);
m_Controls->leImage1->setText(tr("Select an Image in Data Manager"));
m_SelectedNodes.clear();
for (mitk::DataNode* _DataNode : nodes)
{
m_SelectedImageNode->RemoveAllNodes();
*m_SelectedImageNode = _DataNode;
mitk::Image::Pointer tempImage = dynamic_cast<mitk::Image*>(m_SelectedImageNode->GetNode()->GetData());
//no image
if (tempImage.IsNull() || (tempImage->IsInitialized() == false))
{
if (m_SelectedNodes.size() < 1)
{
m_Controls->leImage1->setText(tr("Not an image."));
}
continue;
}
//2D image
if (tempImage->GetDimension() < 3)
{
if (m_SelectedNodes.size() < 1)
{
m_Controls->leImage1->setText(tr("2D images are not supported."));
}
continue;
}
if (m_SelectedNodes.size() < 1)
{
m_Controls->leImage1->setText(QString(m_SelectedImageNode->GetNode()->GetName().c_str()));
mitk::Vector3D aSpacing = tempImage->GetGeometry()->GetSpacing();
std::string text("x-spacing (" + std::to_string(aSpacing[0]) + ")");
m_Controls->tlParam1->setText(text.c_str());
text = "y-spacing (" + std::to_string(aSpacing[1]) + ")";
m_Controls->tlParam2->setText(text.c_str());
text = "z-spacing (" + std::to_string(aSpacing[2]) + ")";
m_Controls->tlParam3->setText(text.c_str());
if (tempImage->GetDimension() > 3)
{
// try to retrieve the TNC (for 4-D Processing )
this->InternalGetTimeNavigationController();
m_Controls->timeSliceNavigationWidget->setEnabled(true);
m_Controls->tlTime->setEnabled(true);
}
}
m_SelectedNodes.push_back(_DataNode);
}
if (m_SelectedNodes.size() > 0)
{
*m_SelectedImageNode = m_SelectedNodes[0];
}
ResetParameterPanel();
}
}
void QmitkPreprocessingResampling::ResetOneImageOpPanel()
{
m_Controls->tlTime->setEnabled(false);
m_Controls->btnDoIt->setEnabled(false);
m_Controls->buttonExecuteOnMultipleImages->setEnabled(false);
m_Controls->cbHideOrig->setEnabled(false);
m_Controls->leImage1->setText(tr("Select an Image in Data Manager"));
m_Controls->tlParam1->setText("x-spacing");
m_Controls->tlParam1->setText("y-spacing");
m_Controls->tlParam1->setText("z-spacing");
}
void QmitkPreprocessingResampling::ResetParameterPanel()
{
m_Controls->btnDoIt->setEnabled(true);
m_Controls->buttonExecuteOnMultipleImages->setEnabled(true);
m_Controls->cbHideOrig->setEnabled(true);
}
void QmitkPreprocessingResampling::ResetTwoImageOpPanel()
{
}
void QmitkPreprocessingResampling::StartMultipleImagesButtonClicked()
{
for (auto currentSelectedNode : m_SelectedNodes)
{
m_SelectedImageNode->RemoveAllNodes();
*m_SelectedImageNode = currentSelectedNode;
StartButtonClicked();
}
}
void QmitkPreprocessingResampling::StartButtonClicked()
{
if(!m_SelectedImageNode->GetNode()) return;
this->BusyCursorOn();
mitk::Image::Pointer newImage;
try
{
newImage = dynamic_cast<mitk::Image*>(m_SelectedImageNode->GetNode()->GetData());
}
catch ( std::exception &e )
{
QString exceptionString = tr("An error occured during image loading:\n");
exceptionString.append( e.what() );
QMessageBox::warning( nullptr, "Preprocessing - Resampling: ", exceptionString , QMessageBox::Ok, QMessageBox::NoButton );
this->BusyCursorOff();
return;
}
// check if input image is valid, casting does not throw exception when casting from 'NULL-Object'
if ( (! newImage) || (newImage->IsInitialized() == false) )
{
this->BusyCursorOff();
QMessageBox::warning( nullptr, "Preprocessing - Resampling", tr("Input image is broken or not initialized. Returning."), QMessageBox::Ok, QMessageBox::NoButton );
return;
}
// check if operation is done on 4D a image time step
if(newImage->GetDimension() > 3)
{
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(newImage);
timeSelector->SetTimeNr(m_Controls->timeSliceNavigationWidget->GetPos());
timeSelector->Update();
newImage = timeSelector->GetOutput();
}
// check if image or vector image
ImageType::Pointer itkImage = ImageType::New();
VectorImageType::Pointer itkVecImage = VectorImageType::New();
int isVectorImage = newImage->GetPixelType().GetNumberOfComponents();
if(isVectorImage > 1)
{
CastToItkImage( newImage, itkVecImage );
}
else
{
CastToItkImage( newImage, itkImage );
}
std::stringstream nameAddition("");
double dparam1 = m_Controls->dsbParam1->value();
double dparam2 = m_Controls->dsbParam2->value();
double dparam3 = m_Controls->dsbParam3->value();
try{
std::string selectedInterpolator;
ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New();
switch (m_SelectedInterpolation)
{
case LINEAR:
{
LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New();
resampler->SetInterpolator(interpolator);
selectedInterpolator = "Linear";
break;
}
case NEAREST:
{
NearestInterpolatorType::Pointer interpolator = NearestInterpolatorType::New();
resampler->SetInterpolator(interpolator);
selectedInterpolator = "Nearest";
break;
}
case SPLINE:
{
BSplineInterpolatorType::Pointer interpolator = BSplineInterpolatorType::New();
interpolator->SetSplineOrder(3);
resampler->SetInterpolator(interpolator);
selectedInterpolator = "B-Spline";
break;
}
default:
{
LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New();
resampler->SetInterpolator(interpolator);
selectedInterpolator = "Linear";
break;
}
}
resampler->SetInput( itkImage );
resampler->SetOutputOrigin( itkImage->GetOrigin() );
ImageType::SizeType input_size = itkImage->GetLargestPossibleRegion().GetSize();
ImageType::SpacingType input_spacing = itkImage->GetSpacing();
ImageType::SizeType output_size;
ImageType::SpacingType output_spacing;
if (dparam1 > 0)
{
output_size[0] = std::ceil(input_size[0] * (input_spacing[0] / dparam1));
output_spacing[0] = dparam1;
}
else
{
output_size[0] = std::ceil(input_size[0] * (-1.0 / dparam1));
output_spacing[0] = -1.0*input_spacing[0] * dparam1;
}
if (dparam2 > 0)
{
output_size[1] = std::ceil(input_size[1] * (input_spacing[1] / dparam2));
output_spacing[1] = dparam2;
}
else
{
output_size[1] = std::ceil(input_size[1] * (-1.0 / dparam2));
output_spacing[1] = -1.0*input_spacing[1] * dparam2;
}
if (dparam3 > 0)
{
output_size[2] = std::ceil(input_size[2] * (input_spacing[2] / dparam3));
output_spacing[2] = dparam3;
}
else
{
output_size[2] = std::ceil(input_size[2] * (-1.0 / dparam3));
output_spacing[2] = -1.0*input_spacing[2] * dparam3;
}
resampler->SetSize( output_size );
resampler->SetOutputSpacing( output_spacing );
resampler->SetOutputDirection( itkImage->GetDirection() );
resampler->UpdateLargestPossibleRegion();
ImageType::Pointer resampledImage = resampler->GetOutput();
newImage = mitk::ImportItkImage( resampledImage )->Clone();
nameAddition << "_Resampled_" << selectedInterpolator;
std::cout << "Resampling successful." << std::endl;
}
catch (...)
{
this->BusyCursorOff();
QMessageBox::warning(nullptr, "Warning", "Problem when applying filter operation. Check your input...");
return;
}
newImage->DisconnectPipeline();
// adjust level/window to new image
mitk::LevelWindow levelwindow;
levelwindow.SetAuto( newImage );
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
levWinProp->SetLevelWindow( levelwindow );
// compose new image name
std::string name = m_SelectedImageNode->GetNode()->GetName();
if (name.find(".nrrd") == name.size() -5 )
{
name = name.substr(0,name.size() -5);
}
name.append( nameAddition.str() );
// create final result MITK data storage node
mitk::DataNode::Pointer result = mitk::DataNode::New();
result->SetProperty( "levelwindow", levWinProp );
result->SetProperty( "name", mitk::StringProperty::New( name.c_str() ) );
result->SetData( newImage );
// for vector images, a different mapper is needed
if(isVectorImage > 1)
{
mitk::VectorImageMapper2D::Pointer mapper =
mitk::VectorImageMapper2D::New();
result->SetMapper(1,mapper);
}
// add new image to data storage and set as active to ease further processing
GetDataStorage()->Add( result, m_SelectedImageNode->GetNode() );
if ( m_Controls->cbHideOrig->isChecked() == true )
m_SelectedImageNode->GetNode()->SetProperty( "visible", mitk::BoolProperty::New(false) );
// show the results
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
this->BusyCursorOff();
}
void QmitkPreprocessingResampling::SelectInterpolator(int interpolator)
{
switch (interpolator)
{
case 0:
{
m_SelectedInterpolation = LINEAR;
break;
}
case 1:
{
m_SelectedInterpolation = NEAREST;
break;
}
case 2:
{
m_SelectedInterpolation = SPLINE;
}
}
}
diff --git a/Plugins/org.mitk.gui.qt.radiomics/CMakeLists.txt b/Plugins/org.mitk.gui.qt.radiomics/CMakeLists.txt
deleted file mode 100644
index 13a722be5a..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-project(org_mitk_gui_qt_radiomics)
-
-mitk_create_plugin(
- EXPORT_DIRECTIVE RADIOMICS_EXPORT
- EXPORTED_INCLUDE_SUFFIXES src
- MODULE_DEPENDS MitkQtWidgetsExt MitkCLUtilities MitkBasicImageProcessing MitkMultilabel
-)
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/UserManual/QmitkPhenotypingPortalPage.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/UserManual/QmitkPhenotypingPortalPage.dox
deleted file mode 100644
index a5f247508a..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/UserManual/QmitkPhenotypingPortalPage.dox
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
-\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 <a href="https://www.dkfz.de/en/mic/index.php">Division of Medical Image Computing</a> 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 \ref org_mitk_views_basicimageprocessing : Deprecated plugin for performing different image-related tasks like subtraction, mutliplaction, filtering etc.
-\li \ref org_mitk_views_matchpoint_algorithm_browser : Selection of MatchPoint (Registration) Algorithm
-\li \ref org_mitk_views_matchpoint_algorithm_control : Configuring and Controlling MatchPoint (Registration) Algorithm
-\li \ref org_mitk_views_matchpoint_evaluator : Evaluate the Registration performance using MatchPoint
-\li \ref org_mitk_views_matchpoint_manipulator : Adapt a registration calculated using MatchPoint
-\li \ref org_mitk_views_matchpoint_mapper : Apply a MatchPoint Registration to a specific image
-\li \ref org_mitk_views_matchpoint_visualizer : Visualize a Registration obtained with MatchPoint
-\li \ref org_mitk_views_segmentation : Creating Multilabel Segmentations
-\li \ref 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/QmitkRadiomicsArithmetricView.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsArithmetricView.dox
deleted file mode 100644
index fb56062e54..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsArithmetricView.dox
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
-\page org_mitk_views_radiomicsarithmetricview Image Arithmetrics
-
-Allows to perform basic arithmetic operations with all images. By default, the resulting image will be of the same type as the first input image. This also means that all operations will be perfomed using the same datatype as the input image. This can lead to rounding errors if an integer data type is used. It is possible to avoid this problem by creating a double-based image as result image by selecting the corresponding option.
-
-There are three different types of operations:
-\li Single Image Operations: These are operations that are performed on each voxel value and do not need any additional parameter. Typical operations are calculating the absolute value of an image, or calculating an trigometric value.
-\li Single Image Operations: These are operations that are performed on each voxel value and do not need any additional parameter. Typical operations are calculating the absolute value of an image, or calculating an trigometric value.
-\li Single Image and Double Value Operation: These are the basic mathematical operations (add, subtract, multiply, and dividive).
-\li Two Images Operations: Allows to perfom basic operations between two images.
-
-\section IA_SingleImageOperations Single Image Operations
-Allows to perfom a arithmetic operation to each voxel of an image independently. Be aware that some operations expect a specific input range. This range is usually not tested for, and it might cause an error if the range if values outside of the expceted range occure. Also, some operations are rather expensive with respect to the calculation time and take some time to finish.
-
-\section IA_SingleImageAndDoubleValue Single Image and Double Value Operation
-Performs a basic mathematical operation (add, subtract, multiply, and divide) between an image and a floating point value. The operation is execuded for each voxel independently. There are two options if the order of the input is relevant (i.e. for subtraction and division) to enable both ways.
-
-\section IA_TwoImages Two Image Operations
-This allows to perfom mathematical operations between two images. The second image needs to be specified within this panel. Both images must match in size, it is also assumed (but not checked) that both images share the same geometry. This means that the corresponding voxels of both images share the same geometrical space.
-
-The first image, that would also be used for other operations, is used as "Image", while the image specified in the panel is used as "Second Image". In general, the first image is also used as first parameter in the mathematical operation.
-
-*/
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsMaskProcessingView.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsMaskProcessingView.dox
deleted file mode 100644
index 23a57edb3e..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsMaskProcessingView.dox
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
-\page org_mitk_views_radiomicsmaskprocessingview Mask Processing
-
-This view gives the option to process existing masks. Currently this means cleaning the mask to remove areas that are probably wrongly segmented.
-
-The view expects two inputs. The first input (1) should be an image and the second input (2) a mask that corresponds to the given input. The mask needs to be a multi-label image. If the existing mask is not a multi-label image, it can be converted to such an image type by right-clicking on the corrsponding image in the "Data Manager" and selecting the point "Convert to Segmentation".
-
-The algorithm expects that the mask and the image share the same geomentry, e.g. have the same spacing, size, and origin. It further works only on the first layer of the segmentation , e.g. it is expected that the image contains only the values 0 and 1, with 1 marking the voxels that are segmented.
-
-There are two options to clean an existing mask. Either by defining a lower or upper limit or by removing the outlier.
-
-If the intensity values corresponds to clear image values, as it is for example with CT, it might be possible to limit the segmentation to only fixed intensity range. This can be done by defining an lower or upper limit and pressing the "Clean Mask based on Intervall" button (4). All elements of the mask which cover voxels with images outside of the specified intervall will then be set to zero, i.e. removed from the mask. To specify the limit, the corresponding values needs to be specified in the corresponding input (3). The lower or upper limit will only be applied if they are enabled! It is possible to either apply only a lower limit, only a upper limit, or applying a lower and an upper limit at the same time.
-
-The second option is to remove all voxels that are outside a three sigma interval from the mean value. The rational behind this is that those values are different from the other values and therefore might represent outliers. This option can be simply perfomed by pressing button "Remove outlier from Mask..." (5).
-
-The resulting image from all options will be masks again.
-
-\imageMacro{RadiomicsMaskProcessingView_01_Overview.png,"Overview of the Mask Processing View",1}
-
-*/
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsStatisticView.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsStatisticView.dox
deleted file mode 100644
index c533696d6a..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsStatisticView.dox
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
-\page org_mitk_views_radiomicsstatisticview Radiomics Statistic
-
-This is a basic view to actually calculate different image features, for example those necessary for radiomic studies. It is possible to select the required feature classes that should be calculated from the given image.
-
-In order to be able to calculate the features it is necessary to define an image (1) and a corresponding mask (2). The image will be converted to an double image during the feature calculation and the mask must be a an Multi-Level Segmentation. If the mask is a standard mask, it is possible to convert the mask into a multilabel mask by right-clicking on the corresponding image on the "Data Manager" and selecting the point "Convert to Segmentation". The image and the segmentation must have the same geometry, e.g. the same spacing, origin, transformation matrix, and same dimensions.
-
-Before calculating the features, it is necessary to select the feature classes that should be calculated in the corresponding panel (3). Each feature class consists of a set of Radiomics Features that share common proporties in the calculation process. All possible feature classes are derived from the AbstractGlobalImageFeature class. To get more details about the individual features, please see the corresponding classes.
-
-It is possible to configure all feature classes within the "Feature Class Selection"-panel (3) but it is also possible to set more global configuration parameters in teh "Configuration Parameter" panel (4). The options set here will influence all features if the corresponding parameter is not explicitly overwritten. For a detailed description of the parameters, see the corresponding subsection.
-
-After starting the calculation process with the "Execute" Button (5), the features will be calculated and the result shown in the result table (6) at the end of the view.
-
-\imageMacro{RadiomicsStatisticView_01_Overview.png,"Overview of the Radiomics Statistic View. ",1}
-
-\section Parameters
-There are two types of possible parameters. The Binning Parameters (1-4) which helps to control the histogram building process that most feature classes use. The second group represent more general parameter (5-7). All parameters are disabled by default (Checkbox left of feature description text), as there is no default value that fits all cases. In order to set a parameter, it must be first enabled. This is especially important for binary options like ignorign the mask for the histogram.
-
-The histogram options allow to define the histogram that is used for many feature classes. It is possible to define a minimum (1) and a maximum (2) intensity value for the histogram. In addition to this there is the possiblility to set the number of bins (3) or the bin size (4) for each histogram. A detailed description of each parameter is given in the description of the AbstractGlobalImageFeature class.
-
-With "Encode Parameter in Name" (5) it is possible to allow the actual parameter set to be encoded in the final feature name. By default, the resulting feature names will only contain the feature class and the actual feature name. If this option is checked, also all relevant parameters are encoded in the name of each feature.
-
-The parameter "Direction Parameter" allows to restrict the calculation of the feature to a given dimension, if this is supported by the feature classes. If it is set to 0, all directions are considered. If it is set to 1, only one direction is considered (mainly for testing purpose). If it is set to values 2 to n, the value-2 dimension is not considered during the feature calculation.
-
-The parameter "Slice-wise calculation" allows to perform slice-wise calculations. Generally, it can be used with all parameters but not all features are well-defined for 2D data (for example, volume based features expect at least 3 dimensions). The value defied here gives the axis along which the split is performed.
-
-\imageMacro{RadiomicsStatisticView_02_Parameter.png,"List of possible Parameters",1}
-
-
-
-*/
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsTransformationView.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsTransformationView.dox
deleted file mode 100644
index c7147ec856..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/QmitkRadiomicsTransformationView.dox
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
-\page org_mitk_views_radiomicstransformationview Image Transformations
-
-This view can be used to apply various transformation to an image. Currently it is possible to apply one of four transformations. In order to do this, a first step is to select an image (1). After this, one of the four possible transformations must be selected (2). Possible actions are:
-\li Multi-Reolution Pyramid
-\li Resample Image
-\li Wavelet Transformation
-\li Lapalcian of Gaussian
-
-\imageMacro{RadiomicsTransformationView_01_Overview.png,"Overview of the transformation view",1}
-
-\section org_mitk_views_radiomicstransformationview_MultiResolutionPyramid Multi-Resolution Pyramid
-Creates a multi-resolution pyramid by filtering the images using a gaussian kernel and then reduing the resolution by a factor 2 for each step of the pyramid. The spacing is adapted duringt the creation of each step. Therefore, the spacial size of the image will be kept.
-
-The view offers two possible parameters. With option (1), "Number of Levels" the number of pyramid levels are controlled. The image of the first level has always the same resolution as the input image. If the input image has 256x256 voxels in two dimensions and the number of levels is set to 4, the resulting output images will be:
-\li Image 0 : Resolution 256x256
-\li Image 1 : Resolution 128x128
-\li Image 2 : Resolution 64x64
-\li Image 3 : Resolution 32x32
-
-With the second option (2), it is possible to ensure that the output will be of the type "double". If this option is not checked, the result will be of the same type as the input image. Beware that this might lead to some artefacts due to the resmapling artefacts.
-
-\imageMacro{RadiomicsTransformationView_02_MultiResolution.png,"Multi-Resolution panel of the Transofrmation View",1}
-
-\section org_mitk_views_radiomicstransformationview_ResampleImage Image Resampling
-Allows to simply resampling an existing image. It is based on the functionality of the MatchPoint Framework.
-
-Options:
-\li Dimension ... (1) : The new target spacing. If this is not enabled (by deselecting the corrsponding option), or set to a negative or zero value, the original spacing will be kept and the corresponding dimension will not be resampled.
-\li Interpolation mode (2): Set the mode for the interpolation. Possible options are "linear" e.g. using a linear model to determine the new intensity value, "B-Spline" e.g. using a higher-dimensional function (second order), "Nearest Neighbour" e.g. using the intensity of the nearest original voxel, "WSinc Hamming", "WSinc Welch" e.g. using Hamming or Welch windowing function.
-\li Grid alignment method (3): Allows to define the alignment method for the newly created image. It is either "Origin algined" e.g. the origin of the original and resampled image match, "Center aligned" e.g. the center of the images are matched or "same size" in which case the resolution will be slightly adated so that the new created image will have the exact same spacial dimensions.
-\li Output as double (4): Returns the resampled image as double output. Without selecting this option, the resulting image will be of the same datatype as the input image.
-\li Round output (5): If this option is selected, the intensity values of the resampled image will be rounded to the next integer.
-\li Resample as mask (6): Resamples the input as mask. Assumes that the input image is a mask, but will also work with other image types. The output value is either 0 or 1. If a interpolation method other than "nearest Neighbour" is chosen, the image will be thresholded with the value 0.5 in order to create the mask.
-
-\imageMacro{RadiomicsTransformationView_03_Resample.png,"Resampling panel of the Transformation View",1}
-
-\section org_mitk_views_radiomicstransformationview_WaveletTransform Wavelet Transformations
-Applying wavelet transformations to the original image. It is expected that the user has sufficient knowledge about Wavelet transformations if this toolbox is used.
-
-
-\section org_mitk_views_radiomicstransformationview_LoG Laplacian of Gaussian
-Applies a Laplacian of Gaussian Transformation to the input image. This is defined as the second order deviation of a gaussian smoothed image.
-The option "Gaussian Sigma" (1) defines the width of the gaussian kernel that is used by defining the corresponding sigma level in mm. It is possible to capture different details on the image by using various sigma levels.
-
-The option "Return result as double" allows to ensure that the result will be of type double. If this option is not selected, the resulting image will be of the same type as the input image. Be aware that all calculations will be performed using the output image data type. If this is not a floating point type, the result might be affected by rounding errors.
-
-\imageMacro{RadiomicsTransformationView_05_LoG.png,"Laplacian of Gaussian panel of the Transformation View",1}
-*/
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsMaskProcessingView_01_Overview.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsMaskProcessingView_01_Overview.png
deleted file mode 100644
index 3487a3d27d..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsMaskProcessingView_01_Overview.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsStatisticView_01_Overview.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsStatisticView_01_Overview.png
deleted file mode 100644
index 1bc61c1966..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsStatisticView_01_Overview.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsStatisticView_02_Parameter.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsStatisticView_02_Parameter.png
deleted file mode 100644
index fcdf83bb82..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsStatisticView_02_Parameter.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_01_Overview.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_01_Overview.png
deleted file mode 100644
index 07902bd644..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_01_Overview.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_02_MultiResolution.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_02_MultiResolution.png
deleted file mode 100644
index 0517912a71..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_02_MultiResolution.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_03_Resample.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_03_Resample.png
deleted file mode 100644
index 89b25cfc0b..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_03_Resample.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_05_LoG.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_05_LoG.png
deleted file mode 100644
index e12c03be4d..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/RadiomicsTransformationView_05_LoG.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/modules.dox
deleted file mode 100644
index 7bf036aa2a..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/modules.dox
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- \defgroup org_mitk_gui_qt_basicimageprocessing org.mitk.gui.qt.basicimageprocessing
- \ingroup MITKPlugins
-
- \brief Describe your plugin here.
-
-*/
-
-/**
- \defgroup org_mitk_gui_qt_basicimageprocessing_internal Internal
- \ingroup org_mitk_gui_qt_basicimageprocessing
-
- \brief This subcategory includes the internal classes of the org.mitk.gui.qt.basicimageprocessing plugin. Other
- plugins must not rely on these classes. They contain implementation details and their interface
- may change at any time. We mean it.
-*/
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_00_PortalPage.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_00_PortalPage.dox
deleted file mode 100644
index 315c0640e1..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_00_PortalPage.dox
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
-\page org_mitk_views_radiomicstutorial_gui_portal GUI based Radiomics Tutorial
-
-This is an basic tutorial to show how MITK Phenotyping can be used to perform the individual steps of an radiomics study. It assumes that you have MITK Phenotyping running on your server, and focuses on the usage of the graphical interface.
-
-In order to use the Tutorial you need an 3D image. We will use the Pic3D.nrrd image, which can be downloaded from https://www.mitk.org/download/tutorial-data/Pic3D.nrrd . So if you want to have a better comparability between our results and your results, we suggest that you use this image as well. However, feel free to use your own image if you want.
-
-The tutorial is designed along the steps that would be perfomed within a radiomics study until to the point where the radiomic features are obtained and the statistical analysis would be necessary. This should be done in the tool of choice of the scientist. Please be aware: This is not a real study, and you might perfom some steps differently or additional steps in a real radiomics study. The main aim of this study is to give the reader an idea how to perfom individual steps in MITK.
-
-The first step is to make MITK Phenotyping and the MITK Workbench familiar to you. If you know the basic of the MITK Workbench, you can skip this step.
-\subpage org_mitk_views_radiomicstutorial_gui_01_basic
-
-The second step is to create a segmentation for the next steps. If you want to create the segmentations with a different tool, you can also skip this step.
-\subpage org_mitk_views_radiomicstutorial_gui_02_Segmentation
-
-The third step is to preprocess the images. This step could also be perfomed before creating the segmentation, which is actually suggested. But it is common that the segmentations are already created for a study. Therefore, we put this step after the segmentation creation process.
-\subpage org_mitk_views_radiomicstutorial_gui_03_preprocessing
-
-The fourth and last step of this tutorial covers the calculation of the features with the graphical interface. We only use a limited amount of features, feel free to calculate more features in one step.
-\subpage org_mitk_views_radiomicstutorial_gui_04_featurecalulation
-
-*/
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_01_Basic.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_01_Basic.dox
deleted file mode 100644
index 8955702e42..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_01_Basic.dox
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
-\page org_mitk_views_radiomicstutorial_gui_01_basic GUI based Radiomics Tutorial - Basic handling of MITK
-
-\section Basic handling of MITK
-
-Open a MITK Workbench which also includes MITK Phenotyping. You should see something similar to figure 1. At the top you'll see a bar (1), (2) with different important operations like open and saving data, different important views (like DICOM Window, Image Navigator and View Navigator), and a list of all Views included in your version (2). Items are grouped, and depending on the width of your screen might be hidden behind small arrows.
-
-The Data Manager (3) is usually placed at the left, although it could be also open at other positions. It is used to organize open images and other data items. Below it you see the Image Navigator (4) which helps to navigate through the 3D data. It allows to change the position within the data either in real-world coordinates (in mm) or by specifiying a slice number.
-
-In the center of your application you should see the Displays (5), which will display the images. It usually consists of four views, showing axial, sagittal, coronal and a 3D view of the data. It is possible to rearange the single displays and configure them to your wishes with the three small buttons which will become visible if the mouse is in the upper right corner of display.
-
-Beside these elements, there are various open views (6). You can close them with the cross and reopen them using the bar at the top (2). It is also possible to rearrange all Views to various positions left, right, above, or below the displays.
-
-An important view is the "View Navigator". In figure 1 it is hidden behind the Data Manager (3) and could be made visible with a click on the corresponding bar left of the "Data Manager" bar. The View Navigator is an easy and straight forward tool to show all available views and open them. It allows to search through all views. Offering a search function it allows to find views using their name of just searching for a functionality you are looking for.
-
-\imageMacro{RadiomicsTutorial_GUI_Step1_01_Overview.png,"Overview of MITK Workbench with active MITK Phenotyping",1}
-
-\section Loading image data
-In order to calculate the radiomics features using the graphical interface you first need to load the data into the graphical environment. This can be done in different ways. If you want to load an DICOM series, it is sufficient to load a single image if the other images of the series are within the same folder. MITK will then combine all Series DICOM Images to a single 3D Image.
-
-\li Open an Image using the "Open File" menu item: If you click on the "Open File" item in the "File" menu or the "Open File" button in the top bar you will be presented a standard file dialog of your system. Select the image you want to load and click "Open".
-
-\li Drag n' Drop: Select the image you want to load with your standard data managing tool, for example with the explorer on windows or finder on Mac. Drag and drop the file into the open MITK Workbench window, the image will then be loaded if possible. If you
-
-\li DICOM Browser: MITK offers the basic possibiliy to manage and handle DICOM images using the DICOM Browser. You can enable this view by clicking on "DICOM", right of the "Redo"-Button. Within the DICOM Browser, it is possible to read complete folders, and load specific series into the workbench. For more information see \ref org_mitk_gui_qt_dicombrowser .
-
-*/
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_02_Segmenting.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_02_Segmenting.dox
deleted file mode 100644
index 33ebf61e73..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_02_Segmenting.dox
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
-\page org_mitk_views_radiomicstutorial_gui_02_Segmentation GUI based Radiomics Tutorial - Creating a basic Segmentation
-
-\section Creating a basic Segmentation
-
-The first step is to create a new segmentation that can be used to calculate radiomics features. You might skip this step if you already have an segmentation at hand. Ti For this, we load the image we want to process and open the segmentation view. The easiest way to do this is to open the "View Navigator" and search for segmentation. The Segmentation view can then be opened by simply double-clicking on the view in the "View Navigator".
-
-With this view, we will create an One-Level segmentation. It would also be possible to create a multi-label segmentation where more than one structure can be segmented using the MultiLabel segmentation. Howerver, MITK Phenotyping is currently only supporting one Label per mask, so there would be no benefit in doing so. In addition, the created segmentation could be extended further if needed.
-
-\imageMacro{RadiomicsTutorial_GUI_Step2_01_Preparation.png,"Segmentation View and loaded image in the MITK Workbench. Go to the position indicated in the Image Navigator for the same view.",1}
-
-To now create a segmentation, we press the "New"-Button in the Data Selection part of the "Segmentation"-View. After giving the segmentation a name and probably selecting a new color if red isn't what we want, we can see a new image in the "Data Manager", the segmentation image. The segmentation can now be edited using the segmentation tools, either slice-by-slice wise or the whole 3D volume using one of the 3D tools. A good description of the different tools and their implication can be found a \ref org_mitk_views_segmentation . The different modes and options are also described there.
-
-We create a simple segmentation of a rib in a few slices, as indiciated by the following picture. At this point, we suggest that you play around to get used to the segmentation tool and then try to roughly reproduce our results. It is not necessary to obtain a one-to-one solution of our segmentation.
-
-\imageMacro{RadiomicsTutorial_GUI_Step2_02_StartSegmentation.png,"Basic segmentation of a rib we created in 6 slices. The color of the segmentation is changed to orange for bone.",1}
-
-*/
\ No newline at end of file
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
deleted file mode 100644
index d715dcd58d..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_03_Preprocessing.dox
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
-\page org_mitk_views_radiomicstutorial_gui_03_preprocessing GUI based Radiomics Tutorial - Preprocessing the data
-
-\section 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_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.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_04_FeatureCalculating.dox b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_04_FeatureCalculating.dox
deleted file mode 100644
index 2ac32167bb..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_04_FeatureCalculating.dox
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
-\page org_mitk_views_radiomicstutorial_gui_04_featurecalulation GUI based Radiomics Tutorial - Calculating the Radiomics Features
-
-\section Calculating the Radiomics Features
-The most important step of a radiomic study is the calculating of the features. With MITK Phenotyping this is done using the "Radiomics Statistic" View. Open it using the View Navigator. Within this view, we select the resampled image and the resampled and cleaned mask. In a first step, we select the features we aim to calculate. For this tutorial we chose four features:
-\li Volumetric Features
-\li First Order Numerics
-\li Intensity Volume Histogram
-\li Co-occurence Based Features
-
-After selecting the features, we need to configure the features. We start with the "Intenstiy Volume Histogram" Features. Because this Feature class makes an uncommon use of the internal histogram, it makes sense to set the histogram parameter for this feature individually. To do so, click on the "+" next to the feature class name. You should see a list of feature specific parameter. Activate the following parameter and set them to the given parameter:
-\li ivoh::minimum 159.5
-\li ivoh::maximum 900.5
-\li ivoh::binsize 1.0
-This configures a histogram that starts from 160 and ranges to 900 with a binsize of 1. Since the minimum and maximum parameter specify the borders of the histogram, we added /subtracted the half of the binsize, so that the middle of the bins will be on a integer.
-
-After this step switch to the "Configuration Parameter" panel. Select the default parameters for the histogram:
-\li Minimum Intensity 160
-\li Maximum Intensity 900
-\li Number of Bins 32
-You will recognize that we chose a quite different setting for the histogram this time. Instead of the histogram binsize, we selected the number of bins. Don't forget to activate the features.
-
-As we will calculate multiple features, also activate the "Encode Parameter in Name" option. After this, you can enable the feature calculation by pressing "Execute". You should see the results of the feature calculation process in the table below the configuration list.
-
-We will now calculate the Co-occurence based feature with a different number of bins. For this, change the "Number of Bins" to 64, and deselect all features except the "Co-occurence based Features". In order to keep the previous results, execute the algorithm this time using the button "Execute & Append". The results will be appended to the results shown at the table in the bottom.
-
-Now select a different image and repeat the calculation of the Co-occurence feature with a bin number of 64. Then reselect the "First Order Numberics" and "Intensity Volume Histogram" again and set the number of Bins back to 32. You don't need to recalculate "Volumetric Features" as these features are based on the shape and therefore won't change if only the image is changed.
-
-You will now have a long list of features. To further process these features, press the "Table to Clipboard" button. You can now paste the results in your favourit editor or statistic program and perfom the analysis of the radiomic study.
-
-To give you some ideas how the results look like, here are some results from our experiment. If you used the same image and made a similar mask, you should obtain similar results, although small differences might be based on variations of the segmentation:
-\li Pic3D__Resampled;Bone__Resampled__MaskRange;Co-occurenced Based Features::Min-160_Max-900_Bins-64_Range-1::%Mean Sum Average;52.5338
-\li Pic3D__Resampled;Bone__Resampled__MaskRange;Co-occurenced Based Features::Min-160_Max-900_Bins-32_Range-1::%Mean Sum Average;26.7659
-\li Pic3D__Resampled__LoG__Sigma-1;Bone__Resampled__MaskRange;Co-occurenced Based Features::Min-160_Max-900_Bins-64_Range-1::%Overall Sum Average;2
-\li Pic3D__Resampled__LoG__Sigma-1;Bone__Resampled__MaskRange;Co-occurenced Based Features::Min-160_Max-900_Bins-32_Range-1::%Overall Sum Average;2
-\li Pic3D__Resampled;Bone__Resampled__MaskRange;First Order Numeric::Min-160_Max-900_Bins-32::%Mean;420.761
-\li Pic3D__Resampled__LoG__Sigma-1;Bone__Resampled__MaskRange;First Order Numeric::Min-160_Max-900_Bins-32::%Mean;-137.746
-
-You can see that the parameters used as well as image used have a clear impact on the final features. You can also see how the name of the image, the mask, and the parameters are encoded so that you are able to reproduce how the results were obtained.
-
-*/
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step1_01_Overview.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step1_01_Overview.png
deleted file mode 100644
index 97e7bf73bb..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step1_01_Overview.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step2_01_Preparation.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step2_01_Preparation.png
deleted file mode 100644
index 39a8c9b693..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step2_01_Preparation.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step2_02_StartSegmentation.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step2_02_StartSegmentation.png
deleted file mode 100644
index bc6e8660b8..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step2_02_StartSegmentation.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step3_01_DetailView.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step3_01_DetailView.png
deleted file mode 100644
index a259f92b9b..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step3_01_DetailView.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step3_02_FinishedPreprocessing.png b/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step3_02_FinishedPreprocessing.png
deleted file mode 100644
index 1f96c2a036..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/documentation/doxygen/tutorial_gui/RadiomicsTutorial_GUI_Step3_02_FinishedPreprocessing.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/files.cmake b/Plugins/org.mitk.gui.qt.radiomics/files.cmake
deleted file mode 100644
index 919e17ce03..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/files.cmake
+++ /dev/null
@@ -1,55 +0,0 @@
-set(SRC_CPP_FILES
-
-)
-
-set(INTERNAL_CPP_FILES
- QmitkRadiomicsStatisticView.cpp
- QmitkRadiomicsTransformationView.cpp
- QmitkRadiomicsArithmetricView.cpp
- QmitkRadiomicsMaskProcessingView.cpp
-
-
- mitkBasicImageProcessingActivator.cpp
- QmitkGIFConfigurationPanel.cpp
-)
-
-set(UI_FILES
- src/internal/QmitkRadiomicsStatisticViewControls.ui
- src/internal/QmitkRadiomicsTransformationViewControls.ui
- src/internal/QmitkRadiomicsArithmetricViewControls.ui
- src/internal/QmitkRadiomicsMaskProcessingViewControls.ui
-)
-
-set(MOC_H_FILES
- src/internal/QmitkRadiomicsStatisticView.h
- src/internal/QmitkRadiomicsTransformationView.h
- src/internal/QmitkRadiomicsArithmetricView.h
- src/internal/QmitkRadiomicsMaskProcessingView.h
-
-
- src/internal/mitkBasicImageProcessingActivator.h
- src/internal/QmitkGIFConfigurationPanel.h
-)
-
-set(CACHED_RESOURCE_FILES
- resources/lena.xpm
- resources/Icon_Transformation.png
- resources/bar-chart-radiomics.svg
- resources/transformation-radiomics.svg
- resources/arithmetric-radiomics.svg
- resources/maskcleaning-radiomics.svg
- plugin.xml
-)
-
-set(QRC_FILES
- resources/QmitkRadiomicsStatisticView.qrc
-)
-
-foreach(file ${SRC_CPP_FILES})
- set(CPP_FILES ${CPP_FILES} src/${file})
-endforeach(file ${SRC_CPP_FILES})
-
-foreach(file ${INTERNAL_CPP_FILES})
- set(CPP_FILES ${CPP_FILES} src/internal/${file})
-endforeach(file ${INTERNAL_CPP_FILES})
-
diff --git a/Plugins/org.mitk.gui.qt.radiomics/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.radiomics/manifest_headers.cmake
deleted file mode 100644
index 5a481d9578..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/manifest_headers.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-set(Plugin-Name "MITK Radiomics")
-set(Plugin-Version "0.1")
-set(Plugin-Vendor "German Cancer Research Center (DKFZ)")
-set(Plugin-ContactAddress "https://www.mitk.org")
-set(Require-Plugin org.mitk.gui.qt.common)
diff --git a/Plugins/org.mitk.gui.qt.radiomics/plugin.xml b/Plugins/org.mitk.gui.qt.radiomics/plugin.xml
deleted file mode 100644
index 760d0150df..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/plugin.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<plugin>
-
- <extension point="org.blueberry.ui.views">
- <view id="org.mitk.views.radiomicsstatistic"
- name="Radiomics Statistic"
- class="QmitkRadiomicsStatistic"
- category="Radiomics"
- icon="resources/bar-chart-radiomics.svg" >
- <description>Calculate Radiomics Features from Images</description>
- <keywordReference id="org.mitk.views.radiomicsstatistic.ViewKeyword"/>
- </view>
- <view id="org.mitk.views.radiomicstransform"
- name="Radiomics Transformation"
- class="QmitkRadiomicsTransformation"
- category="Radiomics"
- icon="resources/transformation-radiomics.svg" >
- <description>Calculate Tranformations like LoG and Wavelet from Images</description>
- <keywordReference id="org.mitk.views.radiomicstransform.ViewKeyword"/>
- </view>
- <view id="org.mitk.views.radiomicsarithmetric"
- name="Radiomics Arithmetric"
- class="QmitkRadiomicsArithmetric"
- category="Radiomics"
- icon="resources/arithmetric-radiomics.svg" >
- <description>Calculate Arithmetic Operations for Images</description>
- <keywordReference id="org.mitk.views.radiomicsarithmetric.ViewKeyword"/>
- </view>
- <view id="org.mitk.views.radiomicsmaskprocessing"
- name="Radiomics Mask Processing"
- class="QmitkRadiomicsMaskProcessing"
- category="Radiomics"
- icon="resources/maskcleaning-radiomics.svg" >
- <description>Processing Masks for Radiomics</description>
- <keywordReference id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword"/>
- </view>
- </extension>
-
- <extension point="org.blueberry.ui.keywords">
- <keyword id="org.mitk.views.radiomicsstatistic.ViewKeyword" label="Radiomics" />
- <keyword id="org.mitk.views.radiomicsstatistic.ViewKeyword" label="Statistic" />
- <keyword id="org.mitk.views.radiomicsstatistic.ViewKeyword" label="Personalized Medicine" />
- <keyword id="org.mitk.views.radiomicsstatistic.ViewKeyword" label="Radiogenomic" />
-
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="Radiomics" />
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="Transformation" />
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="Personalized Medicine" />
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="Radiogenomic" />
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="Laplacian of Gaussian" />
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="LoG" />
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="Wavelet" />
- <keyword id="org.mitk.views.radiomicstransform.ViewKeyword" label="Multiresolution" />
-
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Add" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Addition" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Sub" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Subtract" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Arithmetric" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Radiomics" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Multiply" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Multiplication" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Divide" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Division" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Absolute" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Trigometric Functions" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Sinus" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Cosinus" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Tangents" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Square" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Sqrt" />
- <keyword id="org.mitk.views.radiomicsarithmetric.ViewKeyword" label="Square-Root" />
-
- <keyword id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword" label="Mask" />
- <keyword id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword" label="Segmentation" />
- <keyword id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword" label="Radiomics" />
- <keyword id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword" label="Preprocessing" />
- <keyword id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword" label="Outlier Detection" />
- <keyword id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword" label="Mask Cleaning" />
- <keyword id="org.mitk.views.radiomicsmaskprocessing.ViewKeyword" label="Personalized Medicine" />
- </extension>
-</plugin>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/Icon_Transformation.png b/Plugins/org.mitk.gui.qt.radiomics/resources/Icon_Transformation.png
deleted file mode 100644
index 51a0a89cee..0000000000
Binary files a/Plugins/org.mitk.gui.qt.radiomics/resources/Icon_Transformation.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/ImageProcessing_64.xpm b/Plugins/org.mitk.gui.qt.radiomics/resources/ImageProcessing_64.xpm
deleted file mode 100644
index 9265a814a2..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/ImageProcessing_64.xpm
+++ /dev/null
@@ -1,318 +0,0 @@
-/* XPM */
-static char *ImageProcessing___[] = {
-/* columns rows colors chars-per-pixel */
-"64 64 248 2",
-" c #3F3235",
-". c #572F3A",
-"X c #592F3A",
-"o c #463337",
-"O c #483137",
-"+ c #513037",
-"@ c #503138",
-"# c #503039",
-"$ c #533038",
-"% c #533138",
-"& c #533139",
-"* c #553039",
-"= c #5B313C",
-"- c #612F3B",
-"; c #622E3B",
-": c #632F3B",
-"> c #652F3C",
-", c #682E3C",
-"< c #6F2D3E",
-"1 c #712E3E",
-"2 c #752D3E",
-"3 c #742C3F",
-"4 c #752C3F",
-"5 c #7A2D40",
-"6 c #6E3F4A",
-"7 c #743F4D",
-"8 c #773F4C",
-"9 c #7B3D4C",
-"0 c #783E4C",
-"q c #7B3E4D",
-"w c #7D3D4C",
-"e c gray30",
-"r c #5B444B",
-"t c #67434C",
-"y c #67434D",
-"u c #62454C",
-"i c #62464D",
-"p c #62474D",
-"a c #62464E",
-"s c #65444C",
-"d c #65454C",
-"f c #66444C",
-"g c #67444C",
-"h c #66444D",
-"j c #67444D",
-"k c #66454D",
-"l c #67454D",
-"z c #64464D",
-"x c #66464D",
-"c c #67454E",
-"v c #66464F",
-"b c #68434C",
-"n c #6E404C",
-"m c #6F414D",
-"M c #6D424C",
-"N c #6E424C",
-"B c #68444C",
-"V c #69444C",
-"C c #68454D",
-"Z c #70414C",
-"A c #71414C",
-"S c #71404D",
-"D c #70414D",
-"F c #72404C",
-"G c #73404D",
-"H c #744651",
-"J c #7D4351",
-"K c #7D4F59",
-"L c #665659",
-"P c #615B5C",
-"I c gray40",
-"U c #676767",
-"Y c #686868",
-"T c DimGray",
-"R c #6A6A6A",
-"E c gray42",
-"W c #6C6B6C",
-"Q c #6C6C6C",
-"! c #6D6D6D",
-"~ c #717171",
-"^ c #727272",
-"/ c gray45",
-"( c #747474",
-") c gray46",
-"_ c #767676",
-"` c #777777",
-"' c gray47",
-"] c gray48",
-"[ c #7B7B7B",
-"{ c #7C7C7C",
-"} c #852B41",
-"| c #822D40",
-" . c #8A2B42",
-".. c #8C2B42",
-"X. c #8E2A42",
-"o. c #892C42",
-"O. c #962B45",
-"+. c #9E2A46",
-"@. c #8D364C",
-"#. c #833A4B",
-"$. c #803B4C",
-"%. c #823A4C",
-"&. c #853A4C",
-"*. c #863A4C",
-"=. c #863A4D",
-"-. c #813C4C",
-";. c #833C4D",
-":. c #88394C",
-">. c #8B384C",
-",. c #97344B",
-"<. c #90364C",
-"1. c #92374D",
-"2. c #94344C",
-"3. c #98334B",
-"4. c #9F324B",
-"5. c #9F304C",
-"6. c #9D324C",
-"7. c #AD2748",
-"8. c #A22F4B",
-"9. c #A42F4B",
-"0. c #A72E4B",
-"q. c #AF2848",
-"w. c #AB2D4B",
-"e. c #AC2D4B",
-"r. c #AA2D4C",
-"t. c #AD2C4C",
-"y. c #B6274A",
-"u. c #B7274A",
-"i. c #B8274A",
-"p. c #BB274B",
-"a. c #BD264B",
-"s. c #BD274B",
-"d. c #BE264B",
-"f. c #BF264B",
-"g. c #BE274B",
-"h. c #BF274B",
-"j. c #B32A4B",
-"k. c #B22B4B",
-"l. c #B7284B",
-"z. c #B6294B",
-"x. c #B42A4B",
-"c. c #B52A4B",
-"v. c #B42A4C",
-"b. c #B62A4C",
-"n. c #B9284B",
-"m. c #BA284B",
-"M. c #BB284B",
-"N. c #B9294C",
-"B. c #A1304C",
-"V. c #A2304C",
-"C. c #B73152",
-"Z. c #AB445D",
-"A. c #825962",
-"S. c #9D5667",
-"D. c #95606E",
-"F. c #95616E",
-"G. c #93646F",
-"H. c #8F6A72",
-"J. c #8B7077",
-"K. c #8C7077",
-"L. c #8D777D",
-"P. c #88797D",
-"I. c #937077",
-"U. c #907A7F",
-"Y. c #897D81",
-"T. c #8A7D80",
-"R. c #8A7D81",
-"E. c #8B7E81",
-"W. c #8C7D82",
-"Q. c #A87C85",
-"!. c #808080",
-"~. c #818181",
-"^. c gray51",
-"/. c #838383",
-"(. c #848081",
-"). c #868084",
-"_. c #848484",
-"`. c gray52",
-"'. c gray53",
-"]. c #8C8485",
-"[. c #8D8485",
-"{. c #8E8486",
-"}. c #8F8487",
-"|. c #8A8588",
-" X c #8E8789",
-".X c #888888",
-"XX c #898989",
-"oX c gray54",
-"OX c #8F8889",
-"+X c gray55",
-"@X c #8D8C8D",
-"#X c #8D8D8D",
-"$X c #918586",
-"%X c #908587",
-"&X c #918587",
-"*X c #928588",
-"=X c #938588",
-"-X c #96878A",
-";X c #97878B",
-":X c #918E8F",
-">X c #99888B",
-",X c #9A888B",
-"<X c #9E898D",
-"1X c #909090",
-"2X c gray57",
-"3X c #929292",
-"4X c #939393",
-"5X c #959193",
-"6X c gray58",
-"7X c #959595",
-"8X c gray59",
-"9X c #979797",
-"0X c #9D979B",
-"qX c #989898",
-"wX c gray61",
-"eX c #9F9F9F",
-"rX c #AF818B",
-"tX c #AB848B",
-"yX c #A28A8E",
-"uX c #A58B90",
-"iX c #A68C90",
-"pX c #AB8D93",
-"aX c #A19A9E",
-"sX c #B89199",
-"dX c #A39DA1",
-"fX c gray63",
-"gX c gray64",
-"hX c gray66",
-"jX c #A9A9A9",
-"kX c gray67",
-"lX c #ADACAC",
-"zX c gray68",
-"xX c #AEAEAE",
-"cX c #B5ABB1",
-"vX c #B5ABB2",
-"bX c gray69",
-"nX c #B1B1B1",
-"mX c gray70",
-"MX c #C0939C",
-"NX c #C5959F",
-"BX c #C896A0",
-"VX c #CF98A3",
-"CX c #C1B6BC",
-"ZX c #CFC1C9",
-"AX c #CACACA",
-"SX c gray80",
-"DX c #E1D0DA",
-"FX c None",
-/* pixels */
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXf FXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXm x.w FXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX#.g.f.b.x FXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXl 5.f.f.d.*.FXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXZ c.f.f.N.G FXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX*.h.f.f.e.V FXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXh 8.f.f.f.,.k FXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXA z.f.f.g.-.FXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX:.d.f.f.z.n FXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXs 9.f.f.f.0.t FXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXF l.f.f.f.<.z FXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXp >.f.f.f.s.9 FXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXg 0.f.f.f.j.M FXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX7 n.f.f.f.V.j FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXa @.f.f.f.h.=.FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXy r.f.f.f.b.S FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX8 m.f.f.f.B.c FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXi 1.f.f.f.h.&.FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXB w.f.f.f.v.D FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX0 M.f.f.f.4.h FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXu 2.f.f.f.g.;.FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXb t.f.f.f.j.N FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXq p.f.f.f.6.C FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXh 3.f.f.f.a.$.FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXr 9.f.f.f.k.M FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXT L d.f.n.%.d FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX& > , = W AXlXv 9 B FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX4 u.f.f.7.(.SXhXe FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX@ X.f.f.f.f.f.J P FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX+ +.f.f.f.f.f.f.f.5 FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXo . f.f.f.f.f.f.f.d.X FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFX2 $ q.f.f.f.f.f.f.o.FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFX* p.; | y.f.f.f.i.< FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFX3 f... O } 1 : # FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXO. .% FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFX- FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFX[ ! E E E E E ` <XMXtXI.MXMXsX$XMXMXMXMXMXMX-XcXZXZXZXZXZXcX0XZXZXZXZXZXZX:XgXjXjXjXjXjX4X' E E E E E E ~.jXjXjXjXjXjX2XFXFX",
-"FXFX[ Y I I I I I ) uXVXA.H VXVXNX*XVXVXVXVXVXVX>XCXDXDXDXDXDXCXaXDXDXDXDXDXDX:XkXmXmXmXmXmX9X_ I I I I I U !.mXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) uXVXK 6 VXVXNX*XVXVXVXVXVXVX>XCXDXDXDXDXDXCXaXDXDXDXDXDXDX:XkXmXmXmXmXmX9X_ I I I I I U !.mXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) uXVXQ.rXVXVXNX*XVXVXVXVXVXVX>XCXDXDXDXDXDXCXaXDXDXDXDXDXDX:XkXmXmXmXmXmX9X_ I I I I I U !.mXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) uXVXVXVXVXVXNX*XVXVXVXVXVXVX>XCXDXDXDXDXDXCXaXDXDXDXDXDXDX:XkXmXmXmXmXmX9X_ I I I I I U !.mXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) uXVXVXVXVXVXNX*XVXVXVXVXVXVX>XCXDXDXDXDXDXCXaXDXDXDXDXDXDX:XkXmXmXmXmXmX9X_ I I I I I U !.mXmXmXmXmXmX6XFXFX",
-"FXFX{ / ~ ~ ~ ~ ~ ] =XpXpXpXpXpXiX%XpXpXpXpXpXpX&XdXvXvXvXvXvXdX5XvXvXvXvXvXvX@XqXwXwXwXwXwX+X[ ~ ~ ~ ~ ~ ^ ~.wXwXwXwXwXwX#XFXFX",
-"FXFXFX2X2X2X2X2X2XoXK.D.D.D.D.D.G.W.,X,X,X,X,X,X[.H.D.D.D.D.D.H.J.D.D.D.D.D.D.P.1X2X2X2X2X2XXXXX2X2X2X2X2X2X/._ _ _ _ _ _ { FXFX",
-"FXFXoXbXmXmXmXmXmX8XS.f.f.f.f.f.C.U.VXVXVXVXVXVX>XZ.f.f.f.f.f.Z.F.f.f.f.f.f.f.L.kXmXmXmXmXmX9X6XmXmXmXmXmXnX/.I I I I I I ) FXFX",
-"FXFXoXbXmXmXmXmXmX8XS.f.f.f.f.f.C.U.VXVXVXVXVXVX>XZ.f.f.f.f.f.Z.F.f.f.f.f.f.f.L.kXmXmXmXmXmX9X6XmXmXmXmXmXnX/.I I I I I I ) FXFX",
-"FXFXoXbXmXmXmXmXmX8XS.f.f.f.f.f.C.U.VXVXVXVXVXVX>XZ.f.f.f.f.f.Z.F.f.f.f.f.f.f.L.kXmXmXmXmXmX9X6XmXmXmXmXmXnX/.I I I I I I ) FXFX",
-"FXFXoXbXmXmXmXmXmX8XS.f.f.f.f.f.C.U.VXVXVXVXVXVX>XZ.f.f.f.f.f.Z.F.f.f.f.f.f.f.L.kXmXmXmXmXmX9X6XmXmXmXmXmXnX/.I I I I I I ) FXFX",
-"FXFXoXbXmXmXmXmXmX8XS.f.f.f.f.f.C.U.VXVXVXVXVXVX>XZ.f.f.f.f.f.Z.F.f.f.f.f.f.f.L.kXmXmXmXmXmX9X6XmXmXmXmXmXnX/.I I I I I I ) FXFX",
-"FXFXoXbXmXmXmXmXmX8XS.f.f.f.f.f.C.U.VXVXVXVXVXVX>XZ.f.f.f.f.f.Z.F.f.f.f.f.f.f.L.kXmXmXmXmXmX9X6XmXmXmXmXmXnX/.I I I I I I ) FXFX",
-"FXFXFX^.^.^.^.^.^._.Y.T.T.T.T.T.R.].}.}.}.}.}.}.{.E.T.T.T.T.T.E.T.T.T.T.T.T.T.).^.^.^.^.^.^.~.XXoXoXoXoXoXoX'.^.^.^.^.^.^._.FXFX",
-"FXFX[ R Y Y Y Y Y _ 8XxXxXxXxXxXjX XBXBXBXBXBXBX;XeXxXxXxXxXxXeX1XxXxXxXxXxXxX`.Q Y Y Y Y Y ) 3XxXxXxXxXxXzXXXxXxXxXxXxXxX4XFXFX",
-"FXFX[ Y I I I I I ) 9XmXmXmXmXmXzXOXVXVXVXVXVXVX>XfXmXmXmXmXmXfX2XmXmXmXmXmXmX_.R I I I I I / 6XmXmXmXmXmXnXXXmXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) 9XmXmXmXmXmXzXOXVXVXVXVXVXVX>XfXmXmXmXmXmXfX2XmXmXmXmXmXmX_.R I I I I I / 6XmXmXmXmXmXnXXXmXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) 9XmXmXmXmXmXzXOXVXVXVXVXVXVX>XfXmXmXmXmXmXfX2XmXmXmXmXmXmX_.R I I I I I / 6XmXmXmXmXmXnXXXmXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) 9XmXmXmXmXmXzXOXVXVXVXVXVXVX>XfXmXmXmXmXmXfX2XmXmXmXmXmXmX_.R I I I I I / 6XmXmXmXmXmXnXXXmXmXmXmXmXmX6XFXFX",
-"FXFX[ Y I I I I I ) 9XmXmXmXmXmXzXOXVXVXVXVXVXVX>XfXmXmXmXmXmXfX2XmXmXmXmXmXmX_.R I I I I I / 6XmXmXmXmXmXnXXXmXmXmXmXmXmX6XFXFX",
-"FXFX{ ) ( ( ( ( ( { XX7X7X7X7X7X4X|.yXyXyXyXyXyX[.#X7X7X7X7X7X#XXX7X7X7X7X7X7X/._ ( ( ( ( ( { .X7X7X7X7X7X6X'.7X7X7X7X7X7XoXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX",
-"FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX"
-};
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/QmitkRadiomicsStatisticView.qrc b/Plugins/org.mitk.gui.qt.radiomics/resources/QmitkRadiomicsStatisticView.qrc
deleted file mode 100644
index d8074b5c48..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/QmitkRadiomicsStatisticView.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
- <qresource prefix="/QmitkBasicImageProcessingView">
- <file>lena.xpm</file>
- </qresource>
- </RCC>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/arithmetric-radiomics.svg b/Plugins/org.mitk.gui.qt.radiomics/resources/arithmetric-radiomics.svg
deleted file mode 100644
index 87070bf96d..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/arithmetric-radiomics.svg
+++ /dev/null
@@ -1,146 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="2048"
- height="1792"
- viewBox="0 0 2048 1792"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- sodipodi:docname="arithmetric-radiomics.svg">
- <metadata
- id="metadata10">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs8">
- <linearGradient
- id="linearGradient5601"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop5603" />
- </linearGradient>
- <linearGradient
- id="linearGradient4151"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop4153" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4151"
- id="linearGradient4155"
- x1="1051.9696"
- y1="1356.9391"
- x2="1895.7543"
- y2="1356.9391"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="2560"
- inkscape:window-height="1378"
- id="namedview6"
- showgrid="false"
- inkscape:zoom="0.52678571"
- inkscape:cx="890.37654"
- inkscape:cy="985.71689"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="svg2"
- inkscape:snap-text-baseline="true" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:1517.09448242px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- x="786.97015"
- y="1777.9902"
- id="text5737"
- sodipodi:linespacing="125%"
- transform="scale(1.0082023,0.99186441)"><tspan
- sodipodi:role="line"
- id="tspan5739"
- x="786.97015"
- y="1777.9902"
- style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">R</tspan></text>
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6383"
- width="776.4068"
- height="157.55933"
- x="98.711868"
- y="987.89832" />
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6383-5"
- width="776.4068"
- height="157.55933"
- x="-1448.3229"
- y="406.66995"
- transform="matrix(-0.00407264,-0.99999171,0.99999171,-0.00407264,0,0)" />
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6383-9"
- width="776.4068"
- height="157.55933"
- x="109.15253"
- y="1565.1526" />
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6383-9-2"
- width="776.4068"
- height="157.55933"
- x="1005.1525"
- y="257.22034" />
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6383-9-2-8"
- width="155.66103"
- height="157.55933"
- x="1320.2712"
- y="462.23727" />
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6383-9-2-8-5"
- width="155.66103"
- height="157.55933"
- x="1313.6272"
- y="44.610153" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 198.16814,69.28807 -6.89844,6.435547 0.39844,97.867193 409.17968,438.61328 128.46875,0 -0.38086,-93.67383 -419.0957,-449.24219 -111.67187,0 z"
- id="rect6383-9-2-0"
- inkscape:connector-curvature="0" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 183.49891,597.25178 6.3169,7.00724 97.85976,1.27144 445.53092,-401.63643 2.19195,-128.450042 -93.66669,-1.21748 -456.32747,411.369652 -1.90537,111.65562 z"
- id="rect6383-9-2-0-5"
- inkscape:connector-curvature="0" />
-</svg>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/bar-chart-radiomics.svg b/Plugins/org.mitk.gui.qt.radiomics/resources/bar-chart-radiomics.svg
deleted file mode 100644
index 66c02b7975..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/bar-chart-radiomics.svg
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="2048"
- height="1792"
- viewBox="0 0 2048 1792"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- sodipodi:docname="bar-chart-radiomics.svg">
- <metadata
- id="metadata10">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs8">
- <linearGradient
- id="linearGradient5601"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop5603" />
- </linearGradient>
- <linearGradient
- id="linearGradient4151"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop4153" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4151"
- id="linearGradient4155"
- x1="1051.9696"
- y1="1356.9391"
- x2="1895.7543"
- y2="1356.9391"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="2560"
- inkscape:window-height="1378"
- id="namedview6"
- showgrid="false"
- inkscape:zoom="0.52678571"
- inkscape:cx="803.1219"
- inkscape:cy="640.50505"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="svg2"
- inkscape:snap-text-baseline="true" />
- <path
- d="M640 896v512h-256v-512h256zm384-512v1024h-256v-1024h256zm1024 1152v128h-2048v-1536h128v1408h1920zm-640-896v768h-256v-768h256zm384-384v1152h-256v-1152h256z"
- id="path4"
- style="fill:#00ff00;fill-opacity:1;stroke:none" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:1517.09448242px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- x="786.97015"
- y="1777.9902"
- id="text5737"
- sodipodi:linespacing="125%"
- transform="scale(1.0082023,0.99186441)"><tspan
- sodipodi:role="line"
- id="tspan5739"
- x="786.97015"
- y="1777.9902"
- style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">R</tspan></text>
-</svg>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/lena.xpm b/Plugins/org.mitk.gui.qt.radiomics/resources/lena.xpm
deleted file mode 100644
index ccfee69bc1..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/lena.xpm
+++ /dev/null
@@ -1,255 +0,0 @@
-/* XPM */
-static char *ImageProcessing___[] = {
-/* columns rows colors chars-per-pixel */
-"48 48 201 2",
-" c #542E38",
-". c #5D2F3A",
-"X c #4A3137",
-"o c #4F3037",
-"O c #612E3A",
-"+ c #632E3D",
-"@ c #662E3C",
-"# c #6B2D3B",
-"$ c #6F2D3D",
-"% c #712D3D",
-"& c #732E3D",
-"* c #722D3E",
-"= c #73303F",
-"- c #7F2C41",
-"; c #733F4B",
-": c #753F4D",
-"> c #773F4D",
-", c #793D4B",
-"< c #7E3C4B",
-"1 c #793E4D",
-"2 c #783F4D",
-"3 c #7A3E4D",
-"4 c #7C3D4C",
-"5 c #7E3D4C",
-"6 c #7E3D4D",
-"7 c #6F414B",
-"8 c #6E424B",
-"9 c #70404B",
-"0 c #71414B",
-"q c #70414E",
-"w c #73414E",
-"e c #74404E",
-"r c #74414E",
-"t c #635E5F",
-"y c #6F5D61",
-"u c gray40",
-"i c #686868",
-"p c DimGray",
-"a c gray42",
-"s c #6F6F6F",
-"d c #796B6E",
-"f c gray44",
-"g c #717171",
-"h c #727272",
-"j c gray45",
-"k c gray46",
-"l c #767676",
-"z c #777777",
-"x c #797979",
-"c c #7C7C7C",
-"v c #7E7E7E",
-"b c #7F7F7F",
-"n c #862B41",
-"m c #802D41",
-"M c #882B41",
-"N c #8B2B42",
-"B c #8C374D",
-"V c #8F364C",
-"C c #8F374C",
-"Z c #8F374D",
-"A c #823B4B",
-"S c #833B4C",
-"D c #843A4C",
-"F c #873A4C",
-"G c #803D4D",
-"H c #89384B",
-"J c #94354B",
-"K c #95354B",
-"L c #93354C",
-"P c #92364D",
-"I c #9B324C",
-"U c #9E324C",
-"Y c #A02A46",
-"T c #A42946",
-"R c #AA2748",
-"E c #A52E4B",
-"W c #A72E4A",
-"Q c #A72F4C",
-"! c #AD2848",
-"~ c #A82D4B",
-"^ c #AB2D4C",
-"/ c #A82E4C",
-"( c #B62749",
-") c #BA274B",
-"_ c #BC264A",
-"` c #BD264B",
-"' c #BC274B",
-"] c #BE264B",
-"[ c #BF264B",
-"{ c #BE274B",
-"} c #BF274B",
-"| c #BD274C",
-" . c #B02A4B",
-".. c #B12A4B",
-"X. c #B02B4B",
-"o. c #B32B4B",
-"O. c #B5294B",
-"+. c #B7294B",
-"@. c #B52A4B",
-"#. c #B9284B",
-"$. c #B8294B",
-"%. c #B9294C",
-"&. c #A1304B",
-"*. c #A4304B",
-"=. c #A2304C",
-"-. c #B03A57",
-";. c #8D4D5C",
-":. c #995E6C",
-">. c #A74860",
-",. c #A05265",
-"<. c #A05466",
-"1. c #91646F",
-"2. c #94656F",
-"3. c #956772",
-"4. c #906971",
-"5. c #926973",
-"6. c #966C76",
-"7. c #9A6A74",
-"8. c #8E727A",
-"9. c #8C7D7E",
-"0. c #907379",
-"q. c #967179",
-"w. c #91747A",
-"e. c #97777F",
-"r. c #8F7D82",
-"t. c #927980",
-"y. c #967880",
-"u. c #808080",
-"i. c #868686",
-"p. c gray53",
-"a. c #888787",
-"s. c #888888",
-"d. c #898989",
-"f. c #8B8B8B",
-"g. c gray55",
-"h. c #8D8D8D",
-"j. c #8E8E8E",
-"k. c gray56",
-"l. c #938185",
-"z. c #938387",
-"x. c #938486",
-"c. c #948587",
-"v. c #9C8186",
-"b. c #938488",
-"n. c #928789",
-"m. c #938789",
-"M. c #94888B",
-"N. c #97888A",
-"B. c #96898B",
-"V. c #9A888A",
-"C. c #9B888C",
-"Z. c #9B8A8E",
-"A. c #9D8C90",
-"S. c #9F8C90",
-"D. c #9E8D91",
-"F. c #909090",
-"G. c gray57",
-"H. c #929292",
-"J. c #939393",
-"K. c gray59",
-"L. c #979797",
-"P. c gray60",
-"I. c #9D989B",
-"U. c #9D999B",
-"Y. c #9E9B9C",
-"T. c #B5838D",
-"R. c #A58B90",
-"E. c #A78D91",
-"W. c #A78C92",
-"Q. c #AA8C93",
-"!. c #AA8D93",
-"~. c #AD8D94",
-"^. c #B18F95",
-"/. c #B78C96",
-"(. c #B49096",
-"). c #A0A0A0",
-"_. c gray63",
-"`. c gray64",
-"'. c #A5A5A5",
-"]. c #A7A7A7",
-"[. c #AAA3A7",
-"{. c #ADA6AA",
-"}. c #A9A9A9",
-"|. c #AAAAAA",
-" X c gray67",
-".X c gray68",
-"XX c #AEAEAE",
-"oX c #B0A7AC",
-"OX c gray69",
-"+X c gray70",
-"@X c #C5959F",
-"#X c #CA96A1",
-"$X c #CF98A3",
-"%X c #C2B7BE",
-"&X c #C7BAC1",
-"*X c #CBBEC5",
-"=X c #CACACA",
-"-X c #D5C6CF",
-";X c #DBCBD4",
-":X c #E1D0DA",
-">X c None",
-/* pixels */
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XS D >X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XI [ $.>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X: X.[ O.2 >X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XF | [ W w >X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X8 U [ [ K >X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X2 o.[ ' A >X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XH { [ ..: >X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>Xq &.[ [ =.>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X1 @.[ [ V >X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XB } [ ) 6 >X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X0 *.[ [ ^ r >X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X3 +.[ [ J >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XZ ] [ #.< >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>Xe E [ [ ~ 9 >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X5 $.[ [ P >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XL [ [ %.4 >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X; ~ [ [ Q 7 >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X> #.[ [ C >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>Xt .[ / , >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X$ m = a.=Xy G >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>XY [ [ _ d d.>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X. R [ [ [ [ ( . >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X # [ [ [ [ [ T >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>XM @ [ [ [ [ ! + >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>XO ` * o N - & >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X% n >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>XX >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X",
-">X>Xf p p p p c.@X4./.@X!.R.@X@X@X@XA.-X-X-X-X%X[.-X-X-X-XI.]..X.X.X}.v p p p p k `..X.X.X.Xh.>X",
-">X>Xs u u u u z.$X;.2.$X^.Q.$X$X$X$XS.:X:X:X:X*XoX:X:X:X:XY..X+X+X+XXXc u u u u h ].+X+X+X+Xg.>X",
-">X>Xs u u u u z.$X7.T.$X^.Q.$X$X$X$XS.:X:X:X:X*XoX:X:X:X:XY..X+X+X+XXXc u u u u h ].+X+X+X+Xg.>X",
-">X>Xs u u u u z.$X$X$X$X^.Q.$X$X$X$XS.:X:X:X:X*XoX:X:X:X:XY..X+X+X+XXXc u u u u h ].+X+X+X+Xg.>X",
-">X>Xf i i i i b.#X#X#X#X~.W.#X#X#X#XD.;X;X;X;X&X{.;X;X;X;XU.|.OXOXOX Xv i i i i j '.OXOXOXOXg.>X",
-">X>Xi.s.s.s.s.9.q.q.q.q.w.n.V.V.V.V.x.e.e.e.e.y.t.e.e.e.e.r.F.k.k.k.k.s.s.s.s.s.i.u.b b b b >X>X",
-">X>X`.+X+X+X+X6.[ [ [ [ >.Q.$X$X$X$Xv.[ [ [ [ -.<.[ [ [ [ 3..X+X+X+XXXH.+X+X+X+XP.a u u u u x >X",
-">X>X`.+X+X+X+X6.[ [ [ [ >.Q.$X$X$X$Xv.[ [ [ [ -.<.[ [ [ [ 3..X+X+X+XXXH.+X+X+X+XP.a u u u u x >X",
-">X>X`.+X+X+X+X6.[ [ [ [ >.Q.$X$X$X$Xv.[ [ [ [ -.<.[ [ [ [ 3..X+X+X+XXXH.+X+X+X+XP.a u u u u x >X",
-">X>X`.+X+X+X+X6.[ [ [ [ >.Q.$X$X$X$Xv.[ [ [ [ -.<.[ [ [ [ 3..X+X+X+XXXH.+X+X+X+XP.a u u u u x >X",
-">X>XG.P.P.P.P.0.,.,.,.,.1.N.E.E.E.E.l.,.,.,.,.:.5.,.,.,.,.8.L.P.P.P.K.f.P.P.P.P.j.l h h h h >X>X",
-">X>Xk s s s s d._._._._.J.C.(.(.(.(.B._._._._.P.G._._._._.d.g s s s f s._._._._.H.P._._._._.f.>X",
-">X>Xs u u u u g.+X+X+X+X).Q.$X$X$X$XZ.+X+X+X+X].P.+X+X+X+Xf.p u u u i g.+X+X+X+XP.].+X+X+X+Xg.>X",
-">X>Xs u u u u g.+X+X+X+X).Q.$X$X$X$XZ.+X+X+X+X].P.+X+X+X+Xf.p u u u i g.+X+X+X+XP.].+X+X+X+Xg.>X",
-">X>Xs u u u u g.+X+X+X+X).Q.$X$X$X$XZ.+X+X+X+X].P.+X+X+X+Xf.p u u u i g.+X+X+X+XP.].+X+X+X+Xg.>X",
-">X>Xs u u u u g.+X+X+X+X).Q.$X$X$X$XZ.+X+X+X+X].P.+X+X+X+Xf.p u u u i g.+X+X+X+XP.].+X+X+X+Xg.>X",
-">X>Xx z z z z p.G.G.G.G.h.M.C.C.C.C.m.G.G.G.G.F.g.G.G.G.G.s.l z z z x d.G.G.G.G.h.F.G.G.G.G.>X>X",
-">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X"
-};
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/maskcleaning-radiomics.svg b/Plugins/org.mitk.gui.qt.radiomics/resources/maskcleaning-radiomics.svg
deleted file mode 100644
index 3e1cdb068d..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/maskcleaning-radiomics.svg
+++ /dev/null
@@ -1,1225 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="2048"
- height="1792"
- viewBox="0 0 2048 1792"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- sodipodi:docname="maskcleaning-radiomics.svg">
- <metadata
- id="metadata10">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs8">
- <linearGradient
- id="linearGradient5601"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop5603" />
- </linearGradient>
- <linearGradient
- id="linearGradient4151"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop4153" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4151"
- id="linearGradient4155"
- x1="1051.9696"
- y1="1356.9391"
- x2="1895.7543"
- y2="1356.9391"
- gradientUnits="userSpaceOnUse" />
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-83">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-73"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-5">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-3"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-1-9">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-2-0"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-9-9">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-2-0"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-2-7">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-8-4"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-7-1">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-8-3"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-7-8">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-44-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-81-3">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-9-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-0">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-6"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-6">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-1"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-4">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-0"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-99">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-22"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-1-7">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-2-5"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-9-5">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-2-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-2-3">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-8-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-7-6">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-8-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-3">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-3"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-62">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-4"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-80">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-08"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-80">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-97"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-1-3">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-2-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-9-1">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-2-5"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-2-1">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-8-6"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-7-61">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-8-98"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-7-07">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-44-3"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-81-4">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-9-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-6">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-9">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-0-2">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-6-8"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-6-2">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-1-4"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-3-8">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-3-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-62-8">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-4-1"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-6-1">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-9-5"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-9-6">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-9-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-0-2-2">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-6-8-5"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-6-2-9">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-1-4-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-3-8-6">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-3-9-3"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-62-8-78">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-4-1-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-6-1-0">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-9-5-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-9-6-3">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-9-2-5"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-0-2-27">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-6-8-7"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-6-2-82">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-1-4-6"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-3-8-4">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-3-9-4"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-62-8-38">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-4-1-2"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-6-1-2">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-9-5-52"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-9-6-02">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-9-2-0"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-0-2-27-2">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-6-8-7-4"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-6-2-82-1">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-1-4-6-7"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-3-8-4-0">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-3-9-4-1"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-62-8-38-4">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-4-1-2-3"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-6-1-2-2">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-9-5-52-6"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-9-6-02-0">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-9-2-0-0"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-9-3-1">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-49-3-8"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- <clipPath
- clipPathUnits="userSpaceOnUse"
- id="clipPath4829-6-2-62-84">
- <rect
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f500ff;fill-opacity:0.33000004;fill-rule:nonzero;stroke:#c95f5f;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- id="rect4831-7-7-4-9"
- width="414.28571"
- height="1908.5714"
- x="-705.71429"
- y="-259.06638" />
- </clipPath>
- </defs>
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="2560"
- inkscape:window-height="1378"
- id="namedview6"
- showgrid="false"
- inkscape:zoom="0.52678571"
- inkscape:cx="890.37654"
- inkscape:cy="989.88475"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="svg2"
- inkscape:snap-text-baseline="true" />
- <g
- transform="matrix(17.573245,0,0,16.070404,40.420706,176.0413)"
- id="g5371">
- <g
- id="g4857-7"
- transform="matrix(0.04170618,0,0,0.04170618,23.342056,90.91554)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-83)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-78" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-5)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-69"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-6-3"
- transform="matrix(0.04170618,0,0,0.04170618,35.494577,90.91554)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-1-9)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-9-1" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-9-9)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-6-1"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-14-3"
- transform="matrix(0.04170618,0,0,0.04170618,47.647104,90.91554)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-2-7)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-6-6" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-7-1)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-0-8"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-4-0"
- transform="matrix(0.04170618,0,0,0.04170618,59.799628,90.91554)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-7-8)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-0-6" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-81-3)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-3-4"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-2"
- transform="matrix(0.04170618,0,0,0.04170618,71.952155,90.91554)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-0)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-1" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-6)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-2"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-5"
- transform="matrix(0.04170618,0,0,0.04170618,23.342056,78.81404)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-4)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-63" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-99)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-2"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-6-4"
- transform="matrix(0.04170618,0,0,0.04170618,35.494577,78.81404)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-1-7)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-9-4" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-9-5)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-6-7"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-14-8"
- transform="matrix(0.04170618,0,0,0.04170618,47.647104,78.81404)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-2-3)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-6-1" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-7-6)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-0-2"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-0"
- transform="matrix(0.04170618,0,0,0.04170618,71.952155,78.81404)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-3)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-9" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-62)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-3"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-71"
- transform="matrix(0.04170618,0,0,0.04170618,23.342056,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-80)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-633" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-80)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-33"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-6-8"
- transform="matrix(0.04170618,0,0,0.04170618,35.494577,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-1-3)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-9-47" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-9-1)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-6-73"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-14-0"
- transform="matrix(0.04170618,0,0,0.04170618,47.647104,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-2-1)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-6-3" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-7-61)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-0-4"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-4-6"
- transform="matrix(0.04170618,0,0,0.04170618,59.799627,66.70724)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-7-07)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-0-60" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-81-4)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-3-7"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-5"
- transform="matrix(0.04170618,0,0,0.04170618,71.952155,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-6)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-3" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-9)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-1"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-2-2"
- transform="matrix(0.04170618,0,0,0.04170618,84.104683,90.91554)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-0-2)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-1-3" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-6-2)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-2-8"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-0-7"
- transform="matrix(0.04170618,0,0,0.04170618,84.104683,78.81404)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-3-8)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-9-1" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-62-8)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-3-7"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-5-5"
- transform="matrix(0.04170618,0,0,0.04170618,84.104683,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-6-1)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-3-4" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-9-6)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-1-7"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-2-2-0"
- transform="matrix(0.04170618,0,0,0.04170618,96.257203,90.91554)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-0-2-2)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-1-3-3" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-6-2-9)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-2-8-7"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-0-7-4"
- transform="matrix(0.04170618,0,0,0.04170618,96.257203,78.81404)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-3-8-6)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-9-1-8" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-62-8-78)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-3-7-5"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-5-5-1"
- transform="matrix(0.04170618,0,0,0.04170618,96.257203,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-6-1-0)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-3-4-5" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-9-6-3)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-1-7-8"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-2-2-4"
- transform="matrix(0.04170618,0,0,0.04170618,108.40971,90.91554)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-0-2-27)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-1-3-6" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-6-2-82)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-2-8-6"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-0-7-43"
- transform="matrix(0.04170618,0,0,0.04170618,108.40971,78.81404)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-3-8-4)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-9-1-1" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-62-8-38)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-3-7-3"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-5-5-7"
- transform="matrix(0.04170618,0,0,0.04170618,108.40971,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-6-1-2)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-3-4-4" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-9-6-02)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-1-7-4"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-2-2-4-6"
- transform="matrix(0.04170618,0,0,0.04170618,120.56227,90.91554)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-0-2-27-2)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-1-3-6-9" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-6-2-82-1)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-2-8-6-5"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-0-7-43-5"
- transform="matrix(0.04170618,0,0,0.04170618,120.56227,78.81404)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-3-8-4-0)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-9-1-1-0" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-62-8-38-4)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-3-7-3-7"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <g
- id="g4857-63-5-5-7-6"
- transform="matrix(0.04170618,0,0,0.04170618,120.56227,66.70724)">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-6-1-2-2)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-3-4-4-3" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-9-6-02-0)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-1-7-4-3"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- <path
- inkscape:connector-curvature="0"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 26.695279,97.076595 c -1.076562,-0.553267 -1.316999,-1.476936 -1.327043,-5.098006 -0.0084,-3.018757 0.172567,-4.078474 0.820213,-4.803764 l 0.463337,-0.518884 3.700298,-0.05232 c 4.312432,-0.06097 4.659845,0.01358 5.2249,1.121174 0.328645,0.644197 0.345088,0.888046 0.298094,4.420647 -0.04828,3.629124 -0.06119,3.754893 -0.439889,4.285857 -0.214583,0.300859 -0.571653,0.616023 -0.793489,0.700365 -0.627346,0.238517 -7.467389,0.191114 -7.946421,-0.05507 z"
- id="path4722" />
- <path
- inkscape:connector-curvature="0"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9ff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 26.787826,97.195415 c -0.559685,-0.178425 -1.121053,-0.946523 -1.319025,-1.804773 -0.04588,-0.198897 -0.08244,-1.706842 -0.08358,-3.446729 -0.0022,-3.426135 0.03232,-3.729184 0.510092,-4.473724 0.141189,-0.220024 0.405394,-0.498477 0.587123,-0.618784 l 0.330416,-0.218741 3.67276,-0.0256 c 3.887019,-0.0271 4.098709,-0.01068 4.584136,0.355531 0.314984,0.237627 0.73074,1.014178 0.851179,1.589834 0.123454,0.590066 0.123454,6.199485 0,6.789552 -0.120883,0.577778 -0.53724,1.353813 -0.851179,1.586486 -0.138715,0.102807 -0.378246,0.229121 -0.532291,0.280697 -0.38063,0.12744 -7.345513,0.115087 -7.749634,-0.01375 z"
- id="path4726" />
- <path
- inkscape:connector-curvature="0"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9ff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 26.849145,97.223093 c -0.590398,-0.182202 -1.119753,-0.850384 -1.338236,-1.689197 -0.187521,-0.719942 -0.187521,-6.453449 0,-7.173391 0.1637,-0.628486 0.5518,-1.231254 0.971654,-1.5091 l 0.33054,-0.218741 3.892127,0 3.892127,0 0.35728,0.250072 c 0.267077,0.186936 0.44049,0.413214 0.686864,0.896252 l 0.329584,0.646181 0,3.522031 0,3.522032 -0.329584,0.646181 c -0.246295,0.482885 -0.419844,0.709376 -0.686755,0.896253 l -0.357172,0.250071 -3.762624,0.01512 c -2.069443,0.0083 -3.863056,-0.01588 -3.985805,-0.05376 z"
- id="path4728" />
- <path
- inkscape:connector-curvature="0"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 87.423328,72.931035 c -0.364444,-0.163148 -0.743489,-0.600712 -1.004889,-1.160029 l -0.23105,-0.494376 -0.02618,-3.21344 c -0.0279,-3.424173 0.0084,-3.890248 0.356067,-4.570228 0.222763,-0.435705 0.64346,-0.862121 0.973214,-0.986443 0.375426,-0.141541 7.650456,-0.118407 7.994688,0.02542 0.364547,0.152317 0.836432,0.721542 1.062208,1.28132 0.179231,0.444376 0.186314,0.565563 0.212258,3.631958 0.02861,3.381447 -0.0081,3.849705 -0.355461,4.529029 -0.222763,0.435706 -0.64346,0.862122 -0.973214,0.986444 -0.370214,0.139577 -7.690162,0.112466 -8.007639,-0.02966 z"
- id="path5312" />
- <path
- inkscape:connector-curvature="0"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 87.423328,72.931035 c -0.364444,-0.163148 -0.743489,-0.600712 -1.004889,-1.160029 l -0.23105,-0.494376 0,-3.543024 0,-3.543025 0.23105,-0.494375 c 0.267256,-0.571846 0.64465,-1.00109 1.022841,-1.163368 0.384327,-0.164911 7.646063,-0.167122 8.040182,-0.0024 0.520089,0.217307 1.032524,0.971184 1.201254,1.767242 0.125787,0.593452 0.125707,6.279036 -8.2e-5,6.871948 -0.176634,0.832478 -0.701629,1.583746 -1.251653,1.791113 -0.370214,0.139577 -7.690162,0.112466 -8.007639,-0.02966 l -1.4e-5,0 z"
- id="path5318" />
- <path
- inkscape:connector-curvature="0"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c0c0c0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 87.464525,85.068188 c -0.30883,-0.1225 -0.732382,-0.561473 -0.947251,-0.981739 -0.347654,-0.679979 -0.383966,-1.146054 -0.356067,-4.570227 l 0.02618,-3.213441 0.23105,-0.494375 c 0.267256,-0.571846 0.64465,-1.00109 1.022841,-1.163368 0.212556,-0.09121 1.008133,-0.113769 4.011437,-0.113769 2.441233,0 3.8271,0.03046 3.97825,0.08745 0.329754,0.124322 0.750451,0.550737 0.973214,0.986443 0.347319,0.679325 0.38407,1.147583 0.355461,4.529029 -0.02594,3.066396 -0.03303,3.187582 -0.212258,3.631959 -0.225776,0.559778 -0.697661,1.129003 -1.062208,1.28132 -0.216033,0.09026 -1.025722,0.111826 -4.042401,0.107649 -2.287179,-0.0032 -3.853355,-0.03739 -3.97825,-0.08693 z"
- id="path5320" />
- <path
- inkscape:connector-curvature="0"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 63.15773,97.180388 c -0.30883,-0.1225 -0.732383,-0.561474 -0.947252,-0.981739 -0.347653,-0.679979 -0.383965,-1.146055 -0.356067,-4.570227 l 0.02618,-3.213441 0.22401,-0.478101 c 0.285907,-0.610206 0.496291,-0.876824 0.87399,-1.107598 0.302416,-0.184777 0.306753,-0.184969 4.175339,-0.184969 3.868586,0 3.872923,1.92e-4 4.175338,0.184969 0.3777,0.230774 0.588084,0.497392 0.873991,1.107598 l 0.22401,0.478101 0.02659,3.213441 c 0.02782,3.362089 -0.01064,3.894038 -0.326346,4.512862 -0.251145,0.492284 -0.713012,0.953922 -1.047292,1.04677 -0.399146,0.110866 -7.641338,0.103859 -7.922494,-0.0077 l 0,-3e-6 z"
- id="path5326" />
- <g
- id="g4857-63-0-0"
- transform="matrix(0.04170618,0,0,0.04170618,59.799628,78.81404)"
- style="fill:#ff00ff;fill-opacity:1">
- <path
- inkscape:connector-curvature="0"
- transform="matrix(0.84608119,0,0,1,-61.628007,-0.21428438)"
- clip-path="url(#clipPath4829-9-3-1)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-70-9-7" />
- <path
- inkscape:connector-curvature="0"
- clip-path="url(#clipPath4829-6-2-62-84)"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.787;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:optimizeSpeed;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m -303.56249,152.93363 -40.97322,0 -40.97321,0 -40.97322,0 -40.97321,0 -40.97322,0 c -13.65774,0 -25.47694,-6.33333 -35.45759,-19 -9.98065,-12.66667 -14.97098,-27.66667 -14.97098,-44.999997 l 0,-128 c 0,-17.333333 4.99033,-32.333333 14.97098,-45 9.98065,-12.666669 21.79985,-19.000003 35.45759,-19.000003 l 40.97322,0 40.97321,0 40.97322,0 40.97321,0 40.97322,0"
- id="path4767-7-5-3-4"
- transform="matrix(-0.84608119,0,0,1,-751.30501,-0.21428438)" />
- </g>
- </g>
- <path
- inkscape:connector-curvature="0"
- id="path7307-8"
- d="m 367.93649,949.84261 q 0,-18.13315 -14.4909,-31.38497 -14.49107,-13.25201 -34.32055,-13.25201 -19.82965,0 -34.32037,13.25201 -14.49072,13.25182 -14.49072,31.38497 0,18.13336 14.49072,31.38479 14.49072,13.2522 34.32037,13.2522 19.82965,0 34.32055,-13.2522 14.4909,-13.25143 14.4909,-31.38479 z M 859.1001,656.91305 338.95469,1132.5751 q -28.21894,25.8069 -68.64074,25.8069 -39.6593,0 -69.4036,-25.8069 l -80.84378,-75.3255 q -28.981624,-25.1077 -28.981624,-62.77 0,-36.96535 28.981624,-63.46749 L 639.44932,456.04625 q 29.7443,68.34902 87.3263,121.00809 57.58208,52.65738 132.32448,79.85871 z m 483.5366,-303.39279 q 0,27.20135 -17.5414,73.92939 -35.8457,93.4595 -125.4601,151.69575 -89.6147,58.23775 -197.152,58.23775 -141.0951,0 -241.3872,-91.71399 -100.29188,-91.71568 -100.29188,-220.74547 0,-129.0283 100.29188,-220.74396 100.2921,-91.713977 241.3872,-91.713977 44.2352,0 92.6651,11.507824 48.43,11.508194 81.9877,32.431635 12.2028,7.671449 12.2028,19.528402 0,11.856777 -12.2028,19.528203 l -223.4641,117.870713 0,156.22814 147.1965,74.6288 q 3.8134,-2.09257 60.2516,-33.8265 56.4379,-31.73394 103.3425,-56.49395 46.9046,-24.76001 53.7687,-24.76001 11.4402,0 17.9229,6.97392 6.4826,6.97561 6.4826,17.43733 z"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:1517.09448242px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- x="786.97015"
- y="1777.9902"
- id="text5737"
- sodipodi:linespacing="125%"
- transform="scale(1.0082023,0.99186441)"><tspan
- sodipodi:role="line"
- id="tspan5739"
- x="786.97015"
- y="1777.9902"
- style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">R</tspan></text>
-</svg>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/transformation-radiomics.svg b/Plugins/org.mitk.gui.qt.radiomics/resources/transformation-radiomics.svg
deleted file mode 100644
index 39a94e23a6..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/transformation-radiomics.svg
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="2048"
- height="1792"
- viewBox="0 0 2048 1792"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- sodipodi:docname="transofmration-radiomics.svg">
- <metadata
- id="metadata10">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs8">
- <linearGradient
- id="linearGradient5601"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop5603" />
- </linearGradient>
- <linearGradient
- id="linearGradient4151"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop4153" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4151"
- id="linearGradient4155"
- x1="1051.9696"
- y1="1356.9391"
- x2="1895.7543"
- y2="1356.9391"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="2560"
- inkscape:window-height="1378"
- id="namedview6"
- showgrid="false"
- inkscape:zoom="0.26339286"
- inkscape:cx="634.35459"
- inkscape:cy="1309.9221"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="svg2"
- inkscape:snap-text-baseline="true" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 68.339844 664.40625 L 68.339844 1733.1523 L 1110.5078 1733.1523 L 1110.5078 1226.3047 L 577.08398 1226.3047 L 577.08398 664.40625 L 68.339844 664.40625 z "
- id="rect6281" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 654.91602 362.20312 L 654.91602 1140.5078 L 1456 1140.5078 L 1456 673.89844 L 1110.5078 673.89844 L 1110.5078 362.20312 L 654.91602 362.20312 z "
- id="rect6302-8" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 1188.3398 148.06836 L 1188.3398 603.66016 L 1666.7109 603.66016 L 1666.7109 364.47461 L 1423.7285 364.47461 L 1423.7285 148.06836 L 1188.3398 148.06836 z "
- id="rect6302-8-0-4" />
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6302-8-0-4-1-7"
- width="280.94919"
- height="277.15259"
- x="1492.0677"
- y="20.881319" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:1517.09448242px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- x="786.97015"
- y="1777.9902"
- id="text5737"
- sodipodi:linespacing="125%"
- transform="scale(1.0082023,0.99186441)"><tspan
- sodipodi:role="line"
- id="tspan5739"
- x="786.97015"
- y="1777.9902"
- style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">R</tspan></text>
-</svg>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/resources/transofmration-radiomics.svg b/Plugins/org.mitk.gui.qt.radiomics/resources/transofmration-radiomics.svg
deleted file mode 100644
index 39a94e23a6..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/resources/transofmration-radiomics.svg
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="2048"
- height="1792"
- viewBox="0 0 2048 1792"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- sodipodi:docname="transofmration-radiomics.svg">
- <metadata
- id="metadata10">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs8">
- <linearGradient
- id="linearGradient5601"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop5603" />
- </linearGradient>
- <linearGradient
- id="linearGradient4151"
- osb:paint="solid">
- <stop
- style="stop-color:#000000;stop-opacity:1;"
- offset="0"
- id="stop4153" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4151"
- id="linearGradient4155"
- x1="1051.9696"
- y1="1356.9391"
- x2="1895.7543"
- y2="1356.9391"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="2560"
- inkscape:window-height="1378"
- id="namedview6"
- showgrid="false"
- inkscape:zoom="0.26339286"
- inkscape:cx="634.35459"
- inkscape:cy="1309.9221"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="svg2"
- inkscape:snap-text-baseline="true" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 68.339844 664.40625 L 68.339844 1733.1523 L 1110.5078 1733.1523 L 1110.5078 1226.3047 L 577.08398 1226.3047 L 577.08398 664.40625 L 68.339844 664.40625 z "
- id="rect6281" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 654.91602 362.20312 L 654.91602 1140.5078 L 1456 1140.5078 L 1456 673.89844 L 1110.5078 673.89844 L 1110.5078 362.20312 L 654.91602 362.20312 z "
- id="rect6302-8" />
- <path
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 1188.3398 148.06836 L 1188.3398 603.66016 L 1666.7109 603.66016 L 1666.7109 364.47461 L 1423.7285 364.47461 L 1423.7285 148.06836 L 1188.3398 148.06836 z "
- id="rect6302-8-0-4" />
- <rect
- style="fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.79999924;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect6302-8-0-4-1-7"
- width="280.94919"
- height="277.15259"
- x="1492.0677"
- y="20.881319" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:1517.09448242px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- x="786.97015"
- y="1777.9902"
- id="text5737"
- sodipodi:linespacing="125%"
- transform="scale(1.0082023,0.99186441)"><tspan
- sodipodi:role="line"
- id="tspan5739"
- x="786.97015"
- y="1777.9902"
- style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">R</tspan></text>
-</svg>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkGIFConfigurationPanel.cpp b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkGIFConfigurationPanel.cpp
deleted file mode 100644
index 8645205618..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkGIFConfigurationPanel.cpp
+++ /dev/null
@@ -1,212 +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 "QmitkGIFConfigurationPanel.h"
-
-
-// QT
-#include <qwidget.h>
-#include <qboxlayout.h>
-#include <qformlayout.h>
-
-#include <qpushbutton.h>
-#include <qlabel.h>
-#include <qtextedit.h>
-#include <qlineedit.h>
-#include <qspinbox.h>
-
-#include <mitkLog.h>
-
-
-mitkUI::GIFConfigurationPanel::GIFConfigurationPanel(QWidget * parent, mitk::AbstractGlobalImageFeature::Pointer calculator) :
- QWidget(parent),
- m_FeatureCalculator(calculator)
-{
- QVBoxLayout * lay = new QVBoxLayout;
-
- QHBoxLayout * checkboxLayout = new QHBoxLayout;
- m_CheckCalculateFeature = new QCheckBox;
- m_CheckCalculateFeature->setText(m_FeatureCalculator->GetFeatureClassName().c_str());
- m_ButtonShowAdditionalConfiguration = new QPushButton;
- m_ButtonShowAdditionalConfiguration->setText("+");
- m_ButtonShowAdditionalConfiguration->setMaximumWidth(30);
- m_ButtonShowAdditionalConfiguration->setCheckable(true);
-
- checkboxLayout->addWidget(m_CheckCalculateFeature);
- checkboxLayout->addWidget(m_ButtonShowAdditionalConfiguration);
- lay->addItem(checkboxLayout);
-
- QFormLayout * argumentLayout = new QFormLayout;
- QLabel * label1 = new QLabel("Use Argument");
- QLabel * label2 = new QLabel("Argument Value");
- argumentLayout->addRow(label1, label2);
-
- mitkCommandLineParser parser;
- m_FeatureCalculator->AddArguments(parser);
- std::vector < std::map<std::string, us::Any> > argumentList = parser.getArgumentList();
- for (auto argument : argumentList)
- {
- QString longarg(argument["longarg"].ToString().c_str());
- if (longarg.contains("::"))
- {
-
- QCheckBox * argumentBox = new QCheckBox;
- QWidget * secondWidget = nullptr;
- argumentBox->setText(longarg);
-
- mitkCommandLineParser::Type type = us::any_cast<mitkCommandLineParser::Type>(argument["valuetype"]);
- switch (type)
- {
- case mitkCommandLineParser::Bool:
- secondWidget = new QCheckBox;
- break;
- case mitkCommandLineParser::String:
- {
- QLineEdit* lineEdit = new QLineEdit;
- secondWidget = lineEdit;
- break;
- }
- case mitkCommandLineParser::Int:
- {
- QSpinBox* spinBox = new QSpinBox();
- spinBox->setMinimum(std::numeric_limits<int>::min());
- spinBox->setMaximum(std::numeric_limits<int>::max());
- secondWidget = spinBox;
- break;
- }
- case mitkCommandLineParser::Float:
- {
- QDoubleSpinBox* spindBox = new QDoubleSpinBox;
- spindBox->setMinimum(std::numeric_limits<double>::lowest());
- spindBox->setMaximum(std::numeric_limits<double>::max());
- secondWidget = spindBox;
- break;
- }
- default:
- secondWidget = new QLabel("unkonw type");
- }
-
- argumentLayout->addRow(argumentBox, secondWidget);
- }
- }
- if (argumentList.size() < 2)
- {
- m_ButtonShowAdditionalConfiguration->setVisible(false);
- }
- m_GroupBoxArguments = new QGroupBox;
- m_GroupBoxArguments->setTitle("");
- m_GroupBoxArguments->setLayout(argumentLayout);
- m_GroupBoxArguments->setVisible(false);
- lay->addWidget(m_GroupBoxArguments);
- //lay->addItem(argumentLayout);
-
-
- // Buttons see https://joekuan.wordpress.com/2015/09/23/list-of-qt-icons/
- // Resolution https://itk.org/Doxygen/html/classitk_1_1RecursiveMultiResolutionPyramidImageFilter.html
- // Wavelet https://code.google.com/archive/p/nwave/source/default/source
-
- this->setLayout(lay);
-
- connect((QObject*)(m_ButtonShowAdditionalConfiguration), SIGNAL(clicked(bool)), this, SLOT(OnSButtonShowAdditionalConfigurationPressed(bool)));
-}
-
-void
-mitkUI::GIFConfigurationPanel::OnSButtonShowAdditionalConfigurationPressed(bool /*status*/)
-{
- if (m_ButtonShowAdditionalConfiguration->isChecked())
- {
- m_ButtonShowAdditionalConfiguration->setText("-");
- m_GroupBoxArguments->setVisible(true);
- }
- else
- {
- m_ButtonShowAdditionalConfiguration->setText("+");
- m_GroupBoxArguments->setVisible(false);
- }
-}
-
-void
-mitkUI::GIFConfigurationPanel::CalculateFeaturesUsingParameters(const mitk::Image::Pointer & feature, const mitk::Image::Pointer &mask, std::map < std::string, us::Any> parameter, mitk::AbstractGlobalImageFeature::FeatureListType &featureList)
-{
- parameter[m_FeatureCalculator->GetLongName()] = us::Any(true);
-
- if (m_CheckCalculateFeature->isChecked())
- {
- for (int i = 0; i < m_GroupBoxArguments->layout()->count(); i+=2)
- {
- QCheckBox * argumentBox = dynamic_cast<QCheckBox* >(m_GroupBoxArguments->layout()->itemAt(i)->widget());
- if (argumentBox != nullptr)
- {
- if (argumentBox->isChecked() == false)
- {
- continue;
- }
- std::string argumentName = argumentBox->text().toStdString();
-
-
- QCheckBox * paramBool = dynamic_cast<QCheckBox*>(m_GroupBoxArguments->layout()->itemAt(i + 1)->widget());
- QLineEdit * paramText = dynamic_cast<QLineEdit*>(m_GroupBoxArguments->layout()->itemAt(i + 1)->widget());
- QSpinBox * paramInt = dynamic_cast<QSpinBox*>(m_GroupBoxArguments->layout()->itemAt(i + 1)->widget());
- QDoubleSpinBox * paramFloat = dynamic_cast<QDoubleSpinBox*>(m_GroupBoxArguments->layout()->itemAt(i + 1)->widget());
-
- if (paramBool == nullptr && paramText == nullptr && paramInt == nullptr && paramFloat == nullptr)
- {
- continue;
- }
-
- us::Any value;
- if (paramBool != nullptr)
- {
- value = us::Any(paramBool->isChecked());
- }
- if (paramText != nullptr)
- {
- value = us::Any(paramText->text().toStdString());
- }
- if (paramInt != nullptr)
- {
- value = us::Any(paramInt->value());
- }
- if (paramFloat != nullptr)
- {
- value = us::Any(float(paramFloat->value()));
- }
-
- parameter[argumentName] = value;
- MITK_INFO << argumentName << " : " << value.ToString();
- }
- }
- auto tmpPointer = m_FeatureCalculator->Clone();
- mitk::AbstractGlobalImageFeature::Pointer tmpCalc = dynamic_cast<mitk::AbstractGlobalImageFeature*>(tmpPointer.GetPointer());
- for (auto item : parameter)
- {
- MITK_INFO << item.first << " : " << item.second.ToString();
- }
- tmpCalc->SetParameters(parameter);
- bool calculateSliceWise = false;
- int slice = 0;
- if (parameter.count("slice-wise"))
- {
- slice = us::any_cast<int>(parameter["slice-wise"]);
- calculateSliceWise = true;
- }
- if (calculateSliceWise)
- {
- tmpCalc->CalculateAndAppendFeaturesSliceWise(feature, mask, slice, featureList);
- }
- else
- {
- tmpCalc->CalculateAndAppendFeatures(feature, mask, mask, featureList);
- }
- }
-}
-
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkGIFConfigurationPanel.h b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkGIFConfigurationPanel.h
deleted file mode 100644
index f2ac662d3d..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkGIFConfigurationPanel.h
+++ /dev/null
@@ -1,46 +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.
-
-============================================================================*/
-
-#ifndef QmitkGIFConfigurationPanel_h
-#define QmitkGIFConfigurationPanel_h
-
-// MITK
-#include <mitkAbstractGlobalImageFeature.h>
-
-// QT
-#include <qwidget.h>
-#include <qcheckbox.h>
-#include <qpushbutton.h>
-#include <qgroupbox.h>
-
-namespace mitkUI
-{
- class GIFConfigurationPanel : public QWidget
- {
- Q_OBJECT
- public:
- GIFConfigurationPanel(QWidget * parent, mitk::AbstractGlobalImageFeature::Pointer calculator);
- void CalculateFeaturesUsingParameters(const mitk::Image::Pointer & feature, const mitk::Image::Pointer &mask, std::map < std::string, us::Any> parameter, mitk::AbstractGlobalImageFeature::FeatureListType &featureList);
-
- protected slots:
- void OnSButtonShowAdditionalConfigurationPressed(bool status);
-
- private:
- mitk::AbstractGlobalImageFeature::Pointer m_FeatureCalculator;
-
- QCheckBox* m_CheckCalculateFeature;
- QPushButton* m_ButtonShowAdditionalConfiguration;
- QGroupBox* m_GroupBoxArguments;
- };
-}
-
-#endif
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricView.cpp b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricView.cpp
deleted file mode 100644
index f53736c078..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricView.cpp
+++ /dev/null
@@ -1,474 +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 "QmitkRadiomicsArithmetricView.h"
-
-// QT includes (GUI)
-#include <qlabel.h>
-#include <qspinbox.h>
-#include <qpushbutton.h>
-#include <qcheckbox.h>
-#include <qgroupbox.h>
-#include <qradiobutton.h>
-#include <qmessagebox.h>
-
-// Berry includes (selection service)
-#include <berryISelectionService.h>
-#include <berryIWorkbenchWindow.h>
-
-// MITK includes (GUI)
-#include <QmitkDataStorageComboBox.h>
-#include "QmitkDataNodeSelectionProvider.h"
-#include "mitkDataNodeObject.h"
-
-// MITK includes (general
-#include <mitkNodePredicateDataType.h>
-#include <mitkNodePredicateAnd.h>
-#include <mitkProperties.h>
-#include <mitkArithmeticOperation.h>
-
-// Specific GUI Includes
-#include "QmitkGIFConfigurationPanel.h"
-
-QmitkRadiomicsArithmetric::QmitkRadiomicsArithmetric()
-: QmitkAbstractView(),
- m_Controls(nullptr)
-{
-}
-
-QmitkRadiomicsArithmetric::~QmitkRadiomicsArithmetric()
-{
-
-}
-
-void QmitkRadiomicsArithmetric::CreateQtPartControl(QWidget *parent)
-{
- if (m_Controls == nullptr)
- {
- m_Controls = new Ui::QmitkRadiomicsArithmetricViewControls;
- m_Controls->setupUi(parent);
-
- QLabel * label1 = new QLabel("Image: ");
- QmitkDataStorageComboBox * cb_inputimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- m_Controls->m_InputImageGroup->layout()->addWidget(label1);
- m_Controls->m_InputImageGroup->layout()->addWidget(cb_inputimage);
-
- QLabel * label2 = new QLabel("Second Image: ");
- QmitkDataStorageComboBox * cb_inputimage2 = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- m_Controls->secondImageWidget->layout()->addWidget(label2);
- m_Controls->secondImageWidget->layout()->addWidget(cb_inputimage2);
-
- this->CreateConnections();
- }
-}
-
-void QmitkRadiomicsArithmetric::CreateConnections()
-{
- if ( m_Controls )
- {
- connect( (QObject*)(m_Controls->buttonTan), SIGNAL(clicked() ), this, SLOT(TanButton()));
- connect((QObject*)(m_Controls->buttonATan), SIGNAL(clicked()), this, SLOT(ATanButton()));
- connect((QObject*)(m_Controls->buttonCos), SIGNAL(clicked()), this, SLOT(CosButton()));
- connect((QObject*)(m_Controls->buttonACos), SIGNAL(clicked()), this, SLOT(ACosButton()));
- connect((QObject*)(m_Controls->buttonSin), SIGNAL(clicked()), this, SLOT(SinButton()));
- connect((QObject*)(m_Controls->buttonASin), SIGNAL(clicked()), this, SLOT(ASinButton()));
- connect((QObject*)(m_Controls->buttonSquare), SIGNAL(clicked()), this, SLOT(SquareButton()));
- connect((QObject*)(m_Controls->buttonSqrt), SIGNAL(clicked()), this, SLOT(SqrtButton()));
- connect((QObject*)(m_Controls->buttonAbs), SIGNAL(clicked()), this, SLOT(AbsButton()));
- connect((QObject*)(m_Controls->buttonExp), SIGNAL(clicked()), this, SLOT(ExpButton()));
- connect((QObject*)(m_Controls->buttonExpNeg), SIGNAL(clicked()), this, SLOT(ExpNegButton()));
- connect((QObject*)(m_Controls->buttonLog10), SIGNAL(clicked()), this, SLOT(Log10Button()));
-
- connect((QObject*)(m_Controls->buttonAddLeft), SIGNAL(clicked()), this, SLOT(AddLeftButton()));
- connect((QObject*)(m_Controls->buttonSubLeft), SIGNAL(clicked()), this, SLOT(SubLeftButton()));
- connect((QObject*)(m_Controls->buttonSubRight), SIGNAL(clicked()), this, SLOT(SubRightButton()));
- connect((QObject*)(m_Controls->buttonMulLeft), SIGNAL(clicked()), this, SLOT(MulLeftButton()));
- connect((QObject*)(m_Controls->buttonDivLeft), SIGNAL(clicked()), this, SLOT(DivLeftButton()));
- connect((QObject*)(m_Controls->buttonDivRight), SIGNAL(clicked()), this, SLOT(DivRightButton()));
-
- connect((QObject*)(m_Controls->buttonAdd), SIGNAL(clicked()), this, SLOT(AddButton()));
- connect((QObject*)(m_Controls->buttonSub), SIGNAL(clicked()), this, SLOT(SubButton()));
- connect((QObject*)(m_Controls->buttonMul), SIGNAL(clicked()), this, SLOT(MulButton()));
- connect((QObject*)(m_Controls->buttonDiv), SIGNAL(clicked()), this, SLOT(DivButton()));
- }
-}
-
-mitk::Image::Pointer QmitkRadiomicsArithmetric::GetFirstImage()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- std::string nodeName;
- if ((cb_image->GetSelectedNode().IsNotNull()))
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- nodeName = cb_image->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return nullptr;
- }
- if (raw_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return nullptr;
- }
-
- return raw_image;
-}
-
-mitk::Image::Pointer QmitkRadiomicsArithmetric::GetSecondImage()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->secondImageWidget->layout()->itemAt(1)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- std::string nodeName;
- if ((cb_image->GetSelectedNode().IsNotNull()))
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- nodeName = cb_image->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the second images that should be used.");
- msgBox.exec();
- return nullptr;
- }
- if (raw_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return nullptr;
- }
-
- return raw_image;
-}
-
-
-void QmitkRadiomicsArithmetric::AddImageToNode(mitk::Image::Pointer image, std::string nameAddition)
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- std::string nodeName;
- if ((cb_image->GetSelectedNode().IsNotNull()))
- {
- nodeName = cb_image->GetSelectedNode()->GetName();
- }
-
- mitk::DataNode::Pointer result = mitk::DataNode::New();
- result->SetProperty("name", mitk::StringProperty::New(nodeName + nameAddition));
- result->SetData(image);
- GetDataStorage()->Add(result, cb_image->GetSelectedNode());
-}
-
-
-void QmitkRadiomicsArithmetric::TanButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Tan(firstImage, asDouble);
- AddImageToNode(result, "::Tan");
-}
-
-void QmitkRadiomicsArithmetric::ATanButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Tan(firstImage, asDouble);
- AddImageToNode(result, "::ATan");
-}
-
-void QmitkRadiomicsArithmetric::CosButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Cos(firstImage, asDouble);
- AddImageToNode(result, "::Cos");
-}
-
-void QmitkRadiomicsArithmetric::ACosButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Acos(firstImage, asDouble);
- AddImageToNode(result, "::ACos");
-}
-
-void QmitkRadiomicsArithmetric::SinButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Sin(firstImage, asDouble);
- AddImageToNode(result, "::Sin");
-}
-
-void QmitkRadiomicsArithmetric::ASinButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Asin(firstImage, asDouble);
- AddImageToNode(result, "::ASin");
-}
-
-void QmitkRadiomicsArithmetric::SquareButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Square(firstImage, asDouble);
- AddImageToNode(result, "::Square");
-}
-
-void QmitkRadiomicsArithmetric::SqrtButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Sqrt(firstImage, asDouble);
- AddImageToNode(result, "::Sqrt");
-}
-
-void QmitkRadiomicsArithmetric::AbsButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Abs(firstImage, asDouble);
- AddImageToNode(result, "::Abs");
-}
-
-void QmitkRadiomicsArithmetric::ExpButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Exp(firstImage, asDouble);
- AddImageToNode(result, "::Exp");
-}
-
-void QmitkRadiomicsArithmetric::ExpNegButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::ExpNeg(firstImage, asDouble);
- AddImageToNode(result, "::ExpNeg");
-}
-
-void QmitkRadiomicsArithmetric::Log10Button()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Log10(firstImage, asDouble);
- AddImageToNode(result, "::Log10");
-}
-
-void QmitkRadiomicsArithmetric::AddLeftButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- double value = m_Controls->m_DoubleValue->value();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Add(firstImage, value, asDouble);
- AddImageToNode(result, "::Add");
-}
-
-void QmitkRadiomicsArithmetric::SubLeftButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- double value = m_Controls->m_DoubleValue->value();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Subtract(firstImage, value, asDouble);
- AddImageToNode(result, "::Sub");
-}
-
-void QmitkRadiomicsArithmetric::SubRightButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- double value = m_Controls->m_DoubleValue->value();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Subtract(value, firstImage, asDouble);
- AddImageToNode(result, "::Sub");
-}
-
-void QmitkRadiomicsArithmetric::MulLeftButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- double value = m_Controls->m_DoubleValue->value();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Multiply(firstImage, value, asDouble);
- AddImageToNode(result, "::Mul");
-}
-
-void QmitkRadiomicsArithmetric::DivLeftButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- double value = m_Controls->m_DoubleValue->value();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Divide(firstImage, value, asDouble);
- AddImageToNode(result, "::Div");
-}
-
-void QmitkRadiomicsArithmetric::DivRightButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- double value = m_Controls->m_DoubleValue->value();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Divide(value, firstImage,asDouble);
- AddImageToNode(result, "::Div");
-}
-
-void QmitkRadiomicsArithmetric::AddButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- mitk::Image::Pointer secondImage = GetSecondImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Add(firstImage, secondImage, asDouble);
- AddImageToNode(result, "::Add");
-}
-
-void QmitkRadiomicsArithmetric::MulButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- mitk::Image::Pointer secondImage = GetSecondImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Multiply(firstImage, secondImage, asDouble);
- AddImageToNode(result, "::Mul");
-}
-
-void QmitkRadiomicsArithmetric::SubButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- mitk::Image::Pointer secondImage = GetSecondImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Subtract(firstImage, secondImage, asDouble);
- AddImageToNode(result, "::Sub");
-}
-
-void QmitkRadiomicsArithmetric::DivButton()
-{
- mitk::Image::Pointer firstImage = GetFirstImage();
- mitk::Image::Pointer secondImage = GetSecondImage();
- bool asDouble = m_Controls->m_ResultAsDouble->isChecked();
- if (firstImage.IsNull())
- {
- return;
- }
- auto result = mitk::ArithmeticOperation::Divide(firstImage, secondImage, asDouble);
- AddImageToNode(result, "::Div");
-}
-
-void QmitkRadiomicsArithmetric::SetFocus()
-{
-}
-
-//datamanager selection changed
-void QmitkRadiomicsArithmetric::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes)
-{
- //any nodes there?
- if (!nodes.empty())
- {
-
- }
-}
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricView.h b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricView.h
deleted file mode 100644
index 4463d84a8e..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricView.h
+++ /dev/null
@@ -1,101 +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.
-
-============================================================================*/
-
-#ifndef QmitkRadiomicsArithmetricView_h
-#define QmitkRadiomicsArithmetricView_h
-
-#include <QmitkAbstractView.h>
-#include <org_mitk_gui_qt_radiomics_Export.h>
-#include "ui_QmitkRadiomicsArithmetricViewControls.h"
-
-#include "QmitkStepperAdapter.h"
-
-#include <mitkImage.h>
-#include <mitkDataStorageSelection.h>
-#include <usAny.h>
-
-
-
-class RADIOMICS_EXPORT QmitkRadiomicsArithmetric : public QmitkAbstractView
-{
- Q_OBJECT
-
-public:
-
- /*!
- \brief default constructor
- */
- QmitkRadiomicsArithmetric();
-
- /*!
- \brief default destructor
- */
- ~QmitkRadiomicsArithmetric() override;
-
- /*!
- \brief method for creating the widget containing the application controls, like sliders, buttons etc.
- */
- void CreateQtPartControl(QWidget *parent) override;
-
- void SetFocus() override;
-
- /*!
- \brief method for creating the connections of main and control widget
- */
- virtual void CreateConnections();
-
- /*!
- \brief Invoked when the DataManager selection changed
- */
- void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
-
-
- protected slots:
- void TanButton();
- void ATanButton();
- void CosButton();
- void ACosButton();
- void SinButton();
- void ASinButton();
- void SquareButton();
- void SqrtButton();
- void AbsButton();
- void ExpButton();
- void ExpNegButton();
- void Log10Button();
-
- void AddLeftButton();
- void SubLeftButton();
- void SubRightButton();
- void MulLeftButton();
- void DivLeftButton();
- void DivRightButton();
-
- void AddButton();
- void SubButton();
- void MulButton();
- void DivButton();
-
-private:
- /*!
- * controls containing sliders for scrolling through the slices
- */
- Ui::QmitkRadiomicsArithmetricViewControls *m_Controls;
-
- mitk::Image::Pointer GetFirstImage();
- mitk::Image::Pointer GetSecondImage();
- void AddImageToNode(mitk::Image::Pointer image, std::string nameAddition);
-
-
-};
-
-#endif
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricViewControls.ui b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricViewControls.ui
deleted file mode 100644
index 43f909674e..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsArithmetricViewControls.ui
+++ /dev/null
@@ -1,346 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmitkRadiomicsArithmetricViewControls</class>
- <widget class="QWidget" name="QmitkRadiomicsArithmetricViewControls">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>448</width>
- <height>980</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="m_InputImageGroup"/>
- </item>
- <item row="5" column="0">
- <widget class="QToolBox" name="toolBox">
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="currentIndex">
- <number>2</number>
- </property>
- <widget class="QWidget" name="page">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>430</width>
- <height>852</height>
- </rect>
- </property>
- <attribute name="label">
- <string>Single Image Operations</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QCommandLinkButton" name="buttonSin">
- <property name="text">
- <string>Sinus</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonASin">
- <property name="text">
- <string>A-Sinus</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonCos">
- <property name="text">
- <string>Cosinus</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonACos">
- <property name="text">
- <string>A-Cosinus</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonTan">
- <property name="text">
- <string>Tangents</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonATan">
- <property name="text">
- <string>A-Tangents</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonSquare">
- <property name="text">
- <string>Square</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonSqrt">
- <property name="text">
- <string>Square-Root</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonAbs">
- <property name="text">
- <string>Absolute Value</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonExp">
- <property name="text">
- <string>Exponential (exp)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonExpNeg">
- <property name="text">
- <string>Negative Exponential</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonLog10">
- <property name="text">
- <string>Logarithmic (Base 10)</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_4">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="page_3">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>430</width>
- <height>852</height>
- </rect>
- </property>
- <attribute name="label">
- <string>Single Image and Double Value Operation</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_6">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <item>
- <layout class="QFormLayout" name="formLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Additional Value: </string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QDoubleSpinBox" name="m_DoubleValue">
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>-1000000000000000000000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000000000000000000000.000000000000000</double>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonAddLeft">
- <property name="text">
- <string>Add (Image + Value)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonSubLeft">
- <property name="text">
- <string>Subtract (Image - Value)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonSubRight">
- <property name="text">
- <string>Subtract (Value - Image)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonMulLeft">
- <property name="text">
- <string>Multiply (Image x Value)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonDivLeft">
- <property name="text">
- <string>Divide (Image / Value)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonDivRight">
- <property name="text">
- <string>Divide (Value / Image)</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="page_2">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>430</width>
- <height>852</height>
- </rect>
- </property>
- <attribute name="label">
- <string>Two Image Operations</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <layout class="QFormLayout" name="formLayout_2"/>
- </item>
- <item>
- <widget class="QWidget" name="secondImageWidget" native="true">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>10</height>
- </size>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_9"/>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonAdd">
- <property name="text">
- <string>Add (Image + Second Image)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonSub">
- <property name="text">
- <string>Subtract (Image - Second Image)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonMul">
- <property name="text">
- <string>Multiply (Image x Second Image)</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonDiv">
- <property name="text">
- <string>Divide (Image - Second Image)</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item row="1" column="0">
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="1">
- <widget class="QCheckBox" name="m_ResultAsDouble">
- <property name="text">
- <string/>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Return result as double: </string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingView.cpp b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingView.cpp
deleted file mode 100644
index 188c09ac36..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingView.cpp
+++ /dev/null
@@ -1,201 +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 "QmitkRadiomicsMaskProcessingView.h"
-
-// QT includes (GUI)
-#include <qlabel.h>
-#include <qspinbox.h>
-#include <qpushbutton.h>
-#include <qcheckbox.h>
-#include <qgroupbox.h>
-#include <qradiobutton.h>
-#include <qmessagebox.h>
-
-// Berry includes (selection service)
-#include <berryISelectionService.h>
-#include <berryIWorkbenchWindow.h>
-
-// MITK includes (GUI)
-#include <QmitkDataStorageComboBox.h>
-#include "QmitkDataNodeSelectionProvider.h"
-#include "mitkDataNodeObject.h"
-
-// MITK includes (general
-#include <mitkNodePredicateDataType.h>
-#include <mitkNodePredicateAnd.h>
-#include <mitkProperties.h>
-#include <mitkTransformationOperation.h>
-#include <mitkLabelSetImage.h>
-
-// Specific GUI Includes
-#include <mitkMaskCleaningOperation.h>
-
-QmitkRadiomicsMaskProcessing::QmitkRadiomicsMaskProcessing()
-: QmitkAbstractView(),
- m_Controls(nullptr)
-{
-}
-
-QmitkRadiomicsMaskProcessing::~QmitkRadiomicsMaskProcessing()
-{
- //berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
- //if(s)
- // s->RemoveSelectionListener(m_SelectionListener);
-}
-
-void QmitkRadiomicsMaskProcessing::CreateQtPartControl(QWidget *parent)
-{
- if (m_Controls == nullptr)
- {
- m_Controls = new Ui::QmitkRadiomicsMaskProcessingViewControls;
- m_Controls->setupUi(parent);
-
- QLabel * label1 = new QLabel("Image: ");
- QLabel * label2 = new QLabel("Mask: ");
- QmitkDataStorageComboBox * cb_inputimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- QmitkDataStorageComboBox * cb_maskimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
- m_Controls->m_InputImageGroup->layout()->addWidget(label1);
- m_Controls->m_InputImageGroup->layout()->addWidget(cb_inputimage);
- m_Controls->m_InputImageGroup->layout()->addWidget(label2);
- m_Controls->m_InputImageGroup->layout()->addWidget(cb_maskimage);
-
- this->CreateConnections();
- }
-}
-
-void QmitkRadiomicsMaskProcessing::CreateConnections()
-{
- if ( m_Controls )
- {
- connect( (QObject*)(m_Controls->maskBasedExecutionButton), SIGNAL(clicked() ), this, SLOT(executeButtonIntervalBasedMaskClearning() ) );
- connect((QObject*)(m_Controls->outlierRemoveButton), SIGNAL(clicked()), this, SLOT(executeButtonMaskOutlierRemoval()));
- }
-}
-
-void QmitkRadiomicsMaskProcessing::executeButtonIntervalBasedMaskClearning()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(3)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
- mitk::BaseData* baseDataMaskImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- mitk::Image::Pointer mask_image;
- std::string nodeName;
-
- if ((cb_image->GetSelectedNode().IsNotNull()) && (cb_maskimage->GetSelectedNode().IsNotNull()))
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- baseDataMaskImage = (cb_maskimage->GetSelectedNode()->GetData());
- nodeName = cb_maskimage->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr) && (baseDataMaskImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- mask_image = dynamic_cast<mitk::Image *>(baseDataMaskImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
- if (raw_image.IsNull() || mask_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- bool lowerLimitOn = m_Controls->lowerOn->isChecked();
- bool upperLimitOn = m_Controls->upperOn->isChecked();
- double lowerLimit = m_Controls->lowerLimitSpinbox->value();
- double upperLimit = m_Controls->spinboxUpperValue->value();
-
-
- auto image = mitk::MaskCleaningOperation::RangeBasedMasking(raw_image, mask_image, lowerLimitOn, lowerLimit, upperLimitOn, upperLimit);
-
- mitk::LabelSetImage::Pointer labelResult = mitk::LabelSetImage::New();
- labelResult->InitializeByLabeledImage(image);
- mitk::LabelSetImage::Pointer oldLabelSet = dynamic_cast<mitk::LabelSetImage *>(mask_image.GetPointer());
- labelResult->AddLabelSetToLayer(labelResult->GetActiveLayer(), oldLabelSet->GetLabelSet());
-
- mitk::DataNode::Pointer result = mitk::DataNode::New();
- result->SetProperty("name", mitk::StringProperty::New(nodeName+"::MaskRange"));
- result->SetData(labelResult);
- GetDataStorage()->Add(result, cb_image->GetSelectedNode());
-}
-
-void QmitkRadiomicsMaskProcessing::executeButtonMaskOutlierRemoval()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(3)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
- mitk::BaseData* baseDataMaskImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- mitk::Image::Pointer mask_image;
- std::string nodeName;
-
- if ((cb_image->GetSelectedNode().IsNotNull()) && (cb_maskimage->GetSelectedNode().IsNotNull()))
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- baseDataMaskImage = (cb_maskimage->GetSelectedNode()->GetData());
- nodeName = cb_maskimage->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr) && (baseDataMaskImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- mask_image = dynamic_cast<mitk::Image *>(baseDataMaskImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
- if (raw_image.IsNull() || mask_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- auto image = mitk::MaskCleaningOperation::MaskOutlierFiltering(raw_image, mask_image);
-
- mitk::LabelSetImage::Pointer labelResult = mitk::LabelSetImage::New();
- labelResult->InitializeByLabeledImage(image);
- mitk::LabelSetImage::Pointer oldLabelSet = dynamic_cast<mitk::LabelSetImage *>(mask_image.GetPointer());
- labelResult->AddLabelSetToLayer(labelResult->GetActiveLayer(), oldLabelSet->GetLabelSet());
-
- mitk::DataNode::Pointer result = mitk::DataNode::New();
- result->SetProperty("name", mitk::StringProperty::New(nodeName + "::MaskOutlier"));
- result->SetData(labelResult);
- GetDataStorage()->Add(result, cb_image->GetSelectedNode());
-}
-
-void QmitkRadiomicsMaskProcessing::SetFocus()
-{
-}
-
-//datamanager selection changed
-void QmitkRadiomicsMaskProcessing::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes)
-{
- //any nodes there?
- if (!nodes.empty())
- {
-
- }
-}
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingView.h b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingView.h
deleted file mode 100644
index ee78e4ae2e..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingView.h
+++ /dev/null
@@ -1,91 +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.
-
-============================================================================*/
-
-#ifndef QmitkRadiomicsMaskProcessingView_h
-#define QmitkRadiomicsMaskProcessingView_h
-
-#include <QmitkAbstractView.h>
-#include <org_mitk_gui_qt_radiomics_Export.h>
-#include "ui_QmitkRadiomicsMaskProcessingViewControls.h"
-
-#include "QmitkStepperAdapter.h"
-
-#include <mitkDataStorageSelection.h>
-#include <usAny.h>
-
-/*!
-\brief This module allows to use some basic image processing filters for preprocessing, image enhancement and testing purposes
-
-Several basic ITK image processing filters, like denoising, morphological and edge detection
-are encapsulated in this module and can be selected via a list and an intuitive parameter input.
-The selected filter will be applied on the image, and a new image showing the output is displayed
-as result.
-Also, some image arithmetic operations are available.
-
-Images can be 3D or 4D.
-In the 4D case, the filters work on the 3D image selected via the
-time slider. The result is also a 3D image.
-
-\class QmitkRadiomicsMaskProcessing
-\author Tobias Schwarz
-\version 1.0 (3M3)
-\date 2009-05-10
-\ingroup Bundles
-*/
-
-class RADIOMICS_EXPORT QmitkRadiomicsMaskProcessing : public QmitkAbstractView
-{
- Q_OBJECT
-
-public:
-
- /*!
- \brief default constructor
- */
- QmitkRadiomicsMaskProcessing();
-
- /*!
- \brief default destructor
- */
- ~QmitkRadiomicsMaskProcessing() override;
-
- /*!
- \brief method for creating the widget containing the application controls, like sliders, buttons etc.
- */
- void CreateQtPartControl(QWidget *parent) override;
-
- void SetFocus() override;
-
- /*!
- \brief method for creating the connections of main and control widget
- */
- virtual void CreateConnections();
-
- /*!
- \brief Invoked when the DataManager selection changed
- */
- void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
-
-
- protected slots:
- void executeButtonIntervalBasedMaskClearning();
- void executeButtonMaskOutlierRemoval();
-
-private:
- /*!
- * controls containing sliders for scrolling through the slices
- */
- Ui::QmitkRadiomicsMaskProcessingViewControls *m_Controls;
-
-};
-
-#endif
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingViewControls.ui b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingViewControls.ui
deleted file mode 100644
index 9562c074a4..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsMaskProcessingViewControls.ui
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmitkRadiomicsMaskProcessingViewControls</class>
- <widget class="QWidget" name="QmitkRadiomicsMaskProcessingViewControls">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>448</width>
- <height>980</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="3" column="0">
- <widget class="QFrame" name="frame">
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QCheckBox" name="lowerOn">
- <property name="text">
- <string>Lower Limit:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QDoubleSpinBox" name="lowerLimitSpinbox">
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>-111111110111111104.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000000000000000000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="upperOn">
- <property name="text">
- <string>Upper Limit:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QDoubleSpinBox" name="spinboxUpperValue">
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>-111111110111111104.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000000000000000000000.000000000000000</double>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="maskBasedExecutionButton">
- <property name="text">
- <string>Clean Mask based on Intervall</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="m_InputImageGroup"/>
- </item>
- <item row="5" column="0">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="4" column="0">
- <widget class="QWidget" name="widget" native="true">
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QCommandLinkButton" name="outlierRemoveButton">
- <property name="text">
- <string>Remove outlier from Mask (Limit to μ ± 3*σ)</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticView.cpp b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticView.cpp
deleted file mode 100644
index a5846b7cec..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticView.cpp
+++ /dev/null
@@ -1,326 +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 "QmitkRadiomicsStatisticView.h"
-
-// QT includes (GUI)
-#include <qlabel.h>
-#include <qspinbox.h>
-#include <qpushbutton.h>
-#include <qcheckbox.h>
-#include <qgroupbox.h>
-#include <qradiobutton.h>
-#include <qmessagebox.h>
-#include <QApplication>
-#include <QClipboard>
-
-// Berry includes (selection service)
-#include <berryISelectionService.h>
-#include <berryIWorkbenchWindow.h>
-
-// MITK includes (GUI)
-#include <QmitkDataStorageComboBox.h>
-#include "QmitkDataNodeSelectionProvider.h"
-#include "mitkDataNodeObject.h"
-
-// MITK includes (general)
-#include "mitkLabelSetImage.h"
-#include <mitkAbstractGlobalImageFeature.h>
-#include <mitkGIFCooccurenceMatrix.h>
-#include <mitkGIFCooccurenceMatrix2.h>
-#include <mitkGIFGreyLevelRunLength.h>
-#include <mitkGIFFirstOrderStatistics.h>
-#include <mitkGIFFirstOrderHistogramStatistics.h>
-#include <mitkGIFFirstOrderNumericStatistics.h>
-#include <mitkGIFVolumetricStatistics.h>
-#include <mitkGIFVolumetricDensityStatistics.h>
-#include <mitkGIFGreyLevelSizeZone.h>
-#include <mitkGIFGreyLevelDistanceZone.h>
-#include <mitkGIFImageDescriptionFeatures.h>
-#include <mitkGIFLocalIntensity.h>
-#include <mitkGIFCurvatureStatistic.h>
-#include <mitkGIFIntensityVolumeHistogramFeatures.h>
-#include <mitkGIFNeighbourhoodGreyToneDifferenceFeatures.h>
-#include <mitkGIFNeighbouringGreyLevelDependenceFeatures.h>
-
-#include <mitkNodePredicateDataType.h>
-#include <mitkNodePredicateDimension.h>
-#include <mitkNodePredicateAnd.h>
-#include <mitkImageTimeSelector.h>
-#include <mitkProperties.h>
-#include <mitkLevelWindowProperty.h>
-#include <mitkImageStatisticsHolder.h>
-
-// Includes for image casting between ITK and MITK
-#include <mitkImageCast.h>
-#include <mitkITKImageImport.h>
-
-// Specific GUI Includes
-#include "QmitkGIFConfigurationPanel.h"
-
-QmitkRadiomicsStatistic::QmitkRadiomicsStatistic()
-: QmitkAbstractView(),
- m_Controls(nullptr)
-{
-}
-
-QmitkRadiomicsStatistic::~QmitkRadiomicsStatistic()
-{
- //berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
- //if(s)
- // s->RemoveSelectionListener(m_SelectionListener);
-}
-
-void QmitkRadiomicsStatistic::CreateQtPartControl(QWidget *parent)
-{
- if (m_Controls == nullptr)
- {
- mitk::GIFImageDescriptionFeatures::Pointer ipCalculator = mitk::GIFImageDescriptionFeatures::New(); // Commented 2, Tested
- mitk::GIFFirstOrderStatistics::Pointer firstOrderCalculator = mitk::GIFFirstOrderStatistics::New(); //Commented 2
- mitk::GIFFirstOrderHistogramStatistics::Pointer firstOrderHistoCalculator = mitk::GIFFirstOrderHistogramStatistics::New(); // Commented 2, Tested
- mitk::GIFFirstOrderNumericStatistics::Pointer firstOrderNumericCalculator = mitk::GIFFirstOrderNumericStatistics::New(); // Commented 2, Tested
- mitk::GIFVolumetricStatistics::Pointer volCalculator = mitk::GIFVolumetricStatistics::New(); // Commented 2, Tested
- mitk::GIFVolumetricDensityStatistics::Pointer voldenCalculator = mitk::GIFVolumetricDensityStatistics::New(); // Commented 2, Tested
- mitk::GIFCooccurenceMatrix::Pointer coocCalculator = mitk::GIFCooccurenceMatrix::New(); // Commented 2, Will not be tested
- mitk::GIFCooccurenceMatrix2::Pointer cooc2Calculator = mitk::GIFCooccurenceMatrix2::New(); //Commented 2
- mitk::GIFNeighbouringGreyLevelDependenceFeature::Pointer ngldCalculator = mitk::GIFNeighbouringGreyLevelDependenceFeature::New(); //Commented 2, Tested
- mitk::GIFGreyLevelRunLength::Pointer rlCalculator = mitk::GIFGreyLevelRunLength::New(); // Commented 2
- mitk::GIFGreyLevelSizeZone::Pointer glszCalculator = mitk::GIFGreyLevelSizeZone::New(); // Commented 2, Tested
- mitk::GIFGreyLevelDistanceZone::Pointer gldzCalculator = mitk::GIFGreyLevelDistanceZone::New(); //Commented 2, Tested
- mitk::GIFLocalIntensity::Pointer lociCalculator = mitk::GIFLocalIntensity::New(); //Commented 2, Tested
- mitk::GIFIntensityVolumeHistogramFeatures::Pointer ivohCalculator = mitk::GIFIntensityVolumeHistogramFeatures::New(); // Commented 2
- mitk::GIFNeighbourhoodGreyToneDifferenceFeatures::Pointer ngtdCalculator = mitk::GIFNeighbourhoodGreyToneDifferenceFeatures::New(); //Commented 2, Tested
- mitk::GIFCurvatureStatistic::Pointer curvCalculator = mitk::GIFCurvatureStatistic::New(); //Commented 2, Tested
-
- std::vector<mitk::AbstractGlobalImageFeature::Pointer> features;
- features.push_back(volCalculator.GetPointer());
- features.push_back(voldenCalculator.GetPointer());
- features.push_back(curvCalculator.GetPointer());
- features.push_back(firstOrderCalculator.GetPointer());
- features.push_back(firstOrderNumericCalculator.GetPointer());
- features.push_back(firstOrderHistoCalculator.GetPointer());
- features.push_back(ivohCalculator.GetPointer());
- features.push_back(lociCalculator.GetPointer());
- features.push_back(cooc2Calculator.GetPointer());
- features.push_back(ngldCalculator.GetPointer());
- features.push_back(rlCalculator.GetPointer());
- features.push_back(glszCalculator.GetPointer());
- features.push_back(gldzCalculator.GetPointer());
- features.push_back(ipCalculator.GetPointer());
- features.push_back(ngtdCalculator.GetPointer());
-
- m_Controls = new Ui::QmitkRadiomicsStatisticViewControls;
- m_Controls->setupUi(parent);
-
- for (auto cFeature : features)
- {
- mitkUI::GIFConfigurationPanel* gifPanel = new mitkUI::GIFConfigurationPanel(parent, cFeature);
- m_Controls->m_FeaturesGroup->layout()->addWidget(gifPanel);
- }
-
- QLabel * label1 = new QLabel("Image: ");
- QLabel * label2 = new QLabel("Mask: ");
- QmitkDataStorageComboBox * cb_inputimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- QmitkDataStorageComboBox * cb_maskimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
- m_Controls->m_InputImageGroup->layout()->addWidget(label1);
- m_Controls->m_InputImageGroup->layout()->addWidget(cb_inputimage);
- m_Controls->m_InputImageGroup->layout()->addWidget(label2);
- m_Controls->m_InputImageGroup->layout()->addWidget(cb_maskimage);
-
- this->CreateConnections();
-
- //setup predictaes for combobox
-
- mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3);
- mitk::NodePredicateDataType::Pointer imagePredicate = mitk::NodePredicateDataType::New("Image");
-
-
- }
-}
-
-void QmitkRadiomicsStatistic::CreateConnections()
-{
- if ( m_Controls )
- {
- connect( (QObject*)(m_Controls->buttonExecute), SIGNAL(clicked() ), this, SLOT(executeButtonPressed() ) );
- connect((QObject*)(m_Controls->buttonExecuteAndAppend), SIGNAL(clicked()), this, SLOT(executeAndAppendButtonPressed()));
- connect((QObject*)(m_Controls->buttonTableToClipboard), SIGNAL(clicked()), this, SLOT(copyToClipboardButtonPressed()));
- }
-}
-
-std::map < std::string, us::Any> QmitkRadiomicsStatistic::GenerateParameters()
-{
- std::map < std::string, us::Any> parameter;
-
- if (m_Controls->m_SetMinimumIntensity->isChecked())
- {
- parameter["minimum-intensity"] = us::Any(float(m_Controls->m_ParamMinimumIntensity->value()));
- }
- if (m_Controls->m_SetMaximumIntensity->isChecked())
- {
- parameter["maximum-intensity"] = us::Any(float(m_Controls->m_ParamMaximumIntensity->value()));
- }
- if (m_Controls->m_SetNumberOfBins->isChecked())
- {
- parameter["bins"] = us::Any(m_Controls->m_ParamBins->value());
- }
- if (m_Controls->m_SetBinSize->isChecked())
- {
- parameter["binsize"] = us::Any(float(m_Controls->m_ParamBinSize->value()));
- }
- if (m_Controls->m_SetIgnoreBinSize->isChecked())
- {
- parameter["ignore-mask-for-histogram"] = us::Any(m_Controls->m_ParamIgnoreMask->isChecked());
- }
- if (m_Controls->m_SetEncodeParameterInName->isChecked())
- {
- parameter["encode-parameter-in-name"] = us::Any(m_Controls->m_ParamEncodeName->isChecked());
- }
- if (m_Controls->m_SetDirectionParameter->isChecked())
- {
- parameter["direction"] = us::Any(m_Controls->m_ParamDirection->value());
- }
- if (m_Controls->m_SetSliceWiseParameter->isChecked())
- {
- parameter["slice-wise"] = us::Any(m_Controls->m_ParamSliceWise->value());
- }
-
- return parameter;
-}
-
-void QmitkRadiomicsStatistic::executeButtonPressed()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- QmitkDataStorageComboBox * cb_maskimage = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(3)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
- mitk::BaseData* baseDataMaskImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- mitk::Image::Pointer mask_image;
- QString imageName;
- QString maskName;
-
- if ((cb_image->GetSelectedNode().IsNotNull() ) && (cb_maskimage->GetSelectedNode().IsNotNull()))
- {
- imageName = cb_image->GetSelectedNode()->GetName().c_str();
- maskName = cb_maskimage->GetSelectedNode()->GetName().c_str();
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- baseDataMaskImage = (cb_maskimage->GetSelectedNode()->GetData());
- }
- if ((baseDataRawImage != nullptr) && (baseDataMaskImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- mask_image = dynamic_cast<mitk::Image *>(baseDataMaskImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
- if (raw_image.IsNull() || mask_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- mitk::AbstractGlobalImageFeature::FeatureListType stats;
- for (int i = 0; i < m_Controls->m_FeaturesGroup->layout()->count(); ++i)
- {
- auto parameter = this->GenerateParameters();
-
- mitkUI::GIFConfigurationPanel* gifPanel = dynamic_cast<mitkUI::GIFConfigurationPanel*>(m_Controls->m_FeaturesGroup->layout()->itemAt(i)->widget());
- if (gifPanel == nullptr)
- continue;
- gifPanel->CalculateFeaturesUsingParameters(raw_image, mask_image, parameter, stats);
- }
-
- m_Controls->m_ResultTable->setRowCount(stats.size());
-
- for (std::size_t i = 0; i < stats.size(); ++i)
- {
- m_Controls->m_ResultTable->setItem(i, 0, new QTableWidgetItem(imageName));
- m_Controls->m_ResultTable->setItem(i, 1, new QTableWidgetItem(maskName));
- m_Controls->m_ResultTable->setItem(i, 2, new QTableWidgetItem(stats[i].first.legacyName.c_str()));
- m_Controls->m_ResultTable->setItem(i, 3, new QTableWidgetItem(QString::number(stats[i].second)));
- }
- }
-
-void QmitkRadiomicsStatistic::executeAndAppendButtonPressed()
-{
- std::vector<QTableWidgetItem *> elementImage;
- std::vector<QTableWidgetItem *> elementMask;
- std::vector<QTableWidgetItem *> elementText;
- std::vector<QTableWidgetItem *> elementValue;
-
- for (int i = 0; i < m_Controls->m_ResultTable->rowCount(); ++i)
- {
- auto itemImage = m_Controls->m_ResultTable->item(i, 0)->clone();
- auto itemMask = m_Controls->m_ResultTable->item(i, 1)->clone();
- auto itemText = m_Controls->m_ResultTable->item(i, 2)->clone();
- auto itemValue = m_Controls->m_ResultTable->item(i, 3)->clone();
- elementImage.push_back(itemImage);
- elementMask.push_back(itemMask);
- elementText.push_back(itemText);
- elementValue.push_back(itemValue);
- }
-
- executeButtonPressed();
-
- std::size_t oldSize = m_Controls->m_ResultTable->rowCount();
- m_Controls->m_ResultTable->setRowCount(oldSize + elementText.size());
-
- for (std::size_t i = 0; i < elementText.size(); ++i)
- {
- m_Controls->m_ResultTable->setItem(i + oldSize, 0, elementImage[i]);
- m_Controls->m_ResultTable->setItem(i + oldSize, 1, elementMask[i]);
- m_Controls->m_ResultTable->setItem(i+oldSize, 2, elementText[i]);
- m_Controls->m_ResultTable->setItem(i+oldSize, 3, elementValue[i]);
- }
-}
-
-void QmitkRadiomicsStatistic::copyToClipboardButtonPressed()
-{
- QString selectedText;
- for (int i = 0; i < m_Controls->m_ResultTable->rowCount(); ++i)
- {
- auto itemImage = m_Controls->m_ResultTable->item(i, 0);
- auto itemMask = m_Controls->m_ResultTable->item(i, 1);
- auto itemText = m_Controls->m_ResultTable->item(i, 2);
- auto itemValue = m_Controls->m_ResultTable->item(i, 3);
- selectedText.append(itemImage->text());
- selectedText.append(";");
- selectedText.append(itemMask->text());
- selectedText.append(";");
- selectedText.append(itemText->text());
- selectedText.append(";");
- selectedText.append(itemValue->text());
- selectedText.append("\n");
- }
- QApplication::clipboard()->setText(selectedText);
-}
-
-void QmitkRadiomicsStatistic::SetFocus()
-{
-}
-
-//datamanager selection changed
-void QmitkRadiomicsStatistic::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes)
-{
- //any nodes there?
- if (!nodes.empty())
- {
-
- }
-}
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticView.h b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticView.h
deleted file mode 100644
index cce3ede1bb..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticView.h
+++ /dev/null
@@ -1,94 +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.
-
-============================================================================*/
-
-#ifndef QmitkRadiomicsStatisticView_h
-#define QmitkRadiomicsStatisticView_h
-
-#include <QmitkAbstractView.h>
-#include <org_mitk_gui_qt_radiomics_Export.h>
-#include "ui_QmitkRadiomicsStatisticViewControls.h"
-
-#include "QmitkStepperAdapter.h"
-
-#include <mitkDataStorageSelection.h>
-#include <usAny.h>
-
-/*!
-\brief This module allows to use some basic image processing filters for preprocessing, image enhancement and testing purposes
-
-Several basic ITK image processing filters, like denoising, morphological and edge detection
-are encapsulated in this module and can be selected via a list and an intuitive parameter input.
-The selected filter will be applied on the image, and a new image showing the output is displayed
-as result.
-Also, some image arithmetic operations are available.
-
-Images can be 3D or 4D.
-In the 4D case, the filters work on the 3D image selected via the
-time slider. The result is also a 3D image.
-
-\class QmitkRadiomicsStatistic
-\author Tobias Schwarz
-\version 1.0 (3M3)
-\date 2009-05-10
-\ingroup Bundles
-*/
-
-class RADIOMICS_EXPORT QmitkRadiomicsStatistic : public QmitkAbstractView
-{
- Q_OBJECT
-
-public:
-
- /*!
- \brief default constructor
- */
- QmitkRadiomicsStatistic();
-
- /*!
- \brief default destructor
- */
- ~QmitkRadiomicsStatistic() override;
-
- /*!
- \brief method for creating the widget containing the application controls, like sliders, buttons etc.
- */
- void CreateQtPartControl(QWidget *parent) override;
-
- void SetFocus() override;
-
- /*!
- \brief method for creating the connections of main and control widget
- */
- virtual void CreateConnections();
-
- /*!
- \brief Invoked when the DataManager selection changed
- */
- void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
-
-
- protected slots:
- void executeButtonPressed();
- void executeAndAppendButtonPressed();
- void copyToClipboardButtonPressed();
-
-private:
- std::map < std::string, us::Any> GenerateParameters();
-
- /*!
- * controls containing sliders for scrolling through the slices
- */
- Ui::QmitkRadiomicsStatisticViewControls *m_Controls;
-
-};
-
-#endif
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticViewControls.ui b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticViewControls.ui
deleted file mode 100644
index 5fad0f11ce..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsStatisticViewControls.ui
+++ /dev/null
@@ -1,363 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmitkRadiomicsStatisticViewControls</class>
- <widget class="QWidget" name="QmitkRadiomicsStatisticViewControls">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>448</width>
- <height>980</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="5" column="0">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QCommandLinkButton" name="buttonExecute">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>E&amp;xecute</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonExecuteAndAppend">
- <property name="text">
- <string>Execute &amp;&amp; Append</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="8" column="0">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Minimum</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="9" column="0">
- <widget class="QTableWidget" name="m_ResultTable">
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777209</height>
- </size>
- </property>
- <property name="rowCount">
- <number>0</number>
- </property>
- <property name="columnCount">
- <number>4</number>
- </property>
- <attribute name="horizontalHeaderCascadingSectionResizes">
- <bool>false</bool>
- </attribute>
- <column>
- <property name="text">
- <string>Image Name</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Mask Name</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Feature Name</string>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Feature Values</string>
- </property>
- </column>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QTabWidget" name="tabWidget">
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>340</height>
- </size>
- </property>
- <property name="currentIndex">
- <number>1</number>
- </property>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string> Feature Class Selection </string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QScrollArea" name="m_FeaturesGroup1">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>300</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>300</height>
- </size>
- </property>
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- <property name="sizeAdjustPolicy">
- <enum>QAbstractScrollArea::AdjustToContents</enum>
- </property>
- <property name="widgetResizable">
- <bool>true</bool>
- </property>
- <widget class="QWidget" name="m_FeaturesGroup">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>422</width>
- <height>298</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3"/>
- </widget>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="tab_2">
- <attribute name="title">
- <string> Configuration Parameter </string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <layout class="QFormLayout" name="formLayout_2">
- <property name="horizontalSpacing">
- <number>0</number>
- </property>
- <property name="verticalSpacing">
- <number>0</number>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Binning Parameter:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="m_SetMinimumIntensity">
- <property name="text">
- <string>Minimum Intensity</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QDoubleSpinBox" name="m_ParamMinimumIntensity">
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>-100000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QCheckBox" name="m_SetMaximumIntensity">
- <property name="text">
- <string>Maximum Intensity</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QDoubleSpinBox" name="m_ParamMaximumIntensity">
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>-100000.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QCheckBox" name="m_SetNumberOfBins">
- <property name="text">
- <string>Number of bins</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QSpinBox" name="m_ParamBins">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>10000</number>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QCheckBox" name="m_SetBinSize">
- <property name="text">
- <string>Bin Size</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QDoubleSpinBox" name="m_ParamBinSize">
- <property name="decimals">
- <number>6</number>
- </property>
- <property name="minimum">
- <double>0.000001000000000</double>
- </property>
- <property name="maximum">
- <double>1000000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QCheckBox" name="m_SetIgnoreBinSize">
- <property name="text">
- <string>Ignore mask for Histogram</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QCheckBox" name="m_ParamIgnoreMask">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>General Parameter</string>
- </property>
- </widget>
- </item>
- <item row="8" column="0">
- <widget class="QCheckBox" name="m_SetEncodeParameterInName">
- <property name="text">
- <string>Encode Parameter in Name</string>
- </property>
- </widget>
- </item>
- <item row="8" column="1">
- <widget class="QCheckBox" name="m_ParamEncodeName">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="9" column="0">
- <widget class="QCheckBox" name="m_SetDirectionParameter">
- <property name="text">
- <string>Direction Parameter</string>
- </property>
- </widget>
- </item>
- <item row="9" column="1">
- <widget class="QSpinBox" name="m_ParamDirection"/>
- </item>
- <item row="10" column="0">
- <widget class="QCheckBox" name="m_SetSliceWiseParameter">
- <property name="text">
- <string>Slice-wise calculation</string>
- </property>
- </widget>
- </item>
- <item row="10" column="1">
- <widget class="QSpinBox" name="m_ParamSliceWise"/>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="m_InputImageGroup"/>
- </item>
- <item row="2" column="0">
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="10" column="0">
- <widget class="QPushButton" name="buttonTableToClipboard">
- <property name="text">
- <string>Table to Clipboard</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationView.cpp b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationView.cpp
deleted file mode 100644
index c27b35f152..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationView.cpp
+++ /dev/null
@@ -1,375 +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 "QmitkRadiomicsTransformationView.h"
-
-// QT includes (GUI)
-#include <qlabel.h>
-#include <qspinbox.h>
-#include <qpushbutton.h>
-#include <qcheckbox.h>
-#include <qgroupbox.h>
-#include <qradiobutton.h>
-#include <qmessagebox.h>
-
-// Berry includes (selection service)
-#include <berryISelectionService.h>
-#include <berryIWorkbenchWindow.h>
-
-// MITK includes (GUI)
-#include <QmitkDataStorageComboBox.h>
-#include "QmitkDataNodeSelectionProvider.h"
-#include "mitkDataNodeObject.h"
-
-// MITK includes (general
-#include <mitkNodePredicateDataType.h>
-#include <mitkNodePredicateAnd.h>
-#include <mitkProperties.h>
-#include <mitkTransformationOperation.h>
-#include <mitkLabelSetImage.h>
-
-// Specific GUI Includes
-#include "QmitkGIFConfigurationPanel.h"
-
-QmitkRadiomicsTransformation::QmitkRadiomicsTransformation()
-: QmitkAbstractView(),
- m_Controls(nullptr)
-{
-}
-
-QmitkRadiomicsTransformation::~QmitkRadiomicsTransformation()
-{
- //berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService();
- //if(s)
- // s->RemoveSelectionListener(m_SelectionListener);
-}
-
-void QmitkRadiomicsTransformation::CreateQtPartControl(QWidget *parent)
-{
- if (m_Controls == nullptr)
- {
- m_Controls = new Ui::QmitkRadiomicsTransformationViewControls;
- m_Controls->setupUi(parent);
-
- QLabel * label1 = new QLabel("Image: ");
- QmitkDataStorageComboBox * cb_inputimage = new QmitkDataStorageComboBox(this->GetDataStorage(), mitk::TNodePredicateDataType<mitk::Image>::New());
- m_Controls->m_InputImageGroup->layout()->addWidget(label1);
- m_Controls->m_InputImageGroup->layout()->addWidget(cb_inputimage);
-
- this->CreateConnections();
- }
-}
-
-void QmitkRadiomicsTransformation::CreateConnections()
-{
- if ( m_Controls )
- {
- connect( (QObject*)(m_Controls->buttonExecuteMultiresolution), SIGNAL(clicked() ), this, SLOT(executeButtonMultiResolutionPressed() ) );
- connect((QObject*)(m_Controls->m_WaveletExecuteButton), SIGNAL(clicked()), this, SLOT(executeButtonWaveletPressed()));
- connect((QObject*)(m_Controls->m_ExecuteLOG), SIGNAL(clicked()), this, SLOT(executeButtonLoGPressed()));
- connect((QObject*)(m_Controls->buttonResampleImage), SIGNAL(clicked()), this, SLOT(executeButtonResamplingPressed()));
-
- }
-}
-
-void QmitkRadiomicsTransformation::executeButtonMultiResolutionPressed()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- std::string nodeName;
- if ((cb_image->GetSelectedNode().IsNotNull() ) )
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- nodeName = cb_image->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
- if (raw_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- unsigned int numberOfLevels = m_Controls->m_NumberOfLevels->value();
- bool resultAsDouble = m_Controls->m_resultAsDouble->isChecked();
-
- auto results = mitk::TransformationOperation::MultiResolution(raw_image, numberOfLevels, resultAsDouble);
- unsigned int level = 1;
- for (auto image : results)
- {
- mitk::DataNode::Pointer result = mitk::DataNode::New();
- result->SetProperty("name", mitk::StringProperty::New(nodeName+"::MultiRes::Level-"+us::Any(numberOfLevels-level).ToString()));
- result->SetData(image);
- GetDataStorage()->Add(result, cb_image->GetSelectedNode());
- ++level;
- }
-}
-
-void QmitkRadiomicsTransformation::executeButtonWaveletPressed()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- std::string nodeName;
- if ((cb_image->GetSelectedNode().IsNotNull()))
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- nodeName = cb_image->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
- if (raw_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- unsigned int numberOfLevels = m_Controls->m_WaveletNumberOfLevels->value();
- unsigned int numberOfBands = m_Controls->m_WaveletNumberOfBands->value();
- mitk::BorderCondition condition = mitk::BorderCondition::Constant;
- mitk::WaveletType waveletType = mitk::WaveletType::Held;
-
- std::string waveletStr = m_Controls->m_WaveletWavelet->currentText().toStdString();
- if (waveletStr == "Shannon")
- {
- waveletType = mitk::WaveletType::Shannon;
- }
- if (waveletStr == "Simoncelli")
- {
- waveletType = mitk::WaveletType::Simoncelli;
- }
- if (waveletStr == "Vow")
- {
- waveletType = mitk::WaveletType::Vow;
- }
- if (waveletStr == "Held")
- {
- waveletType = mitk::WaveletType::Held;
- }
-
- std::string conditionStr = m_Controls->m_WaveletBorderCondition->currentText().toStdString();
- if (conditionStr == "Constant")
- {
- condition = mitk::BorderCondition::Constant;
- }
- if (conditionStr == "Periodic")
- {
- condition = mitk::BorderCondition::Periodic;
- }
- if (conditionStr == "Zero Flux Neumann")
- {
- condition = mitk::BorderCondition::ZeroFluxNeumann;
- }
-
- auto results = mitk::TransformationOperation::WaveletForward(raw_image, numberOfLevels, numberOfBands, condition, waveletType);
- unsigned int level = 0;
- for (auto image : results)
- {
- mitk::DataNode::Pointer result = mitk::DataNode::New();
- result->SetProperty("name", mitk::StringProperty::New(nodeName + "::Wavelet::"+waveletStr+"-"+conditionStr+"::Level-" + us::Any(level).ToString()));
- result->SetData(image);
- GetDataStorage()->Add(result, cb_image->GetSelectedNode());
- ++level;
- }
-
-}
-
-
-void QmitkRadiomicsTransformation::executeButtonLoGPressed()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- std::string nodeName;
- if ((cb_image->GetSelectedNode().IsNotNull()))
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- nodeName = cb_image->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
- if (raw_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- double sigma = m_Controls->m_LoGSigma->value();
- bool resultAsDouble = m_Controls->m_LogResultAsDouble->isChecked();
-
- auto results = mitk::TransformationOperation::LaplacianOfGaussian(raw_image, sigma, resultAsDouble);
- mitk::DataNode::Pointer result = mitk::DataNode::New();
- result->SetProperty("name", mitk::StringProperty::New(nodeName + "::LoG::Sigma-" + us::Any(sigma).ToString()));
- result->SetData(results);
- GetDataStorage()->Add(result, cb_image->GetSelectedNode());
-}
-
-void QmitkRadiomicsTransformation::executeButtonResamplingPressed()
-{
- QmitkDataStorageComboBox * cb_image = dynamic_cast<QmitkDataStorageComboBox *>(m_Controls->m_InputImageGroup->layout()->itemAt(1)->widget());
- mitk::BaseData* baseDataRawImage = nullptr;
-
- mitk::Image::Pointer raw_image;
- std::string nodeName;
- if ((cb_image->GetSelectedNode().IsNotNull()))
- {
- baseDataRawImage = (cb_image->GetSelectedNode()->GetData());
- nodeName = cb_image->GetSelectedNode()->GetName();
- }
- if ((baseDataRawImage != nullptr))
- {
- raw_image = dynamic_cast<mitk::Image *>(baseDataRawImage);
- }
- else {
- QMessageBox msgBox;
- msgBox.setText("Please specify the images that shlould be used.");
- msgBox.exec();
- return;
- }
- if (raw_image.IsNull())
- {
- QMessageBox msgBox;
- msgBox.setText("Error during processing the specified images.");
- msgBox.exec();
- return;
- }
-
- mitk::ImageMappingInterpolator::Type interpolatorType;
- switch (m_Controls->comboInterpolationMode->currentIndex())
- {
- case 0:
- interpolatorType = mitk::ImageMappingInterpolator::Linear;
- break;
-
- case 1:
- interpolatorType = mitk::ImageMappingInterpolator::BSpline_3;
- break;
-
- case 2:
- interpolatorType = mitk::ImageMappingInterpolator::NearestNeighbor;
- break;
-
- case 3:
- interpolatorType = mitk::ImageMappingInterpolator::WSinc_Hamming;
- break;
-
- case 4:
- interpolatorType = mitk::ImageMappingInterpolator::WSinc_Welch;
- break;
-
- default:
- interpolatorType = mitk::ImageMappingInterpolator::Linear;
- }
-
- mitk::GridInterpolationPositionType gridPosition;
- switch (m_Controls->comboAxisAlignment->currentIndex())
- {
- case 0:
- gridPosition = mitk::GridInterpolationPositionType::OriginAligned;
- break;
-
- case 1:
- gridPosition = mitk::GridInterpolationPositionType::CenterAligned;
- break;
-
- case 2:
- gridPosition = mitk::GridInterpolationPositionType::SameSize;
- break;
-
- default:
- gridPosition = mitk::GridInterpolationPositionType::OriginAligned;
- }
-
- bool resultAsDouble = m_Controls->checkResamplingOutputAsDouble->isChecked();
- bool roundResult = m_Controls->checkResamplingRoundOutput->isChecked();
-
- mitk::Vector3D spacing;
- spacing.Fill(-1);
- if (m_Controls->checkResampleX->isChecked()) {
- spacing[0] = m_Controls->doubleSpinDimensionX->value();
- }
- if (m_Controls->checkResampleY->isChecked()) {
- spacing[1] = m_Controls->doubleSpinDimensionY->value();
- }
- if (m_Controls->checkResampleZ->isChecked()) {
- spacing[2] = m_Controls->doubleSpinDimensionZ->value();
- }
-
-
- mitk::Image::Pointer results;
- if (m_Controls->checkResampleAsMask->isChecked()) {
- results = mitk::TransformationOperation::ResampleMask(raw_image, spacing, interpolatorType, gridPosition);
- mitk::LabelSetImage::Pointer oldLabelImage = dynamic_cast<mitk::LabelSetImage *> (raw_image.GetPointer());
- if (oldLabelImage.IsNotNull())
- {
- mitk::LabelSetImage::Pointer labelResult = mitk::LabelSetImage::New();
- labelResult->InitializeByLabeledImage(results);
- labelResult->AddLabelSetToLayer(labelResult->GetActiveLayer(), oldLabelImage->GetLabelSet());
- results = dynamic_cast<mitk::Image*>(labelResult.GetPointer());
- }
- }
- else {
- results = mitk::TransformationOperation::ResampleImage(raw_image, spacing, interpolatorType, gridPosition, resultAsDouble, roundResult);
- }
- mitk::DataNode::Pointer result = mitk::DataNode::New();
- result->SetProperty("name", mitk::StringProperty::New(nodeName + "::Resampled" ));
- result->SetData(results);
- GetDataStorage()->Add(result, cb_image->GetSelectedNode());
-}
-
-void QmitkRadiomicsTransformation::SetFocus()
-{
-}
-
-//datamanager selection changed
-void QmitkRadiomicsTransformation::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes)
-{
- //any nodes there?
- if (!nodes.empty())
- {
-
- }
-}
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationView.h b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationView.h
deleted file mode 100644
index db91839d5d..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationView.h
+++ /dev/null
@@ -1,93 +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.
-
-============================================================================*/
-
-#ifndef QmitkRadiomicsTransformationView_h
-#define QmitkRadiomicsTransformationView_h
-
-#include <QmitkAbstractView.h>
-#include <org_mitk_gui_qt_radiomics_Export.h>
-#include "ui_QmitkRadiomicsTransformationViewControls.h"
-
-#include "QmitkStepperAdapter.h"
-
-#include <mitkDataStorageSelection.h>
-#include <usAny.h>
-
-/*!
-\brief This module allows to use some basic image processing filters for preprocessing, image enhancement and testing purposes
-
-Several basic ITK image processing filters, like denoising, morphological and edge detection
-are encapsulated in this module and can be selected via a list and an intuitive parameter input.
-The selected filter will be applied on the image, and a new image showing the output is displayed
-as result.
-Also, some image arithmetic operations are available.
-
-Images can be 3D or 4D.
-In the 4D case, the filters work on the 3D image selected via the
-time slider. The result is also a 3D image.
-
-\class QmitkRadiomicsTransformation
-\author Tobias Schwarz
-\version 1.0 (3M3)
-\date 2009-05-10
-\ingroup Bundles
-*/
-
-class RADIOMICS_EXPORT QmitkRadiomicsTransformation : public QmitkAbstractView
-{
- Q_OBJECT
-
-public:
-
- /*!
- \brief default constructor
- */
- QmitkRadiomicsTransformation();
-
- /*!
- \brief default destructor
- */
- ~QmitkRadiomicsTransformation() override;
-
- /*!
- \brief method for creating the widget containing the application controls, like sliders, buttons etc.
- */
- void CreateQtPartControl(QWidget *parent) override;
-
- void SetFocus() override;
-
- /*!
- \brief method for creating the connections of main and control widget
- */
- virtual void CreateConnections();
-
- /*!
- \brief Invoked when the DataManager selection changed
- */
- void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
-
-
- protected slots:
- void executeButtonMultiResolutionPressed();
- void executeButtonWaveletPressed();
- void executeButtonLoGPressed();
- void executeButtonResamplingPressed();
-
-private:
- /*!
- * controls containing sliders for scrolling through the slices
- */
- Ui::QmitkRadiomicsTransformationViewControls *m_Controls;
-
-};
-
-#endif
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationViewControls.ui b/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationViewControls.ui
deleted file mode 100644
index 4dcd715d4f..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/QmitkRadiomicsTransformationViewControls.ui
+++ /dev/null
@@ -1,506 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmitkRadiomicsTransformationViewControls</class>
- <widget class="QWidget" name="QmitkRadiomicsTransformationViewControls">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>448</width>
- <height>980</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="4" column="0">
- <widget class="QToolBox" name="toolBox">
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="page">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>430</width>
- <height>846</height>
- </rect>
- </property>
- <attribute name="label">
- <string>Multi-Resolution Pyramid</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Number of Levels: </string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QSpinBox" name="m_NumberOfLevels">
- <property name="minimum">
- <number>1</number>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Return result as double: </string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QCheckBox" name="m_resultAsDouble">
- <property name="text">
- <string/>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonExecuteMultiresolution">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Execute Multi-Resolution Pyramid</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="page_4">
- <attribute name="label">
- <string>Resample Image</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_8">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_7">
- <item>
- <layout class="QFormLayout" name="formLayout_4">
- <item row="0" column="0">
- <widget class="QCheckBox" name="checkResampleX">
- <property name="text">
- <string>Dimension X</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="checkResampleY">
- <property name="text">
- <string>Dimension Y</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QCheckBox" name="checkResampleZ">
- <property name="text">
- <string>Dimension Z</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QDoubleSpinBox" name="doubleSpinDimensionX">
- <property name="decimals">
- <number>7</number>
- </property>
- <property name="maximum">
- <double>40000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QDoubleSpinBox" name="doubleSpinDimensionY">
- <property name="decimals">
- <number>7</number>
- </property>
- <property name="maximum">
- <double>40000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QDoubleSpinBox" name="doubleSpinDimensionZ">
- <property name="decimals">
- <number>7</number>
- </property>
- <property name="maximum">
- <double>40000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Interpolation mode</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>Grid alignment method</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QComboBox" name="comboInterpolationMode">
- <item>
- <property name="text">
- <string>Linear</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>B-Spline</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Nearest Neighbour</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>WSinc Hamming</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>WSinc Welch</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QComboBox" name="comboAxisAlignment">
- <item>
- <property name="text">
- <string>Origin aligned</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Center aligned</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Same size (adapts final dimension)</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="5" column="0">
- <widget class="QCheckBox" name="checkResamplingOutputAsDouble">
- <property name="text">
- <string>Output as double</string>
- </property>
- </widget>
- </item>
- <item row="7" column="0">
- <widget class="QCheckBox" name="checkResampleAsMask">
- <property name="text">
- <string>Resample as mask</string>
- </property>
- </widget>
- </item>
- <item row="6" column="0">
- <widget class="QCheckBox" name="checkResamplingRoundOutput">
- <property name="text">
- <string>Round output</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="buttonResampleImage">
- <property name="text">
- <string>Resample Image</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_4">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="page_3">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>430</width>
- <height>846</height>
- </rect>
- </property>
- <attribute name="label">
- <string>Wavelet Transformation</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_6">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <item>
- <layout class="QFormLayout" name="formLayout_3">
- <item row="0" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Number of Levels: </string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QSpinBox" name="m_WaveletNumberOfLevels">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>20000</number>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>Number of Bands: </string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="m_WaveletNumberOfBands">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>2000</number>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>Border Condition: </string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>Wavelet: </string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QComboBox" name="m_WaveletBorderCondition">
- <item>
- <property name="text">
- <string>Constant</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Periodic</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Zero Flux Neumann</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QComboBox" name="m_WaveletWavelet">
- <item>
- <property name="text">
- <string>Shannon</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Simoncelli</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Vow</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Held</string>
- </property>
- </item>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="m_WaveletExecuteButton">
- <property name="text">
- <string>Execute Wavelet Transformation</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="page_2">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>430</width>
- <height>846</height>
- </rect>
- </property>
- <attribute name="label">
- <string>Laplacian of Gaussian</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <layout class="QFormLayout" name="formLayout_2">
- <item row="0" column="1">
- <widget class="QDoubleSpinBox" name="m_LoGSigma">
- <property name="decimals">
- <number>4</number>
- </property>
- <property name="minimum">
- <double>1.000000000000000</double>
- </property>
- <property name="maximum">
- <double>1000000000000.000000000000000</double>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Gaussian Sigma: </string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Return result as double: </string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QCheckBox" name="m_LogResultAsDouble">
- <property name="text">
- <string/>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QCommandLinkButton" name="m_ExecuteLOG">
- <property name="text">
- <string>Execute Laplacian of Gaussian</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="m_InputImageGroup"/>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/mitkBasicImageProcessingActivator.cpp b/Plugins/org.mitk.gui.qt.radiomics/src/internal/mitkBasicImageProcessingActivator.cpp
deleted file mode 100644
index 8e10d26c35..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/mitkBasicImageProcessingActivator.cpp
+++ /dev/null
@@ -1,34 +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 "mitkBasicImageProcessingActivator.h"
-#include "QmitkRadiomicsStatisticView.h"
-#include "QmitkRadiomicsTransformationView.h"
-#include "QmitkRadiomicsArithmetricView.h"
-#include "QmitkRadiomicsMaskProcessingView.h"
-
-namespace mitk {
-
-void RadiomicsStatisticActivator::start(ctkPluginContext* context)
-{
- BERRY_REGISTER_EXTENSION_CLASS(QmitkRadiomicsStatistic, context)
- BERRY_REGISTER_EXTENSION_CLASS(QmitkRadiomicsTransformation, context)
- BERRY_REGISTER_EXTENSION_CLASS(QmitkRadiomicsArithmetric, context)
- BERRY_REGISTER_EXTENSION_CLASS(QmitkRadiomicsMaskProcessing, context)
-}
-
-void RadiomicsStatisticActivator::stop(ctkPluginContext* context)
-{
- Q_UNUSED(context)
-}
-
-}
diff --git a/Plugins/org.mitk.gui.qt.radiomics/src/internal/mitkBasicImageProcessingActivator.h b/Plugins/org.mitk.gui.qt.radiomics/src/internal/mitkBasicImageProcessingActivator.h
deleted file mode 100644
index 0237b688b4..0000000000
--- a/Plugins/org.mitk.gui.qt.radiomics/src/internal/mitkBasicImageProcessingActivator.h
+++ /dev/null
@@ -1,39 +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.
-
-============================================================================*/
-
-#ifndef mitkBasicImageProcessingActivator_h
-#define mitkBasicImageProcessingActivator_h
-
-#include <ctkPluginActivator.h>
-
-namespace mitk {
-
-class RadiomicsStatisticActivator :
- public QObject, public ctkPluginActivator
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_radiomicsstatistic")
- Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_radiomicstransformation")
- Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_radiomicsarithmetric")
- Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_radiomicsmaskprocessing")
- Q_INTERFACES(ctkPluginActivator)
-
-public:
-
- void start(ctkPluginContext* context) override;
- void stop(ctkPluginContext* context) override;
-
-}; // RadiomicsStatisticActivator
-
-}
-
-#endif
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkFindSegmentationTaskDialog.png b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkFindSegmentationTaskDialog.png
new file mode 100644
index 0000000000..5a9cd7a0c2
Binary files /dev/null and b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkFindSegmentationTaskDialog.png differ
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation.dox b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation.dox
index 45613a7f55..1e18045728 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation.dox
+++ b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation.dox
@@ -1,442 +1,439 @@
/**
\page org_mitk_views_segmentation The Segmentation View
\imageMacro{segmentation-dox.svg,"Icon of the Segmentation View",2.00}
\tableofcontents
\section org_mitk_views_segmentationoverview Overview
Segmentation is the act of separating an image into foreground and background subsets by manual or automated delineation, while the foreground is defined to be part of the segmentation.
Such a segmented image subset is also called a label as it typically labels a specific region of interest.
A multilabel segmentation may contain multiple labels organized in distinct groups.
You can create multiple labels for different regions of interest contained within a single segmentation image.
Labels in the same group cannot overlap each other but labels from different groups may overlap.
The MITK <b>Segmentation Plugin</b> allows you to create multilabel segmentations of anatomical and pathological structures in medical images.
-The plugin consists of two views:
+The plugin consists of three views:
<ul>
<li> <b>Segmentation View</b>: Manual and (semi-)automatic segmentation
<li> \subpage org_mitk_views_segmentationutilities : Post-processing of segmentations
+ <li> \subpage org_mitk_views_segmentationtasklist : Optimized workflow for batches of segmentation tasks based on a user-defined task list
</ul>
In this user guide, the features of the <b>Segmentation View</b> are described.
-For an introduction to the Segmentation Utilities, refer to the respective user guide.
+For an introduction to the Segmentation Utilities or Segmentation Task List, refer to the respective user guides.
\imageMacro{QmitkSegmentationPlugin_Overview.png,"Segmentation View", 16.00}
\section org_mitk_views_segmentationtechnicalissues Image and segmentation prerequisites
-The Segmentation View has a few prerequisites regarding the segmentations and their reference image:
+The Segmentation View has a few prerequisites regarding segmentations and their reference image:
<ul>
<li> Images must be two or three-dimensional and may be either static or dynamic, e.g., are time-resolved resp. have different pixel values for different time steps.
<li> Images must be single-valued, i.e. CT, MRI or ultrasound. Images from color doppler or photographic (RGB) images are only partially supported (please be aware that some tools might not be compatible with this image type).
<li> Segmentations must be congruent to their reference images.
</ul>
\section org_mitk_views_segmentationdataselection Image selection and creating new segmentations
To select a reference image for a new segmentation, click on the <i>Image</i> widget in the Data selection section at the very top of the Segmentation View.
Choose an image from the displayed list of Data Manager images.
Once an image is selected, a new segmentation for this reference image can be created by clicking the button right next to the <i>Segmentation</i> widget in the Data selection section.
A new multilabel segmentation with an initial, empty label is automatically generated if not set otherwise in the preferences.
-The new segmentation will be added to the Data Manager as child node of its reference image node.
-It is automatically selected edit can be edited in the Segmentation View right away.
+The new segmentation will be added to the Data Manager as a child node of its reference image node.
+It is automatically selected and can be edited in the Segmentation View right away.
+
Instead of creating a new segmentation, an existing segmentation can be selected and edited as well.
The selection list of existing segmentations for a certain reference image consists of matching/congruent segmentations only.
\imageMacro{"QmitkSegmentation_DataSelection.png","Data selection and creating new segmentations",12}
\section org_mitk_views_segmentationgroups Groups
Segmentation images consist of at least a single group called "Group 0" in which the first default label is created.
More groups can be added and removed but there will always be at least a single group.
Labels of the same group cannot overlap each other.
Labels of different groups may overlap each other.
For example, you could segment the whole heart as "Heart" label in "Group 0", add "Group 1" and create multiple labels of the anatomical details of the heart in that group.
Naturally, all these labels lie within the extents of the "Heart" label of "Group 0" but in principle they are completely independent of "Group 0".
Some pixels are now labelled twice, e.g., as "Heart" and "Left ventricle".
Since the labels of "Group 1" cannot overlap each other, it is impossible to accidentally label a pixel as both "Left ventricle" and "Right ventricle".
If you would like to segment even more details you could create "Group 2" to have up to three labels per pixel.
Nevertheless, groups are technically a flat data structure and cannot contain nested groups.
It is all about possibly overlapping labels from distinct groups and spatially exclusive, non-overlapping labels within the same group.
\imageMacro{"QmitkSegmentation_Groups.png","Groups",10}
-\section org_mitk_views_segmentationlabelinstances Label instances
+\section org_mitk_views_segmentationlabelinstances Labels vs. label instances
-The Segmentation View also supports label instances.
+The Segmentation View supports label instances.
That is, segmenting multiple distributed entities of the same thing like metastases for example.
-A label is already a single instance of itself but for the sake of clearness it is only shown explicitly as such as soon as there are multiple instances of the same label (also refered to as label class).
-Technically all label instances have their own distinct label/pixel value that is explicitly shown in square brackets as a clue for distinction and identification.
-It is important to understand that this number is not a classic index starting at zero for each label class. It is just the plain label/pixel value of the label instance, which is unique across all labels of the whole segmentation.
+A label, as we used the term before, is already a single instance of itself but it may consist of multiple label instances.
+
+If a label consists of multiple label instances, they each show their own distinct pixel value in square brackets as a clue for distinction and identification.
+
+It is important to understand that this number is not a separate, consequtive index for each label.
+It is just the plain pixel value of the label instance, which is unique across all label instances of the whole segmentation.
\imageMacro{"QmitkSegmentation_LabelInstances.png","Label instances",10}
-\section org_mitk_views_segmentationlock_color_visibility Unlocking, changing color of, and hiding labels
+\section org_mitk_views_segmentationlock_color_visibility Unlocking, changing color of, and hiding label instances
-Labels (and label instances) are locked by default: labels from the same group cannot accidentally override pixels from other labels.
-Locked labels behave like cookie cutters for other labels of the same group.
-You can unlock labels to remove that protection from other labels of the same group.
-Their pixel contents can then be overridden by other labels of the same group.
+Label instances are locked by default: label instances from the same group cannot accidentally override pixels from other label instances.
+Locked label instances behave like cookie cutters for other label instances of the same group.
+You can unlock label instances to remove that protection from other label instances of the same group.
+Their pixel contents can then be overridden by other label instances of the same group.
-Remember that labels from distinct groups do not interact with each other.
+Remember that label instances from distinct groups do not interact with each other.
They can always overlap (not override) each other.
-You can also change the color of labels and label instances as well as show (default) or hide their pixel contents.
+You can also change the color of label instances as well as show (default) or hide their pixel contents.
The icons at the right side of the rows of the groups and labels widget reflect their state in all these regards.
-Renaming of labels can be found in their content menu as shown further below.
+Renaming of labels and label instances can be found in their content menu as shown further below.
-\imageMacro{"QmitkSegmentation_LockColorVisibility.png","Unlocking\, changing color of\, and hiding labels",10}
+\imageMacro{"QmitkSegmentation_LockColorVisibility.png","Unlocking\, changing color of\, and hiding label instances",10}
\section org_mitk_views_segmentationcontextmenus Context menus
Actions for organization of groups, labels, and label instances (as well as other operations) can be also found in their right-click context menus.
\imageMacro{"QmitkSegmentation_ContextMenus.png","Context menus of groups\, labels\, and label instances",12}
Most actions available in these context menus are self-explanatory or were already described above by other means of access like the tool button bar for adding and removing groups, labels, and label instances.
Labels and label instances can be <b>renamed</b>, while groups have fixed names.
-This may change in future releases of MITK.
+Note that renaming a label instance will make a separate label out of it, since all instances of the same label share a single common name.
-<b>Clear content</b> only clears the pixels of a label or label instance but won't delete the actual label or label instance.
+<b>Clear content</b> only clears the pixels of a label instance but won't delete the actual label instance.
-Groups can be <b>locked</b> and <b>unlocked</b> as a whole from their context menu, while labels and label instances can be directly locked and unlocked outside the context menu as decribed further below.
+Groups can be <b>locked</b> and <b>unlocked</b> as a whole from their context menu, while label instances can be directly locked and unlocked outside the context menu as decribed further below.
\section org_mitk_views_segmentationlabelsuggestions Label name and color suggestions
-When renaming labels or creating new labels with enforced manual naming in the Segmentation preferences, entering names is supported by auto-completion for common label names.
+When renaming label instances or creating new label instances with enforced manual naming in the Segmentation preferences, entering names is supported by auto-completion for common label names.
The list of predefined label names and colors for the auto-completion feature can be either extented or replaced by a custom list of label name and color suggestions.
This custom list must be specified as a JSON file, just containing an array of objects, each with a mandatory "name" string and an optional "color" string.
The JSON file can be set in the Segmentation preferences as well as a few options on how to apply these suggestions.
\section org_mitk_views_segmentationlabelpresets Saving and loading label set presets
Label set presets are useful to share a certain style or scheme between different segmentation sessions or to provide templates for new segmentation sessions.
-The properties of all labels in all groups like their names, colors, and visibilities are saved as a label set preset by clicking on the 'Save label set preset' button.
+The properties of all label instances in all groups like their names, colors, and visibilities are saved as a label set preset by clicking on the 'Save label set preset' button.
Label set presets are applied to any segmentation session by clicking on the 'Load label set preset' button.
-If a label for a certain value already exists, its properties are overridden by the preset.
-If a label for a certain value does not yet exist, an empty label with the label properties of the preset is created.
-The actual segmentations of labels are unaffected as label set presets only store label properties.
+If a label instance for a certain value already exists, its properties are overridden by the preset.
+If a label instance for a certain value does not yet exist, an empty label instance with the label properties of the preset is created.
+The actual pixel contents of label instances are unaffected as label set presets only store label properties.
\imageMacro{QmitkSegmentation_Preset.png,"Saving and loading label set presets", 10.00}
\subsection org_mitk_views_segmentationdefaultlabelpresets Applying label set presets by default
If you work on a repetetive segmentation task, manually loading the same label set preset for each and every new segmentation can be tedious.
-To streamline your workflow, you can set a default label set preset in the Segmentation preferences (Ctrl+P). When set, this label set preset will be applied to all new segmentations instead of creating the default red "Label 1" label.
+To streamline your workflow, you can set a default label set preset in the Segmentation preferences (Ctrl+P). When set, this label set preset will be applied to all new segmentations instead of creating the default red "Label 1" label instance.
\section org_mitk_views_segmentationpreferences Preferences
The Segmentation Plugin offers a number of preferences which can be set via the MITK Workbench application preferences (Ctrl+P):
\imageMacro{QmitkSegmentationPreferences.png,"Segmentation preferences", 10.00}
<ul>
<li> <b>Compact view:</b> Hide the tool button texts to save some space on screen (6 instead of 4 buttons per row)
<li> <b>2D display:</b> Draw segmentations as as outlines or transparent overlays
<li> <b>Data node selection mode:</b> Hide everything but the selected segmentation and its reference image
<li> <b>Default label set preset:</b> Start a new segmentation with this preset instead of a default label
- <li> <b>Label creation:</b> Assign default names and colors to new labels or ask users for name and color
+ <li> <b>Label creation:</b> Assign default names and colors to new label instances or ask users for name and color
<li> <b>Label suggestions:</b> Specify custom suggestions for label names and colors
</ul>
\section org_mitk_views_segmentationtooloverview Segmentation tool overview
MITK offers a comprehensive set of slice-based 2D and (semi-)automated 3D segmentation tools.
The manual 2D tools require some user interaction and can only be applied to a single image slice whereas the 3D tools operate on the whole image.
The 3D tools usually only require a small amount of user interaction, i.e. placing seed points or setting / adjusting parameters.
You can switch between the different toolsets by selecting the 2D or 3D tab in the segmentation view.
\imageMacro{QmitkSegmentation_ToolOverview.png,"An overview of the existing 2D and 3D tools in MITK.",5.50}
\section org_mitk_views_segmentation2dsegmentation 2D segmentation tools
With 2D manual contouring you define which voxels are part of the segmentation and which are not. This allows you to create segmentations of any structures of interest in an image.
You can also use manual contouring to correct segmentations that result from sub-optimal automatic methods.
The drawback of manual contouring is that you might need to define contours on many 2D slices. However, this is mitigated by the interpolation feature, which will make suggestions for a segmentation.
To start using one of the editing tools, click its button from the displayed toolbox.
The selected editing tool will be active and its corresponding button will stay pressed until you click the button again.
Selecting a different tool also deactivates the previous one.\n
If you have to delineate a lot of images, shortcuts to switch between tools becomes convenient.
For that, just hit the first letter of each tool to activate it (A for Add, S for Subtract, etc.).
All of the editing tools work by the same principle: using the mouse (left button) to click anywhere in a 2D window (any of the orientations axial, sagittal, or coronal),
moving the mouse while holding the mouse button and releasing the button to finish the editing action.
Multi-step undo and redo is fully supported by all editing tools by using the application-wide undo / redo buttons in the toolbar.
<i>Remark</i>: Clicking and moving the mouse in any of the 2D render windows will move the crosshair that defines what part of the image is displayed.
This behavior is disabled as long as any of the manual segmentation tools are active - otherwise you might have a hard time concentrating on the contour you are drawing.
\subsection org_mitk_views_segmentationaddsubtracttools Add and subtract tools
\imageMacro{QmitkSegmentation_IMGIconAddSubtract.png,"Add and subtract tools",7.70}
Use the left mouse button to draw a closed contour. When releasing the mouse button, the contour will be added (Add tool) to or removed (Subtract tool) from the current segmentation.
Adding and subtracting voxels can be iteratively repeated for the same segmentation. Holding CTRL / CMD while drawing will invert the current tool's behavior (i.e. instead of adding voxels, they will be subtracted).
\subsection org_mitk_views_segmentationlassotool Lasso tool
\imageMacro{QmitkSegmentation_Lasso.png,"Lasso tool",7.70}
The tool is a more advanced version of the add/subtract tool. It offers you the following features:
<ol>
<li> Generating a polygon segmentation (click left mouse button to set ancor point)
<li> Freehand contouring (like the add tool; press left mouse button while moving the mouse)
<li> Move ancor points (select an ancor point, press left mouse button while moving the mouse)
<li> Add new ancor points (press CTRL while click left mouse to add an ancor to the contour)
<li> Delete an ancor point (press Del while ancor point is selected)
<li> Segmentation can be added to the label (Add mode) or subtracted (Subtract mode)
</ol>
To start a segmentation double left click where the first ancor point should be. To end the segmentation double left click where the last ancor point should be.
Please note that:
<ul>
<li> feature 3-6 are only available, if auto confirm is *not* activated
<li> feature 3-5 is not available for freehand contour segments
</ul>
\subsection org_mitk_views_segmentationpaintwipetools Paint and wipe tools
\imageMacro{QmitkSegmentation_IMGIconPaintWipe.png,"Paint and wipe tools",7.68}
Use the <i>Size</i> slider to change the radius of the round paintbrush tool. Move the mouse in any 2D window and press the left button to draw or erase pixels.
Holding CTRL / CMD while drawing will invert the current tool's behavior (i.e. instead of painting voxels, they will be wiped).
\subsection org_mitk_views_segmentationregiongrowingtool Region growing tool
\imageMacro{QmitkSegmentation_IMGIconRegionGrowing.png,"Region growing tool",3.81}
Click at one point in a 2D slice widget to add an image region to the segmentation with the region growing tool.
Region Growing selects all pixels around the mouse cursor that have a similar gray value as the pixel below the mouse cursor.
This allows to quickly create segmentations of structures that have a good contrast to surrounding tissue.
The tool operates based on the current level window, so changing the level window to optimize the contrast for the ROI is encouraged.
Moving the mouse up / down is different from left / right:
Moving up the cursor while holding the left mouse button widens the range for the included grey values; moving it down narrows it.
Moving the mouse left and right will shift the range.
The tool will select more or less pixels, corresponding to the changing gray value range.
\if THISISNOTIMPLEMENTEDATTHEMOMENT
A common issue with region growing is the so called "leakage" which happens when the structure of interest is connected to other pixels, of similar gray values, through a narrow "bridge" at the border of the structure.
The Region Growing tool comes with a "leakage detection/removal" feature. If leakage happens, you can left-click into the leakage region and the tool will try to automatically remove this region (see illustration below).
\imageMacro{QmitkSegmentation_Leakage.png,"Leakage correction feature of the region growing tool",11.28}
\endif
\subsection org_mitk_views_segmentationfilltool Fill tool
\imageMacro{QmitkSegmentation_IMGIconFill.png,"Fill tool",3.81}
Left-click inside a region/segmentation to flood fill all connected pixels that have the same label with the active label. This tool will only work on regions of unlocked labels or on regions that are not labeled at all.
\subsection org_mitk_views_segmentationerasetool Erase tool
\imageMacro{QmitkSegmentation_IMGIconErase.png,"Erase tool",3.79}
This tool removes a connected part of pixels that form a segmentation.
You may use it to remove single segmented regions (left-click on specific segmentation) or to clear a whole slice at once (left-click at the non-labeled background).
This tool will only work and regions of unlocked labels or on regions of the active label.
\subsection org_mitk_views_segmentationclosetool Close tool
\imageMacro{QmitkSegmentation_IMGIconClose.png,"Close tool",3.79}
Left-click inside the region/segmentation to fill all "holes" (pixels labelled with another label or no label) inside the region.
Therefore this tool behaves like a local closing operation. This tool will not work, when a non-labeled region is selected and holes of locked labels will not be filled.
\remark This tool always uses the label of the selected region (even if this label is not the active label). Therefore you can use this tool on regions of the active label and of none locked labels (without the need to change the active label).
\subsection org_mitk_views_segmentationlivewiretool Live wire tool
\imageMacro{QmitkSegmentation_IMGIconLiveWire.png,"Live wire tool",3.01}
The Live Wire Tool acts as a magnetic lasso with a contour snapping to edges of objects.
\imageMacro{QmitkSegmentation_IMGLiveWireUsage.PNG,"Steps for using the Live Wire Tool",16.00}
The tool handling is the same like the Lasso tool (see for more info), except it generates live wire contours instead of straight lines.
\subsection org_mitk_views_segmentationinterpolation 2D and 3D Interpolation
Creating segmentations using 2D manual contouring for large image volumes may be very time-consuming, because structures of interest may cover a large range of slices.
-Note: Interpolation is currently disabled for segmentations containing more than one label.
The segmentation view offers two helpful features to mitigate this drawback:
<ul>
<li> 2D Interpolation
<li> 3D Interpolation
</ul>
The <b>2D Interpolation</b> creates suggestions for a segmentation whenever you have a slice that
<ul>
<li> has got neighboring slices with segmentations (these do not need to be direct neighbors but could also be a couple of slices away) AND
<li> is completely clear of a manual segmentation, i.e. there will be no suggestion if there is even only a single pixel of segmentation in the current slice.
</ul>
\imageMacro{QmitkSegmentation_2DInterpolation.png,"2D interpolation usage",3.01}
Interpolated suggestions are displayed as outlines, until you confirm them as part of the segmentation.
To confirm single slices, click the <i>Confirm for single slice</i> button below the toolbox. You may also review the interpolations visually and then accept all of them at once by selecting <i>Confirm for all slices</i>.
The <b>3D interpolation</b> creates suggestions for 3D segmentations. That means if you start contouring, from the second contour onwards, the surface of the segmented area will be interpolated based on the given contour information.
The interpolation works with all available manual tools. Please note that this is currently a pure mathematical interpolation, i.e. image intensity information is not taken into account.
With each further contour the interpolation result will be improved, but the more contours you provide the longer the recalculation will take.
To achieve an optimal interpolation result and in this way a most accurate segmentation you should try to describe the surface with sparse contours by segmenting in arbitrary
oriented planes. The 3D interpolation is not meant to be used for parallel slice-wise segmentation, but rather segmentations in i.e. the axial, coronal and sagittal plane.
\imageMacro{QmitkSegmentation_3DInterpolationWrongRight.png,"3D interpolation usage",16.00}
You can accept the interpolation result by clicking the <i>Confirm</i>-button below the tool buttons.
In this case the 3D interpolation will be deactivated automatically so that the result can be post-processed without any interpolation running in the background.
Additional to the surface, black contours are shown in the 3D render window, which mark all the drawn contours used for the interpolation.
You can navigate between the drawn contours by clicking on the corresponding <i>position</i> nodes in the data manager which are stored as sub-nodes of the selected segmentation.
If you do not want to see these nodes just uncheck the <i>Show Position Nodes</i> checkbox and these nodes will be hidden.
If you want to delete a drawn contour we recommend to use the Erase-Tool since undo / redo is not yet working for 3D interpolation.
The current state of the 3D interpolation can be saved across application restart. For that, just click on save project during the interpolation is active.
After restarting the application and load your project you can click on "Reinit Interpolation" within the 3D interpolation GUI area.
\section org_mitk_views_segmentation3dsegmentation 3D segmentation tools
The 3D tools operate on the whole image and require usually a small amount of interaction like placing seed-points or specifying certain parameters. All 3D tools provide
an immediate segmentation feedback, which is displayed as a transparent green overlay. For accepting a preview you have to press the <i>Confirm</i> button of the selected tool.
The following 3D tools are available:
\subsection org_mitk_views_segmentation3dthresholdtool 3D Threshold tool
The thresholding tool simply applies a 3D threshold to the patient image. All pixels with values equal or above the selected threshold are labeled as part of the segmentation.
You can change the threshold by either moving the slider of setting a certain value in the spinbox.
\imageMacro{QmitkSegmentation_3DThresholdTool.png,"3D Threshold tool",10.00}
\subsection org_mitk_views_segmentation3dulthresholdTool 3D upper / lower threshold tool
The Upper/Lower Thresholding tool works similar to the simple 3D threshold tool but allows you to define an upper and lower threshold. All pixels with
values within this threshold interval will be labeled as part of the segmentation.
\imageMacro{QmitkSegmentation_3DULThresholdTool.png,"3D upper / lower threshold tool",10.00}
\subsection org_mitk_views_segmentation3dotsutool 3D Otsu tool
The 3D Otsu tool provides a more sophisticated thresholding algorithm. It allows you to define a number of regions. Based on the image histogram the pixels will
then be divided into different regions. The more regions you define the longer the calculation will take. You can select afterwards which of these regions you want to confirm as segmentation.
\imageMacro{QmitkSegmentation_3DOtsuTool.png,"3D Otsu tool",10.00}
\subsection org_mitk_views_segmentation3dgrowcuttool 3D GrowCut tool
The 3D GrowCut tool uses previously created segmentation labels (e.g. by the "Add"-tool) stored in the segmentation layer 0.
The GrowCut tool will use these segmentation labels to create a seedimage that will serve as input to the algorithm.
As an advanced setting option, a Distance penalty can be set, which increases the cohesion in the immediate surroundings of the initial labels.
Based on the seedimage and the Distance penalty, a growing is started, which includes all areas that are not initially assigned to a specific label.
During this process, initially unassigned areas are assigned to the best fitting labels.
After the segmentation process, the user can decide which newly generated labels should be confirmed.
\imageMacro{QmitkSegmentation_3DGrowCutTool.png,"3D GrowCut tool",16.00}
-\subsection org_mitk_views_segmentation3drgtool 3D Region growing tool
-
-The 3D Region Growing tool works similar to the 2D pendant. At the beginning you have to place a seedpoint and define a threshold interval. If you press
-<i>Run Segmentation</i> a preview is calculated. By moving the <i>Adapt region growing</i> slider you can interactively adapt the segmentation result.
-
-\imageMacro{QmitkSegmentation_3DRGTool.png,"3D Region growing tool",10.00}
-
\subsection org_mitk_views_segmentationpickingtool Picking Tool
The Picking tool offers two modes that allow you to manipulate "islands" within your segmentation. This is especially useful if e.g. a thresholding provided you with several areas within
your image but you are just interested in one special region.
- Picking mode: Allows you to select certain "islands". When the pick is confirmed, the complete content of the active label will be removed except the pick. This mode is beneficial if you have a lot segmentation noise and want to pick the relevant parts and dismiss the rest. Hint: You can also pick from other labels, but this will only work if these labels are unlocked.
- Relabel mode: Allows you to select certain "islands". When the pick is confirmed, it will be relabeled and added to the active label content. Hint: This mode ignores the locks of other labels, hence you do not need to unlock them explicitly.
\imageMacro{QmitkSegmentation_PickingTool.png,"Picking tool",10.00}
\subsection org_mitk_views_segmentationnnUNetTool nnU-Net Tool (Ubuntu only)
\imageMacro{QmitkSegmentation_nnUnetTool.png,"nnUNet tool",10.00}
-This tool provides a GUI to the deep learning-based segmentation algorithm called the nnUNet. With this tool, you can get a segmentation mask predicted for the loaded image in MITK. Be ready with the pre-trained weights (a.k.a <b>RESULTS_FOLDER</b>)
+This tool provides a GUI to the deep learning-based segmentation algorithm called the nnU-Net v1. With this tool, you can get a segmentation mask predicted for the loaded image in MITK. Be ready with the pre-trained weights (a.k.a <b>RESULTS_FOLDER</b>)
for your organ or task concerned, before using the tool. For a detailed explanation of the parameters and pre-trained weights folder structure etc., please refer to https://github.com/MIC-DKFZ/nnUNet. <br>
-Remark: The tool assumes that you have a Python3 environment with nnUNet (pip) installed. Your machine should be also equipped with a CUDA enabled GPU.
+Remark: The tool assumes that you have a Python3 environment with nnU-Net v1 (pip) installed. Your machine should be also equipped with a CUDA enabled GPU.
\subsubsection org_mitk_views_segmentationnnUNetToolWorkflow Workflow:
-# Select the "Python Path" drop-down to see if MITK has automatically detected other Python environments.
Click on a fitting environment for the nnUNet inference or click "Select" in the dropdown to choose an unlisted python environment. Note that, while selecting an arbitrary environment folder, only select the base folder, e.g. "myenv".
No need to select all the way until "../myenv/bin/python", for example.
-# Click on the "nnUNet Results Folder" directory icon to navigate to the results folder on your hard disk. This is equivalent to setting the <b>RESULTS_FOLDER</b> environment variable. If your results folder is as
per the nnUNet required folder structure, the configuration, trainers, tasks and folds are automatically parsed and correspondingly loaded in the drop-down boxes as shown below. Note that MITK automatically checks for the
<b>RESULTS_FOLDER</b> environment variable value and, if found, auto parses that directory when the tool is started.
\imageMacro{QmitkSegmentation_nnUNet_Settings.png,"nnUNet Segmentation Settings",10}
-# Choose your required Task-Configuration-Trainer-Planner-Fold parameters, sequentially. By default, all entries are selected inside the "Fold" dropdown (shown: "All").
Note that, even if you uncheck all entries from the "Fold" dropdown (shown: "None"), then too, all folds would be considered for inferencing.
-# For ensemble predictions, you will get the option to select parameters irrespective on postprocessing files available in the ensembles folder of <b>RESULTS_FOLDER</b>.
Note that, if a postprocessing json file exists for the selected combination then it will used for ensembling, by default. To choose not to, uncheck the "Use PostProcessing JSON" in the "Advanced" section.
\imageMacro{QmitkSegmentation_nnUNet_ensemble.png,"nnUNet Segmentation Settings",10}
-# If your task is trained with multi-modal inputs, then "Multi-Modal" checkbox is checked and the no.of modalities are preloaded and shown next to "Required Modalities".
Instantly, as much node selectors with corresponding modality names should appear below to select the Data Manager along including a selector with preselected with the reference node.
Now, select the image nodes in the node selectors accordingly for accurate inferencing.
\imageMacro{QmitkSegmentation_nnUNet_multimodal.png,"nnUNet Multi Modal Settings",10.00}
-# Click on "Preview".
-# In the "Advanced" section, you can also activate other options like "Mixed Precision" and "Enable Mirroring" (for test time data augmentation) pertaining to nnUNet.
\imageMacro{QmitkSegmentation_nnUNet_Advanced.png,"nnUNet Advanced Settings",10.00}
-# Use "Advanced" > "GPU Id" combobox to change the preferred GPU for inferencing. This is internally equivalent to setting the <b>CUDA_VISIBLE_DEVICES</b> environment variable.
-# Every inferred segmentation is cached to prevent a redundant computation. In case, a user doesn't wish to cache a Preview, uncheck the "Enable Caching" in the "Advanced" section. This will ensure that the
current parameters will neither be checked against the existing cache nor a segmentation be loaded from it when Preview is clicked.
-# You may always clear all the cached segmentations by clicking "Clear Cache" button.
\subsubsection org_mitk_views_segmentationnnUNetToolMisc Miscellaneous:
-# In case you want to reload/reparse the folders in the "nnUNet Results Folder", eg. after adding new tasks into it, you may do so without reselecting the folder again by clicking the "Refresh Results Folder" button.
-# The "Advanced" > "GPU Id" combobox lists the Nvidia GPUs available by parsing the <tt>nvidia-smi</tt> utility output. In case your machine has Nvidia CUDA enabled GPUs but the <tt>nvidia-smi</tt> fails for some reason, the "GPU Id" combobox will show no entries.
In such a situation, it's still possible to execute inferencing by manually entering the preferred GPU Id, eg. 0 in the combobox.
-# The "Advanced" > "Available Models" lists the available pre-trained tasks for download. Make sure you have internet connection. Then, choose a Task from the dropdown and click the Download button. The pre-trained models for the selected Task
will be downloaded and placed to the <b>RESULTS_FOLDER</b> directory automatically.
-# In the <b>RESULTS_FOLDER</b> directory, inside the trainer-planner folder of every task, MITK keeps a "mitk_export.json" file for fast loading for multi-modal information. It is recommended not to delete this file(s) for a fast responsive UI.
Tip: If multi-modal information shown on MITK is not correct for a given task, you may modify this JSON file and try again.
\subsection org_mitk_views_segmentationTotalSegmentator TotalSegmentator Tool
\imageMacro{QmitkSegmentation_nnUnetTool.png,"TotalSegmentator tool",10.00}
This tool provides a GUI to the deep learning-based segmentation algorithm called the TotalSegmentator. With this tool, you can get a segmentation mask predicted for 104 classes in CT images, loaded in MITK.
For a detailed explanation on tasks and supported classes etc., please refer to https://github.com/wasserth/TotalSegmentator <br>
The tool assumes that you have Python 3 installed and available on your machine. We recommend to install TotalSegmentator via MITK. The "Install TotalSegmentator" action implicitly creates a python virtual environment in an MITK mainitained
directory. Note: on Debian/Ubuntu systems, you need to install the python3-venv package using the following command: `apt install python3-venv`. For best results, your machine should be ideally equipped with a CUDA-enabled GPU.
\imageMacro{QmitkSegmentation_TotalsegmentatorTool.png, "TotalSegmentator Settings",5}
\subsubsection org_mitk_views_segmentationTotalSegmentatorWorkflow Workflow:
-# Install TotalSegmentator: Click "Install TotalSegmentator" to install TotalSegmentator (version: 1.5.5) in a virtual environment. Make sure you have a working internet connection. This might take a while. It is a one time job, though.
Once installed, the "Install TotalSegmentator" button is grayed out.
-# If Python is not found by MITK goto "Install Options" & select the "System Python Path" drop-down to see if MITK has automatically detected other Python environments.
Click on a fitting Python installation for TotalSegmentator to use or click "Select" in the dropdown to choose an unlisted installation of Python. Note that, while selecting an arbitrary environment folder, only select the base folder, e.g. "/usr/bin/".
No need to navigate all the way into "../usr/bin/python3", for example.
-# Select a specific subtask in the "Tasks" drop-downs. The default is "total" for non-specific total segmentation.
-# Click on "Run TotalSegmentator" for a preview.
-# In the "Advanced" section, you can also activate other options like "Fast" for faster runtime and less memory requirements. Use "Fast" if you only have a CPU for inferencing.
-# Use "Advanced" > "GPU Id" combobox to change the preferred GPU for inferencing. This is internally equivalent to setting the <b>CUDA_VISIBLE_DEVICES</b> environment variable.
-# In case you want to use your own virtual environment containing TotalSegmentator, goto "Install Options" & check "Use Custom Installation" checkbox. Then, select the environment of your choice by using "Custom Env. Path".
\section org_mitk_views_segmentationpostprocessing Additional things you can do with segmentations
Segmentations are never an end in themselves. Consequently, the segmentation view adds a couple of "post-processing" actions, accessible through the context-menu of the data manager.
\imageMacro{QmitkSegmentation_IMGDataManagerContextMenu.png,"Context menu items for segmentations",10.58}
<ul>
<li> <b>Create polygon %model</b> applies the marching cubes algorithm to the segmentation. This polygon %model can be used for visualization in 3D or other applications such as stereolithography (3D printing).
<li> <b>Create smoothed polygon %model</b> uses smoothing in addition to the marching cubes algorithm, which creates models that do not follow the exact outlines of the segmentation, but look smoother.
<li> <b>Autocrop</b> can save memory. Manual segmentations have the same extent as the patient image, even if the segmentation comprises only a small sub-volume. This invisible and meaningless margin is removed by autocropping.
</ul>
\section org_mitk_views_segmentationof3dtimages Segmentation of 3D+t images
For segmentation of 3D+t images, some tools give you the option to choose between creating dynamic and static masks.
<ul>
<li> Dynamic masks can be created on each time frame individually.
<li> Static masks will be defined on one time frame and will be the same for all other time frames.
</ul>
In general, segmentation is applied on the time frame that is selected when execution is performed.
If you alter the time frame, the segmentation preview is adapted.
\section org_mitk_views_segmentationtechnicaldetail Technical information for developers
For technical specifications see \subpage QmitkSegmentationTechnicalPage and for information on the extensions of the tools system \subpage toolextensions.
*/
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationTaskList.dox b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationTaskList.dox
new file mode 100644
index 0000000000..af1669d092
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationTaskList.dox
@@ -0,0 +1,186 @@
+/**
+\page org_mitk_views_segmentationtasklist The Segmentation Task List View
+
+\imageMacro{segmentation_task_list-dox.svg,"Icon of the Segmentation Task List View",2.00}
+
+\tableofcontents
+
+\section org_mitk_views_segmentationtasklist_disclaimer Disclaimer
+
+- The Segmentation Task List View and MITK Segmentation Task Lists in general are still in an <b>experimental</b> stage.
+- While we try to minimize breaking changes in the future, we cannot give any guarantees at the moment.
+- We strongly advise to ignore the Data Manager regarding loading and unloading of data while using the Segmentation Task List View, as it will completely take over these operations and may run into invalid states otherwise.
+
+\section org_mitk_views_segmentationtasklist_overview Overview
+
+\imageMacro{QmitkSegmentationTaskList.png,"Segmentation Task List View", 12.00}
+
+As the Segmentation Task List View is typically used in combination with the Segmentation View, we suggest to move the Segmentatiom View to the other side of the application (e.g. on top of the Data Manager), to see both views at the same time.
+
+To unlock the Segmentation Task List View, unload everything but a single MITK Segmentation Task List.
+The remaining Segmentation Task List will be automatically selected.
+
+The Segmentation Task List View shows the progress of the whole Segmentation Task List, e.g., the number of the tasks marked as <em>done</em> vs. the total number of available tasks.
+
+Below the progress indictator you can navigate between tasks, read their descriptions and related information, as well as load/activate the currently shown task.
+This will unload all data from a previously active task, if any, and load all data of the current task.
+To prevent any accidental data loss, unsaved task data will interfer task switches and you can decide on how to proceed.
+
+Above the task description, the status of tasks is displayed as a pair of colored labels, indicating if a task is either active or inactive and if it is considered not to be done, having unsaved changes, or to be done.
+
+With the bottom two buttons you can either save an interim result (the task is considered not to be done), or accept and save the task result.
+You can still edit accepted tasks but in contrast to interim results, the task is considered to be done.
+
+\section org_mitk_views_segmentationtasklist_shortcuts Keyboard shortcuts
+
+The Segmentation Task List View can be used even more efficiently with the following set of keyboard shortcuts:
+
+- <tt>Ctrl</tt> + <tt>Alt</tt> + <tt>P</tt>: Navigate to <b>p</b>revious task
+- <tt>Ctrl</tt> + <tt>Shift</tt> + <tt>P</tt>: Navigate to <b>p</b>revious undone task (or <tt>Shift</tt> + click on resp. button)
+- <tt>Ctrl</tt> + <tt>Alt</tt> + <tt>N</tt>: Navigate to <b>n</b>ext task
+- <tt>Ctrl</tt> + <tt>Shift</tt> + <tt>N</tt>: Navigate to <b>n</b>ext undone task (or <tt>Shift</tt> + click on resp. button)
+- <tt>Ctrl</tt> + <tt>Alt</tt> + <tt>L</tt>: <b>L</b>oad currently shown task
+- <tt>Ctrl</tt> + <tt>Alt</tt> + <tt>S</tt>: <b>S</b>tore interim result
+- <tt>Ctrl</tt> + <tt>Alt</tt> + <tt>A</tt>: <b>A</b>ccept task and store result
+- <tt>Ctrl</tt> + <tt>F</tt>: <b>F</b>ind task...
+
+\section org_mitk_views_segmentationtasklist_find Finding tasks
+
+\imageMacro{QmitkFindSegmentationTaskDialog.png,"Find Segmentation Task dialog", 12.00}
+
+To find a specific task in a segmentation task list, click on the "Find task..." button (magnifier icon) or press <tt>Ctrl</tt> + <tt>F</tt>.
+A dedicated dialog will appear for filtering and searching the current segmentation task list.
+Enter a task number and press <tt>Return</tt> to immediately load the according task or filter the shown list of tasks and double click on a result to load the task.
+
+\section org_mitk_views_segmentationtasklist_fileformat MITK Segmentation Task List file format
+
+MITK Segmentation Task List files are JSON files containing a JSON object as root.
+It must contain the two mandatory properties <tt>FileFormat</tt> and <tt>Version</tt>:
+
+\code{.json}
+{
+ "FileFormat": "MITK Segmentation Task List",
+ "Version": 1
+}
+\endcode
+
+We also recommend to specify an optional <tt>Name</tt> that is used in the application if present instead of the plain filename of the JSON file:
+
+\code{.json}
+{
+ "FileFormat": "MITK Segmentation Task List",
+ "Version": 1,
+ "Name": "My First Task List"
+}
+\endcode
+
+\subsection org_mitk_views_segmentationtasklist_fileformat_tasks Tasks
+
+The root object must also contain a mandatory <tt>Tasks</tt> array, containing JSON objects that specify the individual tasks of the task list.
+A minimum task object must contain <tt>Image</tt> and <tt>Result</tt> file paths.
+<tt>Image</tt> refers to the patient image and <tt>Result</tt> refers to the path were the resulting segmentation is expected to be stored.
+Paths can be absolute or relative to the JSON file.
+
+\code{.json}
+{
+ "FileFormat": "MITK Segmentation Task List",
+ "Version": 1,
+ "Tasks": [
+ {
+ "Image": "images/Pic3D.nrrd",
+ "Result": "results/liver.nrrd"
+ }
+ ]
+}
+\endcode
+
+In addition, tasks can contain a bunch of optional properties that mainly specify a segmentation a user starts with:
+
+- <tt>Name</tt> (<em>string</em>): A name for the task.
+- <tt>Description</tt> (<em>string</em>): A short description/definition of the task.
+- <tt>LabelName</tt> (<em>string</em>): The name of the first label in a new segmentation that is created for the task on the fly.
+- <tt>LabelNameSuggestions</tt> (<em>file path</em>): A Label Suggestions JSON file (example in next comment) specifying names and optional colors, that are suggested to the user for new labels in the segmentation.
+- <tt>Preset</tt> (<em>file path</em>): A Label Set Preset XML file in MITK's .lsetp file format. The preset is applied to a new segmentation that is created for the task on the fly. We recommend to use the Segmentation plugin of the MITK Workbench to create such label set preset files as described in its {key F1} user guide.
+- <tt>Segmentation</tt> (<em>file path</em>): A pre-segmentation that a user can start with or has to refine for example.
+- <tt>Dynamic</tt> (<em>boolean</em>): In case <tt>Image</tt> refers to a dynamic (3d+t) image, specifies whether the segmentation should be static (<em>false</em>), i.e. equal for all time steps, or dynamic (<em>true</em>), i.e. individual for each time step.
+
+\subsection org_mitk_views_segmentationtasklist_fileformat_taskdefaults Task defaults / common properties
+
+If a task list contains multiple tasks with common properties, they do not have to be specified for each and every task again and again.
+Instead, the root object can contain an optional <tt>Defaults</tt> object that is identical in format to the tasks specified above.
+As the name indicates, default properties can still be overridden by individual tasks if they are specified explicitly.
+
+There is a single exception, though: A <tt>Defaults</tt> object must not contain a <tt>Result</tt> file path, since result files of tasks must be distinct by definition.
+
+\subsection org_mitk_views_segmentationtasklist_fileformat_example Example
+
+The following example is a complete showcase of the properties and features listed above.
+It specifies 4 tasks.
+3 tasks refer to the same patient image so it is specified as default.
+
+Remember that the only task property required to be distinct is <tt>Result</tt> so you are pretty free in your task design.
+For simplicity, we chose to define tasks around organs for this example and named the tasks accordingly:
+
+\code{.json}
+{
+ "FileFormat": "MITK Segmentation Task List",
+ "Version": 1,
+ "Name": "Example Segmentation Task List",
+ "Defaults": {
+ "Image": "images/Pic3D.nrrd"
+ },
+ "Tasks": [
+ {
+ "Name": "Liver",
+ "LabelName": "Liver",
+ "LabelNameSuggestions": "suggestions/label_suggestions.json",
+ "Description": "This task provides an image and label name suggestions for new labels. The segmentation will start with an empty label named Liver.",
+ "Result": "results/liver.nrrd"
+ },
+ {
+ "Name": "Kidneys",
+ "Description": "This task provides an image and a label set preset that is applied to the new segmentation.",
+ "Preset": "presets/kidneys.lsetp",
+ "Result": "results/kidneys.nrrd"
+ },
+ {
+ "Name": "Spleen",
+ "Description": "This task provides an image and an initial (pre-)segmentation.",
+ "Segmentation": "segmentations/spleen.nrrd",
+ "Result": "results/spleen.nrrd"
+ },
+ {
+ "Name": "Surprise",
+ "Description": "And now for something completely different. This task overrides the default Image and starts with an empty static segmentation for a dynamic image.",
+ "Image": "images/US4DCyl.nrrd",
+ "Result": "results/US4DCyl.nrrd",
+ "Dynamic": false
+ }
+ ]
+}
+\endcode
+
+\section org_mitk_views_segmentationtasklist_labelsuggestions MITK Label Suggestions file format
+
+The Label Suggestions JSON file format mentioned above to specify a list of suggested names and optional colors for new labels is as follows:
+
+\code{.json}
+[
+ {
+ "name": "Abdomen",
+ "color": "red"
+ },
+ {
+ "name": "Lung",
+ "color": "#00ff00"
+ },
+ {
+ "name": "Heart"
+ },
+ {
+ "name": "Aortic Valve",
+ "color": "CornflowerBlue"
+ }
+]
+\endcode
+*/
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationTaskList.png b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationTaskList.png
new file mode 100644
index 0000000000..619547b824
Binary files /dev/null and b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationTaskList.png differ
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation_3DRGTool.png b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation_3DRGTool.png
deleted file mode 100644
index e3f0257cf1..0000000000
Binary files a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation_3DRGTool.png and /dev/null differ
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation_ContextMenus.png b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation_ContextMenus.png
index 6aa5f0c13e..10e513a38f 100644
Binary files a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation_ContextMenus.png and b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentation_ContextMenus.png differ
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/segmentation_task_list-dox.svg b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/segmentation_task_list-dox.svg
new file mode 100644
index 0000000000..fa7f9e8990
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/segmentation_task_list-dox.svg
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="32"
+ height="32"
+ viewBox="0 0 8.4666665 8.4666669"
+ version="1.1"
+ id="svg8"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="segmentation_task_list-dox.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#676767"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:zoom="20"
+ inkscape:cx="12.070777"
+ inkscape:cy="21.616923"
+ inkscape:document-units="mm"
+ inkscape:current-layer="g920"
+ inkscape:document-rotation="0"
+ showgrid="true"
+ units="px"
+ inkscape:pagecheckerboard="true"
+ showborder="true"
+ borderlayer="false"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="2560"
+ inkscape:window-height="1377"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect835"
+ width="6.0854168"
+ height="7.1437502"
+ x="1.1906248"
+ y="0.92604148"
+ rx="0.26458332"
+ ry="0.26458332" />
+ <g
+ style="stroke:#000000;stroke-opacity:1"
+ id="g920"
+ transform="translate(-3.3333334e-8,0.13229177)">
+ <path
+ id="path857"
+ d="M 3.9626056,3.036013 H 6.4629181"
+ style="fill:none;stroke:#000000;stroke-width:0.330729;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path859"
+ d="M 1.852084,3.10621 2.4500425,3.7041689 3.3469803,2.2092717"
+ style="fill:none;stroke:#525252;stroke-width:0.396875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g970">
+ <circle
+ r="0.39687496"
+ cy="1.6497022"
+ cx="2.3812499"
+ id="path943"
+ style="fill:#000b00;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path857-1"
+ d="M 2.38125,1.5875 V 0.52916667"
+ style="fill:none;stroke:#000000;stroke-width:0.330728;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1" />
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ transform="translate(1.2347223)"
+ id="g970-7">
+ <circle
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path943-9"
+ cx="2.3812499"
+ cy="1.6497022"
+ r="0.39687496" />
+ <path
+ style="fill:#000000;stroke:#000000;stroke-width:0.330728;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+ d="M 2.38125,1.5875 V 0.52916667"
+ id="path857-1-8" />
+ </g>
+ <g
+ id="g970-4"
+ transform="translate(2.4694441)">
+ <circle
+ r="0.39687496"
+ cy="1.6497022"
+ cx="2.3812499"
+ id="path943-1"
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path857-1-5"
+ d="M 2.38125,1.5875 V 0.52916667"
+ style="fill:none;stroke:#000000;stroke-width:0.330728;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g970-9"
+ transform="translate(3.7041667)">
+ <circle
+ r="0.39687496"
+ cy="1.6497022"
+ cx="2.3812499"
+ id="path943-6"
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path857-1-9"
+ d="M 2.38125,1.5875 V 0.52916667"
+ style="fill:none;stroke:#000000;stroke-width:0.330728;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1"
+ id="g1080"
+ transform="translate(-6.6666669e-8,-0.26458327)">
+ <path
+ id="path857-0"
+ d="M 3.9626056,5.2849714 H 6.4629181"
+ style="fill:none;stroke:#000000;stroke-width:0.330729;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ ry="0.26458332"
+ rx="0.26458332"
+ y="4.6634164"
+ x="1.8519536"
+ height="1.256501"
+ width="1.256501"
+ id="rect1060"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.330999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ style="stroke:#000000;stroke-opacity:1"
+ id="g1080-1"
+ transform="translate(-3.3333334e-8,1.5875)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.330729;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3.9626056,5.2849714 H 6.4629181"
+ id="path857-0-3" />
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.330999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1060-3"
+ width="1.256501"
+ height="1.256501"
+ x="1.8519536"
+ y="4.6634164"
+ rx="0.26458332"
+ ry="0.26458332" />
+ </g>
+ </g>
+</svg>
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp
index 330e893f69..4a96a422a7 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp
@@ -1,86 +1,68 @@
/*============================================================================
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 "QmitkSegmentationUtilitiesView.h"
#include <QmitkBooleanOperationsWidget.h>
#include <QmitkContourModelToImageWidget.h>
#include <QmitkImageMaskingWidget.h>
#include <QmitkMorphologicalOperationsWidget.h>
#include <QmitkSurfaceToImageWidget.h>
QmitkSegmentationUtilitiesView::QmitkSegmentationUtilitiesView()
: m_BooleanOperationsWidget(nullptr),
m_ContourModelToImageWidget(nullptr),
m_ImageMaskingWidget(nullptr),
m_MorphologicalOperationsWidget(nullptr),
m_SurfaceToImageWidget(nullptr)
{
}
QmitkSegmentationUtilitiesView::~QmitkSegmentationUtilitiesView()
{
}
void QmitkSegmentationUtilitiesView::CreateQtPartControl(QWidget* parent)
{
m_Controls.setupUi(parent);
- mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart();
-
- mitk::SliceNavigationController* timeNavigationController = renderWindowPart != nullptr
- ? renderWindowPart->GetTimeNavigationController()
- : nullptr;
-
auto dataStorage = this->GetDataStorage();
- m_BooleanOperationsWidget = new QmitkBooleanOperationsWidget(dataStorage, timeNavigationController, parent);
- m_ContourModelToImageWidget = new QmitkContourModelToImageWidget(dataStorage, timeNavigationController, parent);
- m_ImageMaskingWidget = new QmitkImageMaskingWidget(dataStorage, timeNavigationController, parent);
- m_MorphologicalOperationsWidget = new QmitkMorphologicalOperationsWidget(dataStorage, timeNavigationController, parent);
- m_SurfaceToImageWidget = new QmitkSurfaceToImageWidget(dataStorage, timeNavigationController, parent);
+ m_BooleanOperationsWidget = new QmitkBooleanOperationsWidget(dataStorage, parent);
+ m_ContourModelToImageWidget = new QmitkContourModelToImageWidget(dataStorage, parent);
+ m_ImageMaskingWidget = new QmitkImageMaskingWidget(dataStorage, parent);
+ m_MorphologicalOperationsWidget = new QmitkMorphologicalOperationsWidget(dataStorage, parent);
+ m_SurfaceToImageWidget = new QmitkSurfaceToImageWidget(dataStorage, parent);
this->AddUtilityWidget(m_BooleanOperationsWidget, QIcon(":/SegmentationUtilities/BooleanOperations_48x48.png"), "Boolean Operations");
this->AddUtilityWidget(m_ContourModelToImageWidget, QIcon(":/SegmentationUtilities/ContourModelSetToImage_48x48.png"), "Contour to Image");
this->AddUtilityWidget(m_ImageMaskingWidget, QIcon(":/SegmentationUtilities/ImageMasking_48x48.png"), "Image Masking");
this->AddUtilityWidget(m_MorphologicalOperationsWidget, QIcon(":/SegmentationUtilities/MorphologicalOperations_48x48.png"), "Morphological Operations");
this->AddUtilityWidget(m_SurfaceToImageWidget, QIcon(":/SegmentationUtilities/SurfaceToImage_48x48.png"), "Surface to Image");
}
void QmitkSegmentationUtilitiesView::AddUtilityWidget(QWidget* widget, const QIcon& icon, const QString& text)
{
m_Controls.toolBox->addItem(widget, icon, text);
}
void QmitkSegmentationUtilitiesView::SetFocus()
{
m_Controls.toolBox->setFocus();
}
-void QmitkSegmentationUtilitiesView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
+void QmitkSegmentationUtilitiesView::RenderWindowPartActivated(mitk::IRenderWindowPart*)
{
- mitk::SliceNavigationController* timeNavigationController = renderWindowPart->GetTimeNavigationController();
-
- m_BooleanOperationsWidget->SetTimeNavigationController(timeNavigationController);
- m_ContourModelToImageWidget->SetTimeNavigationController(timeNavigationController);
- m_ImageMaskingWidget->SetTimeNavigationController(timeNavigationController);
- m_MorphologicalOperationsWidget->SetTimeNavigationController(timeNavigationController);
- m_SurfaceToImageWidget->SetTimeNavigationController(timeNavigationController);
}
void QmitkSegmentationUtilitiesView::RenderWindowPartDeactivated(mitk::IRenderWindowPart*)
{
- m_BooleanOperationsWidget->SetTimeNavigationController(nullptr);
- m_ContourModelToImageWidget->SetTimeNavigationController(nullptr);
- m_ImageMaskingWidget->SetTimeNavigationController(nullptr);
- m_MorphologicalOperationsWidget->SetTimeNavigationController(nullptr);
- m_SurfaceToImageWidget->SetTimeNavigationController(nullptr);
}
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
index 8a8e62bb17..bdf64a65dd 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
@@ -1,1031 +1,1083 @@
/*============================================================================
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 "QmitkSegmentationView.h"
#include "mitkPluginActivator.h"
// blueberry
#include <berryIWorkbenchPage.h>
// mitk
#include <mitkApplicationCursor.h>
#include <mitkBaseApplication.h>
#include <mitkBaseRendererHelper.h>
#include <mitkCameraController.h>
#include <mitkLabelSetImage.h>
#include <mitkLabelSetImageHelper.h>
#include <mitkMultiLabelIOHelper.h>
#include <mitkManualPlacementAnnotationRenderer.h>
#include <mitkNodePredicateSubGeometry.h>
#include <mitkSegmentationObjectFactory.h>
#include <mitkSegTool2D.h>
#include <mitkStatusBar.h>
#include <mitkToolManagerProvider.h>
#include <mitkVtkResliceInterpolationProperty.h>
#include <mitkWorkbenchUtil.h>
#include <mitkIPreferences.h>
// Qmitk
#include <QmitkRenderWindow.h>
#include <QmitkStaticDynamicSegmentationDialog.h>
#include <QmitkNewSegmentationDialog.h>
#include <QmitkMultiLabelManager.h>
// us
#include <usModuleResource.h>
#include <usModuleResourceStream.h>
// Qt
#include <QMessageBox>
#include <QShortcut>
#include <QDir>
// vtk
#include <vtkQImageToImageSource.h>
#include <regex>
namespace
{
QList<QmitkRenderWindow*> Get2DWindows(const QList<QmitkRenderWindow*> allWindows)
{
QList<QmitkRenderWindow*> all2DWindows;
for (auto* window : allWindows)
{
if (window->GetRenderer()->GetMapperID() == mitk::BaseRenderer::Standard2D)
{
all2DWindows.append(window);
}
}
return all2DWindows;
}
}
const std::string QmitkSegmentationView::VIEW_ID = "org.mitk.views.segmentation";
QmitkSegmentationView::QmitkSegmentationView()
: m_Parent(nullptr)
, m_Controls(nullptr)
, m_RenderWindowPart(nullptr)
, m_ToolManager(nullptr)
, m_ReferenceNode(nullptr)
, m_WorkingNode(nullptr)
, m_DrawOutline(true)
, m_SelectionMode(false)
, m_MouseCursorSet(false)
, m_DefaultLabelNaming(true)
, m_SelectionChangeIsAlreadyBeingHandled(false)
{
auto isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
auto isDwi = mitk::NodePredicateDataType::New("DiffusionImage");
auto isDti = mitk::NodePredicateDataType::New("TensorImage");
auto isOdf = mitk::NodePredicateDataType::New("OdfImage");
auto isSegment = mitk::NodePredicateDataType::New("Segment");
auto validImages = mitk::NodePredicateOr::New();
validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegment)));
validImages->AddPredicate(isDwi);
validImages->AddPredicate(isDti);
validImages->AddPredicate(isOdf);
m_SegmentationPredicate = mitk::NodePredicateAnd::New();
m_SegmentationPredicate->AddPredicate(mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
m_SegmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
m_SegmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
m_ReferencePredicate = mitk::NodePredicateAnd::New();
m_ReferencePredicate->AddPredicate(validImages);
m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(m_SegmentationPredicate));
m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
}
QmitkSegmentationView::~QmitkSegmentationView()
{
if (nullptr != m_Controls)
{
// deactivate all tools
m_ToolManager->ActivateTool(-1);
// removing all observers from working data
for (NodeTagMapType::iterator dataIter = m_WorkingDataObserverTags.begin(); dataIter != m_WorkingDataObserverTags.end(); ++dataIter)
{
(*dataIter).first->GetProperty("visible")->RemoveObserver((*dataIter).second);
}
m_WorkingDataObserverTags.clear();
+ this->RemoveObserversFromWorkingImage();
+
// removing all observers from reference data
for (NodeTagMapType::iterator dataIter = m_ReferenceDataObserverTags.begin(); dataIter != m_ReferenceDataObserverTags.end(); ++dataIter)
{
(*dataIter).first->GetProperty("visible")->RemoveObserver((*dataIter).second);
}
m_ReferenceDataObserverTags.clear();
mitk::RenderingManager::GetInstance()->RemoveObserver(m_RenderingManagerObserverTag);
ctkPluginContext* context = mitk::PluginActivator::getContext();
ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
service->RemoveAllPlanePositions();
context->ungetService(ppmRef);
m_ToolManager->SetReferenceData(nullptr);
m_ToolManager->SetWorkingData(nullptr);
}
m_ToolManager->ActiveToolChanged -=
- mitk::MessageDelegate<QmitkSegmentationView>(this, &QmitkSegmentationView::ActiveToolChanged);
+ mitk::MessageDelegate<Self>(this, &Self::ActiveToolChanged);
delete m_Controls;
}
/**********************************************************************/
/* private Q_SLOTS */
/**********************************************************************/
void QmitkSegmentationView::OnReferenceSelectionChanged(QList<mitk::DataNode::Pointer>)
{
this->OnAnySelectionChanged();
}
void QmitkSegmentationView::OnSegmentationSelectionChanged(QList<mitk::DataNode::Pointer>)
{
this->OnAnySelectionChanged();
}
void QmitkSegmentationView::OnAnySelectionChanged()
{
// When only a segmentation has been selected and the method is then called by a reference image selection,
// the already selected segmentation may not match the geometry predicate of the new reference image anymore.
// This will trigger a recursive call of this method further below. While it would be resolved gracefully, we
// can spare the extra call with an early-out. The original call of this method will handle the segmentation
// selection change afterwards anyway.
if (m_SelectionChangeIsAlreadyBeingHandled)
return;
auto selectedReferenceNode = m_Controls->referenceNodeSelector->GetSelectedNode();
bool referenceNodeChanged = false;
m_ToolManager->ActivateTool(-1);
if (m_ReferenceNode != selectedReferenceNode)
{
referenceNodeChanged = true;
// Remove visibility observer for the current reference node
if (m_ReferenceDataObserverTags.find(m_ReferenceNode) != m_ReferenceDataObserverTags.end())
{
m_ReferenceNode->GetProperty("visible")->RemoveObserver(m_ReferenceDataObserverTags[m_ReferenceNode]);
m_ReferenceDataObserverTags.erase(m_ReferenceNode);
}
// Set new reference node
m_ReferenceNode = selectedReferenceNode;
m_ToolManager->SetReferenceData(m_ReferenceNode);
// Prepare for a potential recursive call when changing node predicates of the working node selector
m_SelectionChangeIsAlreadyBeingHandled = true;
if (m_ReferenceNode.IsNull())
{
// Without a reference image, allow all segmentations to be selected
m_Controls->workingNodeSelector->SetNodePredicate(m_SegmentationPredicate);
m_SelectionChangeIsAlreadyBeingHandled = false;
}
else
{
// With a reference image, only allow segmentations that fit the geometry of the reference image to be selected.
m_Controls->workingNodeSelector->SetNodePredicate(mitk::NodePredicateAnd::New(
mitk::NodePredicateSubGeometry::New(m_ReferenceNode->GetData()->GetGeometry()),
m_SegmentationPredicate.GetPointer()));
m_SelectionChangeIsAlreadyBeingHandled = false;
this->ApplySelectionModeOnReferenceNode();
// Add visibility observer for the new reference node
- auto command = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
- command->SetCallbackFunction(this, &QmitkSegmentationView::ValidateSelectionInput);
+ auto command = itk::SimpleMemberCommand<Self>::New();
+ command->SetCallbackFunction(this, &Self::ValidateSelectionInput);
m_ReferenceDataObserverTags[m_ReferenceNode] =
m_ReferenceNode->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command);
}
}
auto selectedWorkingNode = m_Controls->workingNodeSelector->GetSelectedNode();
bool workingNodeChanged = false;
if (m_WorkingNode != selectedWorkingNode)
{
workingNodeChanged = true;
+ this->RemoveObserversFromWorkingImage();
+
// Remove visibility observer for the current working node
if (m_WorkingDataObserverTags.find(m_WorkingNode) != m_WorkingDataObserverTags.end())
{
m_WorkingNode->GetProperty("visible")->RemoveObserver(m_WorkingDataObserverTags[m_WorkingNode]);
m_WorkingDataObserverTags.erase(m_WorkingNode);
}
// Set new working node
m_WorkingNode = selectedWorkingNode;
m_ToolManager->SetWorkingData(m_WorkingNode);
if (m_WorkingNode.IsNotNull())
{
this->ApplySelectionModeOnWorkingNode();
// Add visibility observer for the new segmentation node
- auto command = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
- command->SetCallbackFunction(this, &QmitkSegmentationView::ValidateSelectionInput);
+ auto command = itk::SimpleMemberCommand<Self>::New();
+ command->SetCallbackFunction(this, &Self::ValidateSelectionInput);
m_WorkingDataObserverTags[m_WorkingNode] =
m_WorkingNode->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command);
+
+ this->AddObserversToWorkingImage();
}
}
// Reset camera if any selection changed but only if both reference node and working node are set
if ((referenceNodeChanged || workingNodeChanged) && (m_ReferenceNode.IsNotNull() && m_WorkingNode.IsNotNull()))
{
if (nullptr != m_RenderWindowPart)
{
m_RenderWindowPart->InitializeViews(m_ReferenceNode->GetData()->GetTimeGeometry(), false);
}
}
this->UpdateGUI();
}
+void QmitkSegmentationView::OnLabelAdded(mitk::LabelSetImage::LabelValueType)
+{
+ this->ValidateSelectionInput();
+}
+
+void QmitkSegmentationView::OnLabelRemoved(mitk::LabelSetImage::LabelValueType)
+{
+ this->ValidateSelectionInput();
+}
+
+void QmitkSegmentationView::OnGroupRemoved(mitk::LabelSetImage::GroupIndexType)
+{
+ this->ValidateSelectionInput();
+}
+
+mitk::LabelSetImage* QmitkSegmentationView::GetWorkingImage()
+{
+ if (m_WorkingNode.IsNull())
+ return nullptr;
+
+ return dynamic_cast<mitk::LabelSetImage*>(m_WorkingNode->GetData());
+}
+
+void QmitkSegmentationView::AddObserversToWorkingImage()
+{
+ auto* workingImage = this->GetWorkingImage();
+
+ if (workingImage != nullptr)
+ {
+ workingImage->AddLabelAddedListener(mitk::MessageDelegate1<Self, mitk::LabelSetImage::LabelValueType>(this, &Self::OnLabelAdded));
+ workingImage->AddLabelRemovedListener(mitk::MessageDelegate1<Self, mitk::LabelSetImage::LabelValueType>(this, &Self::OnLabelRemoved));
+ workingImage->AddGroupRemovedListener(mitk::MessageDelegate1<Self, mitk::LabelSetImage::GroupIndexType>(this, &Self::OnGroupRemoved));
+ }
+}
+
+void QmitkSegmentationView::RemoveObserversFromWorkingImage()
+{
+ auto* workingImage = this->GetWorkingImage();
+
+ if (workingImage != nullptr)
+ {
+ workingImage->RemoveLabelAddedListener(mitk::MessageDelegate1<Self, mitk::LabelSetImage::LabelValueType>(this, &Self::OnLabelAdded));
+ workingImage->RemoveLabelRemovedListener(mitk::MessageDelegate1<Self, mitk::LabelSetImage::LabelValueType>(this, &Self::OnLabelRemoved));
+ workingImage->RemoveGroupRemovedListener(mitk::MessageDelegate1<Self, mitk::LabelSetImage::GroupIndexType>(this, &Self::OnGroupRemoved));
+ }
+}
+
void QmitkSegmentationView::OnVisibilityShortcutActivated()
{
if (m_WorkingNode.IsNull())
{
return;
}
bool isVisible = false;
m_WorkingNode->GetBoolProperty("visible", isVisible);
m_WorkingNode->SetVisibility(!isVisible);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSegmentationView::OnLabelToggleShortcutActivated()
{
if (m_WorkingNode.IsNull())
{
return;
}
auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_WorkingNode->GetData());
if (nullptr == workingImage)
{
return;
}
this->WaitCursorOn();
workingImage->GetActiveLabelSet()->SetNextActiveLabel();
workingImage->Modified();
this->WaitCursorOff();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSegmentationView::OnNewSegmentation()
{
m_ToolManager->ActivateTool(-1);
if (m_ReferenceNode.IsNull())
{
MITK_ERROR << "'Create new segmentation' button should never be clickable unless a reference image is selected.";
return;
}
mitk::Image::ConstPointer referenceImage = dynamic_cast<mitk::Image*>(m_ReferenceNode->GetData());
if (referenceImage.IsNull())
{
QMessageBox::information(
m_Parent, "New segmentation", "Please load and select an image before starting some action.");
return;
}
if (referenceImage->GetDimension() <= 1)
{
QMessageBox::information(
m_Parent, "New segmentation", "Segmentation is currently not supported for 2D images");
return;
}
auto segTemplateImage = referenceImage;
if (referenceImage->GetDimension() > 3)
{
QmitkStaticDynamicSegmentationDialog dialog(m_Parent);
dialog.SetReferenceImage(referenceImage.GetPointer());
dialog.exec();
segTemplateImage = dialog.GetSegmentationTemplate();
}
mitk::DataNode::Pointer newSegmentationNode;
try
{
this->WaitCursorOn();
newSegmentationNode = mitk::LabelSetImageHelper::CreateNewSegmentationNode(m_ReferenceNode, segTemplateImage);
this->WaitCursorOff();
}
catch (mitk::Exception& e)
{
this->WaitCursorOff();
MITK_ERROR << "Exception caught: " << e.GetDescription();
QMessageBox::warning(m_Parent, "New segmentation", "Could not create a new segmentation.");
return;
}
auto newLabelSetImage = dynamic_cast<mitk::LabelSetImage*>(newSegmentationNode->GetData());
if (nullptr == newLabelSetImage)
{
// something went wrong
return;
}
const auto labelSetPreset = this->GetDefaultLabelSetPreset();
if (labelSetPreset.empty() || !mitk::MultiLabelIOHelper::LoadLabelSetImagePreset(labelSetPreset, newLabelSetImage))
{
auto newLabel = mitk::LabelSetImageHelper::CreateNewLabel(newLabelSetImage);
if (!m_DefaultLabelNaming)
QmitkNewSegmentationDialog::DoRenameLabel(newLabel, nullptr, m_Parent);
newLabelSetImage->GetActiveLabelSet()->AddLabel(newLabel);
}
if (!this->GetDataStorage()->Exists(newSegmentationNode))
{
this->GetDataStorage()->Add(newSegmentationNode, m_ReferenceNode);
}
if (m_ToolManager->GetWorkingData(0))
{
m_ToolManager->GetWorkingData(0)->SetSelected(false);
}
newSegmentationNode->SetSelected(true);
m_Controls->workingNodeSelector->SetCurrentSelectedNode(newSegmentationNode);
}
std::string QmitkSegmentationView::GetDefaultLabelSetPreset() const
{
auto labelSetPreset = mitk::BaseApplication::instance().config().getString(mitk::BaseApplication::ARG_SEGMENTATION_LABELSET_PRESET.toStdString(), "");
if (labelSetPreset.empty())
labelSetPreset = m_LabelSetPresetPreference.toStdString();
return labelSetPreset;
}
void QmitkSegmentationView::OnManualTool2DSelected(int id)
{
this->ResetMouseCursor();
mitk::StatusBar::GetInstance()->DisplayText("");
if (id >= 0)
{
std::string text = "Active Tool: \"";
text += m_ToolManager->GetToolById(id)->GetName();
text += "\"";
mitk::StatusBar::GetInstance()->DisplayText(text.c_str());
us::ModuleResource resource = m_ToolManager->GetToolById(id)->GetCursorIconResource();
this->SetMouseCursor(resource, 0, 0);
}
}
void QmitkSegmentationView::OnShowMarkerNodes(bool state)
{
mitk::SegTool2D::Pointer manualSegmentationTool;
unsigned int numberOfExistingTools = m_ToolManager->GetTools().size();
for (unsigned int i = 0; i < numberOfExistingTools; i++)
{
manualSegmentationTool = dynamic_cast<mitk::SegTool2D*>(m_ToolManager->GetToolById(i));
if (nullptr == manualSegmentationTool)
{
continue;
}
manualSegmentationTool->SetShowMarkerNodes(state);
}
}
void QmitkSegmentationView::OnCurrentLabelSelectionChanged(QmitkMultiLabelManager::LabelValueVectorType labels)
{
auto segmentation = this->GetCurrentSegmentation();
const auto labelValue = labels.front();
const auto groupID = segmentation->GetGroupIndexOfLabel(labelValue);
if (groupID != segmentation->GetActiveLayer()) segmentation->SetActiveLayer(groupID);
if (labelValue != segmentation->GetActiveLabelSet()->GetActiveLabel()->GetValue()) segmentation->GetActiveLabelSet()->SetActiveLabel(labelValue);
segmentation->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSegmentationView::OnGoToLabel(mitk::LabelSetImage::LabelValueType /*label*/, const mitk::Point3D& pos)
{
if (m_RenderWindowPart)
{
m_RenderWindowPart->SetSelectedPosition(pos);
}
}
void QmitkSegmentationView::OnLabelRenameRequested(mitk::Label* label, bool rename) const
{
auto segmentation = this->GetCurrentSegmentation();
if (rename)
{
QmitkNewSegmentationDialog::DoRenameLabel(label, segmentation, this->m_Parent, QmitkNewSegmentationDialog::Mode::RenameLabel);
return;
}
QmitkNewSegmentationDialog::DoRenameLabel(label, nullptr, this->m_Parent, QmitkNewSegmentationDialog::Mode::NewLabel);
}
mitk::LabelSetImage* QmitkSegmentationView::GetCurrentSegmentation() const
{
auto workingNode = m_Controls->workingNodeSelector->GetSelectedNode();
if (workingNode.IsNull()) mitkThrow() << "Segmentation view is in an invalid state. Working node is null, but a label selection change has been triggered.";
auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
if (nullptr == segmentation) mitkThrow() << "Segmentation view is in an invalid state. Working node contains no segmentation, but a label selection change has been triggered.";
return segmentation;
}
/**********************************************************************/
/* private */
/**********************************************************************/
void QmitkSegmentationView::CreateQtPartControl(QWidget* parent)
{
m_Parent = parent;
m_Controls = new Ui::QmitkSegmentationViewControls;
m_Controls->setupUi(parent);
// *------------------------
// * SHORTCUTS
// *------------------------
QShortcut* visibilityShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key::Key_H), parent);
- connect(visibilityShortcut, &QShortcut::activated, this, &QmitkSegmentationView::OnVisibilityShortcutActivated);
+ connect(visibilityShortcut, &QShortcut::activated, this, &Self::OnVisibilityShortcutActivated);
QShortcut* labelToggleShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key::Key_L, Qt::CTRL | Qt::Key::Key_I), parent);
- connect(labelToggleShortcut, &QShortcut::activated, this, &QmitkSegmentationView::OnLabelToggleShortcutActivated);
+ connect(labelToggleShortcut, &QShortcut::activated, this, &Self::OnLabelToggleShortcutActivated);
// *------------------------
// * DATA SELECTION WIDGETS
// *------------------------
m_Controls->referenceNodeSelector->SetDataStorage(GetDataStorage());
m_Controls->referenceNodeSelector->SetNodePredicate(m_ReferencePredicate);
m_Controls->referenceNodeSelector->SetInvalidInfo("Select an image");
m_Controls->referenceNodeSelector->SetPopUpTitel("Select an image");
m_Controls->referenceNodeSelector->SetPopUpHint("Select an image that should be used to define the geometry and bounds of the segmentation.");
m_Controls->workingNodeSelector->SetDataStorage(GetDataStorage());
m_Controls->workingNodeSelector->SetNodePredicate(m_SegmentationPredicate);
m_Controls->workingNodeSelector->SetInvalidInfo("Select a segmentation");
m_Controls->workingNodeSelector->SetPopUpTitel("Select a segmentation");
m_Controls->workingNodeSelector->SetPopUpHint("Select a segmentation that should be modified. Only segmentation with the same geometry and within the bounds of the reference image are selected.");
connect(m_Controls->referenceNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
- this, &QmitkSegmentationView::OnReferenceSelectionChanged);
+ this, &Self::OnReferenceSelectionChanged);
connect(m_Controls->workingNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
- this, &QmitkSegmentationView::OnSegmentationSelectionChanged);
+ this, &Self::OnSegmentationSelectionChanged);
// *------------------------
// * TOOLMANAGER
// *------------------------
m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
m_ToolManager->SetDataStorage(*(this->GetDataStorage()));
m_ToolManager->InitializeTools();
QString segTools2D = tr("Add Subtract Lasso Fill Erase Close Paint Wipe 'Region Growing' 'Live Wire'");
QString segTools3D = tr("Threshold 'UL Threshold' Otsu 'Region Growing 3D' Picking GrowCut TotalSegmentator MonaiLabel");
#ifdef __linux__
segTools3D.append(" nnUNet"); // plugin not enabled for MacOS / Windows
#endif
std::regex extSegTool2DRegEx("SegTool2D$");
std::regex extSegTool3DRegEx("SegTool3D$");
auto tools = m_ToolManager->GetTools();
for (const auto &tool : tools)
{
if (std::regex_search(tool->GetNameOfClass(), extSegTool2DRegEx))
{
segTools2D.append(QString(" '%1'").arg(tool->GetName()));
}
else if (std::regex_search(tool->GetNameOfClass(), extSegTool3DRegEx))
{
segTools3D.append(QString(" '%1'").arg(tool->GetName()));
}
}
// setup 2D tools
m_Controls->toolSelectionBox2D->SetToolManager(*m_ToolManager);
m_Controls->toolSelectionBox2D->SetGenerateAccelerators(true);
m_Controls->toolSelectionBox2D->SetToolGUIArea(m_Controls->toolGUIArea2D);
m_Controls->toolSelectionBox2D->SetDisplayedToolGroups(segTools2D.toStdString());
connect(m_Controls->toolSelectionBox2D, &QmitkToolSelectionBox::ToolSelected,
- this, &QmitkSegmentationView::OnManualTool2DSelected);
+ this, &Self::OnManualTool2DSelected);
// setup 3D Tools
m_Controls->toolSelectionBox3D->SetToolManager(*m_ToolManager);
m_Controls->toolSelectionBox3D->SetGenerateAccelerators(true);
m_Controls->toolSelectionBox3D->SetToolGUIArea(m_Controls->toolGUIArea3D);
m_Controls->toolSelectionBox3D->SetDisplayedToolGroups(segTools3D.toStdString());
m_Controls->slicesInterpolator->SetDataStorage(this->GetDataStorage());
// create general signal / slot connections
- connect(m_Controls->newSegmentationButton, &QToolButton::clicked, this, &QmitkSegmentationView::OnNewSegmentation);
+ connect(m_Controls->newSegmentationButton, &QToolButton::clicked, this, &Self::OnNewSegmentation);
- connect(m_Controls->slicesInterpolator, &QmitkSlicesInterpolator::SignalShowMarkerNodes, this, &QmitkSegmentationView::OnShowMarkerNodes);
+ connect(m_Controls->slicesInterpolator, &QmitkSlicesInterpolator::SignalShowMarkerNodes, this, &Self::OnShowMarkerNodes);
- connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::CurrentSelectionChanged, this, &QmitkSegmentationView::OnCurrentLabelSelectionChanged);
- connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::GoToLabel, this, &QmitkSegmentationView::OnGoToLabel);
- connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::LabelRenameRequested, this, &QmitkSegmentationView::OnLabelRenameRequested);
+ connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::CurrentSelectionChanged, this, &Self::OnCurrentLabelSelectionChanged);
+ connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::GoToLabel, this, &Self::OnGoToLabel);
+ connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::LabelRenameRequested, this, &Self::OnLabelRenameRequested);
- auto command = itk::SimpleMemberCommand<QmitkSegmentationView>::New();
- command->SetCallbackFunction(this, &QmitkSegmentationView::ValidateSelectionInput);
+ auto command = itk::SimpleMemberCommand<Self>::New();
+ command->SetCallbackFunction(this, &Self::ValidateSelectionInput);
m_RenderingManagerObserverTag =
mitk::RenderingManager::GetInstance()->AddObserver(mitk::RenderingManagerViewsInitializedEvent(), command);
m_RenderWindowPart = this->GetRenderWindowPart();
if (nullptr != m_RenderWindowPart)
{
this->RenderWindowPartActivated(m_RenderWindowPart);
}
// Make sure the GUI notices if appropriate data is already present on creation.
// Should be done last, if everything else is configured because it triggers the autoselection of data.
m_Controls->referenceNodeSelector->SetAutoSelectNewNodes(true);
m_Controls->workingNodeSelector->SetAutoSelectNewNodes(true);
this->UpdateGUI();
}
void QmitkSegmentationView::ActiveToolChanged()
{
if (nullptr == m_RenderWindowPart)
{
return;
}
mitk::TimeGeometry* interactionReferenceGeometry = nullptr;
auto activeTool = m_ToolManager->GetActiveTool();
if (nullptr != activeTool && m_ReferenceNode.IsNotNull())
{
mitk::Image::ConstPointer referenceImage = dynamic_cast<mitk::Image *>(m_ReferenceNode->GetData());
if (referenceImage.IsNotNull())
{
// tool activated, reference image available: set reference geometry
interactionReferenceGeometry = m_ReferenceNode->GetData()->GetTimeGeometry();
}
}
// set the interaction reference geometry for the render window part (might be nullptr)
m_RenderWindowPart->SetInteractionReferenceGeometry(interactionReferenceGeometry);
}
void QmitkSegmentationView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
{
if (m_RenderWindowPart != renderWindowPart)
{
m_RenderWindowPart = renderWindowPart;
}
if (nullptr != m_Parent)
{
m_Parent->setEnabled(true);
}
if (nullptr == m_Controls)
{
return;
}
if (nullptr != m_RenderWindowPart)
{
auto all2DWindows = Get2DWindows(m_RenderWindowPart->GetQmitkRenderWindows().values());
m_Controls->slicesInterpolator->Initialize(m_ToolManager, all2DWindows);
if (!m_RenderWindowPart->HasCoupledRenderWindows())
{
// react if the active tool changed, only if a render window part with decoupled render windows is used
m_ToolManager->ActiveToolChanged +=
- mitk::MessageDelegate<QmitkSegmentationView>(this, &QmitkSegmentationView::ActiveToolChanged);
+ mitk::MessageDelegate<Self>(this, &Self::ActiveToolChanged);
}
}
}
void QmitkSegmentationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/)
{
m_RenderWindowPart = nullptr;
if (nullptr != m_Parent)
{
m_Parent->setEnabled(false);
}
// remove message-connection to make sure no message is processed if no render window part is available
m_ToolManager->ActiveToolChanged -=
- mitk::MessageDelegate<QmitkSegmentationView>(this, &QmitkSegmentationView::ActiveToolChanged);
+ mitk::MessageDelegate<Self>(this, &Self::ActiveToolChanged);
m_Controls->slicesInterpolator->Uninitialize();
}
void QmitkSegmentationView::RenderWindowPartInputChanged(mitk::IRenderWindowPart* /*renderWindowPart*/)
{
if (nullptr == m_RenderWindowPart)
{
return;
}
m_Controls->slicesInterpolator->Uninitialize();
auto all2DWindows = Get2DWindows(m_RenderWindowPart->GetQmitkRenderWindows().values());
m_Controls->slicesInterpolator->Initialize(m_ToolManager, all2DWindows);
}
void QmitkSegmentationView::OnPreferencesChanged(const mitk::IPreferences* prefs)
{
auto labelSuggestions = mitk::BaseApplication::instance().config().getString(mitk::BaseApplication::ARG_SEGMENTATION_LABEL_SUGGESTIONS.toStdString(), "");
m_DefaultLabelNaming = labelSuggestions.empty()
? prefs->GetBool("default label naming", true)
: false; // No default label naming when label suggestions are enforced via command-line argument
if (nullptr != m_Controls)
{
m_Controls->multiLabelWidget->SetDefaultLabelNaming(m_DefaultLabelNaming);
bool compactView = prefs->GetBool("compact view", false);
int numberOfColumns = compactView ? 6 : 4;
m_Controls->toolSelectionBox2D->SetLayoutColumns(numberOfColumns);
m_Controls->toolSelectionBox2D->SetShowNames(!compactView);
m_Controls->toolSelectionBox3D->SetLayoutColumns(numberOfColumns);
m_Controls->toolSelectionBox3D->SetShowNames(!compactView);
}
m_DrawOutline = prefs->GetBool("draw outline", true);
m_SelectionMode = prefs->GetBool("selection mode", false);
m_LabelSetPresetPreference = QString::fromStdString(prefs->Get("label set preset", ""));
this->ApplyDisplayOptions();
this->ApplySelectionMode();
}
void QmitkSegmentationView::NodeAdded(const mitk::DataNode* node)
{
if (m_SegmentationPredicate->CheckNode(node))
this->ApplyDisplayOptions(const_cast<mitk::DataNode*>(node));
this->ApplySelectionMode();
}
void QmitkSegmentationView::NodeRemoved(const mitk::DataNode* node)
{
if (!m_SegmentationPredicate->CheckNode(node))
{
return;
}
// remove all possible contour markers of the segmentation
mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations(
node, mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)));
ctkPluginContext* context = mitk::PluginActivator::getContext();
ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it)
{
std::string nodeName = node->GetName();
unsigned int t = nodeName.find_last_of(" ");
unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1;
service->RemovePlanePosition(id);
this->GetDataStorage()->Remove(it->Value());
}
context->ungetService(ppmRef);
service = nullptr;
mitk::Image* image = dynamic_cast<mitk::Image*>(node->GetData());
mitk::SurfaceInterpolationController::GetInstance()->RemoveInterpolationSession(image);
}
void QmitkSegmentationView::ApplyDisplayOptions()
{
if (nullptr == m_Parent)
{
return;
}
if (nullptr == m_Controls)
{
return; // might happen on initialization (preferences loaded)
}
mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDataStorage()->GetSubset(m_SegmentationPredicate);
for (mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter)
{
this->ApplyDisplayOptions(*iter);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSegmentationView::ApplyDisplayOptions(mitk::DataNode* node)
{
if (nullptr == node)
{
return;
}
auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(node->GetData());
if (nullptr == labelSetImage)
{
return;
}
// the outline property can be set in the segmentation preference page
node->SetProperty("labelset.contour.active", mitk::BoolProperty::New(m_DrawOutline));
// force render window update to show outline
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkSegmentationView::ApplySelectionMode()
{
if (!m_SelectionMode)
return;
this->ApplySelectionModeOnReferenceNode();
this->ApplySelectionModeOnWorkingNode();
}
void QmitkSegmentationView::ApplySelectionModeOnReferenceNode()
{
this->ApplySelectionMode(m_ReferenceNode, m_ReferencePredicate);
}
void QmitkSegmentationView::ApplySelectionModeOnWorkingNode()
{
this->ApplySelectionMode(m_WorkingNode, m_SegmentationPredicate);
}
void QmitkSegmentationView::ApplySelectionMode(mitk::DataNode* node, mitk::NodePredicateBase* predicate)
{
if (!m_SelectionMode || node == nullptr || predicate == nullptr)
return;
auto nodes = this->GetDataStorage()->GetSubset(predicate);
for (auto iter = nodes->begin(); iter != nodes->end(); ++iter)
(*iter)->SetVisibility(*iter == node);
}
void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode* node)
{
QmitkRenderWindow* selectedRenderWindow = nullptr;
auto* renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN);
auto* axialRenderWindow = renderWindowPart->GetQmitkRenderWindow("axial");
auto* sagittalRenderWindow = renderWindowPart->GetQmitkRenderWindow("sagittal");
auto* coronalRenderWindow = renderWindowPart->GetQmitkRenderWindow("coronal");
auto* threeDRenderWindow = renderWindowPart->GetQmitkRenderWindow("3d");
bool PlanarFigureInitializedWindow = false;
// find initialized renderwindow
if (node->GetBoolProperty("PlanarFigureInitializedWindow",
PlanarFigureInitializedWindow, axialRenderWindow->GetRenderer()))
{
selectedRenderWindow = axialRenderWindow;
}
if (!selectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
sagittalRenderWindow->GetRenderer()))
{
selectedRenderWindow = sagittalRenderWindow;
}
if (!selectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
coronalRenderWindow->GetRenderer()))
{
selectedRenderWindow = coronalRenderWindow;
}
if (!selectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
threeDRenderWindow->GetRenderer()))
{
selectedRenderWindow = threeDRenderWindow;
}
// make node visible
if (nullptr != selectedRenderWindow)
{
std::string nodeName = node->GetName();
unsigned int t = nodeName.find_last_of(" ");
unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1;
ctkPluginContext* context = mitk::PluginActivator::getContext();
ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
selectedRenderWindow->GetSliceNavigationController()->ExecuteOperation(service->GetPlanePosition(id));
context->ungetService(ppmRef);
selectedRenderWindow->GetRenderer()->GetCameraController()->Fit();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkSegmentationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
if (0 == nodes.size())
{
return;
}
std::string markerName = "Position";
unsigned int numberOfNodes = nodes.size();
std::string nodeName = nodes.at(0)->GetName();
if ((numberOfNodes == 1) && (nodeName.find(markerName) == 0))
{
this->OnContourMarkerSelected(nodes.at(0));
return;
}
}
void QmitkSegmentationView::ResetMouseCursor()
{
if (m_MouseCursorSet)
{
mitk::ApplicationCursor::GetInstance()->PopCursor();
m_MouseCursorSet = false;
}
}
void QmitkSegmentationView::SetMouseCursor(const us::ModuleResource& resource, int hotspotX, int hotspotY)
{
// Remove previously set mouse cursor
if (m_MouseCursorSet)
{
this->ResetMouseCursor();
}
if (resource)
{
us::ModuleResourceStream cursor(resource, std::ios::binary);
mitk::ApplicationCursor::GetInstance()->PushCursor(cursor, hotspotX, hotspotY);
m_MouseCursorSet = true;
}
}
void QmitkSegmentationView::UpdateGUI()
{
mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0);
bool hasReferenceNode = referenceNode != nullptr;
mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0);
bool hasWorkingNode = workingNode != nullptr;
m_Controls->newSegmentationButton->setEnabled(false);
if (hasReferenceNode)
{
m_Controls->newSegmentationButton->setEnabled(true);
}
if (hasWorkingNode && hasReferenceNode)
{
int layer = -1;
referenceNode->GetIntProperty("layer", layer);
workingNode->SetIntProperty("layer", layer + 1);
}
this->ValidateSelectionInput();
}
void QmitkSegmentationView::ValidateSelectionInput()
{
auto referenceNode = m_Controls->referenceNodeSelector->GetSelectedNode();
auto workingNode = m_Controls->workingNodeSelector->GetSelectedNode();
bool hasReferenceNode = referenceNode.IsNotNull();
bool hasWorkingNode = workingNode.IsNotNull();
bool hasBothNodes = hasReferenceNode && hasWorkingNode;
QString warning;
bool toolSelectionBoxesEnabled = hasReferenceNode && hasWorkingNode;
unsigned int numberOfLabels = 0;
m_Controls->multiLabelWidget->setEnabled(hasWorkingNode);
m_Controls->toolSelectionBox2D->setEnabled(hasBothNodes);
m_Controls->toolSelectionBox3D->setEnabled(hasBothNodes);
m_Controls->slicesInterpolator->setEnabled(false);
m_Controls->interpolatorWarningLabel->hide();
if (hasReferenceNode)
{
if (nullptr != m_RenderWindowPart && m_RenderWindowPart->HasCoupledRenderWindows() && !referenceNode->IsVisible(nullptr))
{
warning += tr("The selected reference image is currently not visible!");
toolSelectionBoxesEnabled = false;
}
}
if (hasWorkingNode)
{
if (nullptr != m_RenderWindowPart && m_RenderWindowPart->HasCoupledRenderWindows() && !workingNode->IsVisible(nullptr))
{
warning += (!warning.isEmpty() ? "<br>" : "") + tr("The selected segmentation is currently not visible!");
toolSelectionBoxesEnabled = false;
}
m_ToolManager->SetReferenceData(referenceNode);
m_ToolManager->SetWorkingData(workingNode);
m_Controls->multiLabelWidget->setEnabled(true);
m_Controls->toolSelectionBox2D->setEnabled(true);
m_Controls->toolSelectionBox3D->setEnabled(true);
auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
- auto activeLayer = labelSetImage->GetActiveLayer();
- numberOfLabels = labelSetImage->GetNumberOfLabels(activeLayer);
+ numberOfLabels = labelSetImage->GetTotalNumberOfLabels();
if (numberOfLabels > 0)
m_Controls->slicesInterpolator->setEnabled(true);
m_Controls->multiLabelWidget->SetMultiLabelSegmentation(dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData()));
}
else
{
m_Controls->multiLabelWidget->SetMultiLabelSegmentation(nullptr);
}
toolSelectionBoxesEnabled &= numberOfLabels > 0;
// Here we need to check whether the geometry of the selected segmentation image (working image geometry)
// is aligned with the geometry of the 3D render window.
// It is not allowed to use a geometry different from the working image geometry for segmenting.
// We only need to this if the tool selection box would be enabled without this check.
// Additionally this check only has to be performed for render window parts with coupled render windows.
// For different render window parts the user is given the option to reinitialize each render window individually
// (see QmitkRenderWindow::ShowOverlayMessage).
if (toolSelectionBoxesEnabled && nullptr != m_RenderWindowPart && m_RenderWindowPart->HasCoupledRenderWindows())
{
const mitk::BaseGeometry* workingNodeGeometry = workingNode->GetData()->GetGeometry();
const mitk::BaseGeometry* renderWindowGeometry =
m_RenderWindowPart->GetQmitkRenderWindow("3d")->GetSliceNavigationController()->GetCurrentGeometry3D();
if (nullptr != workingNodeGeometry && nullptr != renderWindowGeometry)
{
if (!mitk::Equal(*workingNodeGeometry->GetBoundingBox(), *renderWindowGeometry->GetBoundingBox(), mitk::eps, true))
{
warning += (!warning.isEmpty() ? "<br>" : "") + tr("Please reinitialize the selected segmentation image!");
toolSelectionBoxesEnabled = false;
}
}
}
m_Controls->toolSelectionBox2D->setEnabled(toolSelectionBoxesEnabled);
m_Controls->toolSelectionBox3D->setEnabled(toolSelectionBoxesEnabled);
this->UpdateWarningLabel(warning);
m_ToolManager->SetReferenceData(referenceNode);
m_ToolManager->SetWorkingData(workingNode);
}
void QmitkSegmentationView::UpdateWarningLabel(QString text)
{
if (text.isEmpty())
{
m_Controls->selectionWarningLabel->hide();
}
else
{
m_Controls->selectionWarningLabel->setText("<font color=\"red\">" + text + "</font>");
m_Controls->selectionWarningLabel->show();
}
}
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h
index 93d2058441..0d71e0274c 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h
@@ -1,184 +1,175 @@
/*============================================================================
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 QmitkSegmentationView_h
#define QmitkSegmentationView_h
#include "ui_QmitkSegmentationViewControls.h"
#include <QmitkAbstractView.h>
#include <mitkIRenderWindowPartListener.h>
/**
* @brief The segmentation view provides a set of tool to use different segmentation algorithms.
* It provides two selection widgets to load an image node and a segmentation node
* on which to perform the segmentation. Creating new segmentation nodes is also possible.
* The available segmentation tools are grouped into "2D"- and "3D"-tools.
*
* Most segmentation tools / algorithms need some kind of user interaction, where the
* user is asked to draw something in the image display or set some seed points / start values.
* The tools also often provide additional propeties so that a user can modify the
* algorithm's behavior.
*
* This class additionally provides options to work with different layers (create new layers,
* switch between layers).
* Moreover, a multilabel widget displays all the existing labels of a multilabel segmentation
* for the currently active layer.
* The multilabel widget allows to control the labels by creatin new one, removing existing ones,
* showing / hiding single labels, merging labels, (re-)naming them etc.
*
* Additionally the view provides an option to create "2D"- and "3D"-interpolations between
* neighboring segmentation masks on unsegmented slices.
* Interpolation for multilabel segmentations is currently not implemented.
*/
class QmitkSegmentationView : public QmitkAbstractView, public mitk::IRenderWindowPartListener
{
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkSegmentationView();
~QmitkSegmentationView() override;
private Q_SLOTS:
// reaction to the selection of a new reference image in the selection widget
void OnReferenceSelectionChanged(QList<mitk::DataNode::Pointer> nodes);
// reaction to the selection of a new segmentation image in the selection widget
void OnSegmentationSelectionChanged(QList<mitk::DataNode::Pointer> nodes);
// reaction to the shortcut ("CTRL+H") for toggling the visibility of the working node
void OnVisibilityShortcutActivated();
// reaction to the shortcut ("CTRL+L") for iterating over all labels
void OnLabelToggleShortcutActivated();
// reaction to the button "New segmentation"
void OnNewSegmentation();
void OnManualTool2DSelected(int id);
void OnShowMarkerNodes(bool);
void OnCurrentLabelSelectionChanged(QmitkMultiLabelManager::LabelValueVectorType labels);
void OnGoToLabel(mitk::LabelSetImage::LabelValueType label, const mitk::Point3D&);
void OnLabelRenameRequested(mitk::Label* label, bool rename) const;
+ void OnLabelAdded(mitk::LabelSetImage::LabelValueType labelValue);
+ void OnLabelRemoved(mitk::LabelSetImage::LabelValueType labelValue);
+ void OnGroupRemoved(mitk::LabelSetImage::GroupIndexType groupIndex);
+
private:
+ using Self = QmitkSegmentationView;
+
+ mitk::LabelSetImage* GetWorkingImage();
+ void AddObserversToWorkingImage();
+ void RemoveObserversFromWorkingImage();
+
void CreateQtPartControl(QWidget* parent) override;
void SetFocus() override {}
/**
* @brief Enable or disable the SegmentationInteractor.
*
* The active tool is retrieved from the tool manager.
* If the active tool is valid, the SegmentationInteractor is enabled
* to listen to 'SegmentationInteractionEvent's.
*/
void ActiveToolChanged();
- /**
- * @brief Test whether the geometry of the reference image
- * fits the world geometry of the respective renderer.
- *
- * The respective renderer is retrieved from the given event, which
- * needs to be a 'SegmentationInteractionEvent'.
- * This event provides not only the sending base renderer but also a
- * bool that indicates whether the mouse cursor entered or left the
- * base renderer.
- * This information is used to compare the renderer's world geometry
- * with the oriented time geometry of the current reference image.
- * If the geometries align, the renderer is not blocked anymore and the
- * view's warning message is removed.
- * If the geometries do not align, 'ShowRenderWindowWarning' is called
- * and a warning message is added to the top of this plugin view.
- *
- * @param event The observed mitk::SegmentationInteractionEvent.
- */
- void ValidateRendererGeometry(const itk::EventObject& event);
void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) override;
void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) override;
void RenderWindowPartInputChanged(mitk::IRenderWindowPart* renderWindowPart) override;
void OnPreferencesChanged(const mitk::IPreferences* prefs) override;
void NodeAdded(const mitk::DataNode* node) override;
void NodeRemoved(const mitk::DataNode* node) override;
void OnAnySelectionChanged();
// make sure all images / segmentations look according to the user preference settings
void ApplyDisplayOptions();
// decorates a DataNode according to the user preference settings
void ApplyDisplayOptions(mitk::DataNode* node);
void ApplySelectionMode();
void ApplySelectionModeOnReferenceNode();
void ApplySelectionModeOnWorkingNode();
void ApplySelectionMode(mitk::DataNode* node, mitk::NodePredicateBase* predicate);
// If a contourmarker is selected, the plane in the related widget will be reoriented according to the marker`s geometry
void OnContourMarkerSelected(const mitk::DataNode* node);
void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer> &nodes) override;
void ResetMouseCursor();
void SetMouseCursor(const us::ModuleResource&, int hotspotX, int hotspotY);
void UpdateGUI();
void ValidateSelectionInput();
void UpdateWarningLabel(QString text);
std::string GetDefaultLabelSetPreset() const;
mitk::LabelSetImage* GetCurrentSegmentation() const;
QWidget* m_Parent;
Ui::QmitkSegmentationViewControls* m_Controls;
mitk::IRenderWindowPart* m_RenderWindowPart;
mitk::ToolManager* m_ToolManager;
mitk::DataNode::Pointer m_ReferenceNode;
mitk::DataNode::Pointer m_WorkingNode;
typedef std::map<mitk::DataNode*, unsigned long> NodeTagMapType;
NodeTagMapType m_WorkingDataObserverTags;
NodeTagMapType m_ReferenceDataObserverTags;
unsigned int m_RenderingManagerObserverTag;
mitk::NodePredicateAnd::Pointer m_ReferencePredicate;
mitk::NodePredicateAnd::Pointer m_SegmentationPredicate;
bool m_DrawOutline;
bool m_SelectionMode;
bool m_MouseCursorSet;
QString m_LabelSetPresetPreference;
bool m_DefaultLabelNaming;
bool m_SelectionChangeIsAlreadyBeingHandled;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.tubegraph/src/internal/QmitkTubeGraphLabelWidget.cpp b/Plugins/org.mitk.gui.qt.tubegraph/src/internal/QmitkTubeGraphLabelWidget.cpp
index 05776510ec..ca5289bc97 100644
--- a/Plugins/org.mitk.gui.qt.tubegraph/src/internal/QmitkTubeGraphLabelWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.tubegraph/src/internal/QmitkTubeGraphLabelWidget.cpp
@@ -1,109 +1,109 @@
/*============================================================================
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 "QmitkTubeGraphLabelWidget.h"
#include <QHBoxLayout>
#include <QColorDialog>
QmitkTubeGraphLabelWidget::QmitkTubeGraphLabelWidget(QWidget* parent)
:QWidget(parent)
{
this->InitWidget();
}
QmitkTubeGraphLabelWidget::~QmitkTubeGraphLabelWidget()
{
delete m_VisibilityCheckBox;
delete m_LabelPushButton;
delete m_ColoringPushButton;
}
void QmitkTubeGraphLabelWidget::InitWidget()
{
m_VisibilityCheckBox = new QCheckBox("", this);
m_VisibilityCheckBox->setChecked(true);
m_VisibilityCheckBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
m_LabelPushButton = new QPushButton("", this);
//m_LabelPushButton->setCheckable(true);
//m_LabelPushButton->setAutoExclusive(true);
m_ColoringPushButton = new QPushButton(this);
m_ColoringPushButton->setStyleSheet( QString("* { background-color: rgb(0,0,0)}"));
m_ColoringPushButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
auto layout = new QHBoxLayout;
layout->addWidget(m_VisibilityCheckBox);
layout->addWidget(m_LabelPushButton);
layout->addWidget(m_ColoringPushButton);
this->setLayout(layout);
connect(m_VisibilityCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnVisibilityToggled(bool)));
connect(m_LabelPushButton, SIGNAL(clicked()), this, SLOT(OnLabelButtonClicked()));
connect(m_ColoringPushButton, SIGNAL(clicked()), this, SLOT(OnColoringButtonClicked()));
//connect(m_ColoringPushButton, SIGNAL(clicked()), this, SIGNAL(SignalLabelColorChanged(this->GetLabelName())));
}
void QmitkTubeGraphLabelWidget::SetLabelName(QString name)
{
m_LabelPushButton->setText(name);
}
QString QmitkTubeGraphLabelWidget::GetLabelName()
{
return m_LabelPushButton->text();
}
void QmitkTubeGraphLabelWidget::SetLabelColor(mitk::Color* color)
{
m_ColoringPushButton->setStyleSheet( QString("* { background-color: rgb(%1,%2,%3)}").arg(color->GetRed()).arg(color->GetGreen()).arg(color->GetBlue()) );
}
mitk::Color* QmitkTubeGraphLabelWidget::GetLabelColor()
{
//return the background color of the button
const QColor color = m_ColoringPushButton->palette().color(QPalette::Button);
- auto rgb = new mitk::Color();
- rgb[0] = color.red(); rgb[1] = color.green(); rgb[2] = color.blue();
+ auto rgb = new mitk::Color();
+ rgb->Set(color.red(), color.green(), color.blue());
return rgb;
}
void QmitkTubeGraphLabelWidget::OnVisibilityToggled(bool isVisible)
{
emit SignalLabelVisibilityToggled(isVisible, this->GetLabelName());
}
void QmitkTubeGraphLabelWidget::OnLabelButtonClicked()
{
emit SignalLabelButtonClicked(this->GetLabelName());
}
void QmitkTubeGraphLabelWidget::OnColoringButtonClicked()
{
QColor usersChoice = QColorDialog::getColor();
mitk::Color color;
if (usersChoice.spec() != 0)
{
color[0] = usersChoice.red();
color[1] = usersChoice.green();
color[2] = usersChoice.blue();
this->SetLabelColor(&color);
emit SignalLabelColorChanged(color, this->GetLabelName());
}
}
diff --git a/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkViewNavigatorWidget.cpp b/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkViewNavigatorWidget.cpp
index 975285c71a..d431fa5643 100644
--- a/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkViewNavigatorWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkViewNavigatorWidget.cpp
@@ -1,716 +1,730 @@
/*============================================================================
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.
============================================================================*/
// View navigator plugin
#include <QmitkViewNavigatorWidget.h>
#include <QmitkPerspectiveItem.h>
#include <QmitkViewItem.h>
// Blueberry
#include <berryIWorkbenchWindow.h>
#include <berryIPerspectiveRegistry.h>
#include <berryPlatform.h>
#include <berryIWorkbenchPage.h>
#include <berryIExtensionRegistry.h>
#include <berryIHandlerService.h>
#include <berryIWorkbenchCommandConstants.h>
#include <berryUIElement.h>
// MITK
-#include <mitkLogMacros.h>
+#include <mitkLog.h>
// Qt
#include <QHash>
#include <QInputDialog>
#include <QMessageBox>
#include <QStandardItem>
#include <QSortFilterProxyModel>
+namespace
+{
+ QFont getLargeFont()
+ {
+ QFont font = qApp->font();
+ font.setPointSizeF(font.pointSizeF() * 1.25f);
+ return font;
+ }
+}
+
class KeywordRegistry
{
public:
KeywordRegistry()
{
berry::IExtensionRegistry* extensionPointService = berry::Platform::GetExtensionRegistry();
auto keywordExts = extensionPointService->GetConfigurationElementsFor("org.blueberry.ui.keywords");
for (auto keywordExtsIt = keywordExts.begin(); keywordExtsIt != keywordExts.end(); ++keywordExtsIt)
{
QString keywordId = (*keywordExtsIt)->GetAttribute("id");
QString keywordLabels = (*keywordExtsIt)->GetAttribute("label");
m_Keywords[keywordId].push_back(keywordLabels);
}
}
QStringList GetKeywords(const QString& id)
{
return m_Keywords[id];
}
QStringList GetKeywords(const QStringList& ids)
{
QStringList result;
for (const auto& id : ids)
{
result.append(this->GetKeywords(id));
}
return result;
}
private:
QHash<QString, QStringList> m_Keywords;
};
class ClassFilterProxyModel : public QSortFilterProxyModel
{
public:
ClassFilterProxyModel(QObject* parent = nullptr)
: QSortFilterProxyModel(parent)
{
}
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override
{
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
return hasToBeDisplayed(index);
}
private:
bool displayElement(const QModelIndex index) const
{
QString type = sourceModel()->data(index, Qt::DisplayRole).toString();
QStandardItem* item = dynamic_cast<QStandardItemModel*>(sourceModel())->itemFromIndex(index);
if (type.contains(filterRegExp()))
{
return true;
}
QmitkViewItem* viewItem = dynamic_cast<QmitkViewItem*>(item);
if (nullptr != viewItem)
{
for (const auto& tag : viewItem->m_Tags)
{
if (tag.contains(filterRegExp()))
{
return true;
}
}
if (viewItem->m_Description.contains(filterRegExp()))
{
return true;
}
}
QmitkPerspectiveItem* perspectiveItem = dynamic_cast<QmitkPerspectiveItem*>(item);
if (nullptr != perspectiveItem)
{
for (const auto& tag : perspectiveItem->m_Tags)
{
if (tag.contains(filterRegExp()))
{
return true;
}
}
if (perspectiveItem->m_Description.contains(filterRegExp()))
{
return true;
}
}
return false;
}
bool hasToBeDisplayed(const QModelIndex index) const
{
bool result = false;
if (sourceModel()->rowCount(index) > 0)
{
for (int i = 0; i < sourceModel()->rowCount(index); i++)
{
QModelIndex childIndex = sourceModel()->index(i, 0, index);
if (!childIndex.isValid())
{
break;
}
result = hasToBeDisplayed(childIndex);
result |= displayElement(index);
if (result)
{
break;
}
}
}
else
{
result = displayElement(index);
}
return result;
}
};
class ViewNavigatorPerspectiveListener: public berry::IPerspectiveListener
{
public:
ViewNavigatorPerspectiveListener(QmitkViewNavigatorWidget* parent)
: m_ParentWidget(parent)
{
}
Events::Types GetPerspectiveEventTypes() const override
{
return Events::ACTIVATED | Events::SAVED_AS | Events::DEACTIVATED
// remove the following line when command framework is finished
| Events::CLOSED | Events::OPENED | Events::PART_CHANGED;
}
void PerspectiveActivated(const berry::IWorkbenchPage::Pointer& /*page*/,
const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override
{
m_ParentWidget->UpdateTreeList();
}
void PerspectiveSavedAs(const berry::IWorkbenchPage::Pointer& /*page*/,
const berry::IPerspectiveDescriptor::Pointer& /*oldPerspective*/,
const berry::IPerspectiveDescriptor::Pointer& /*newPerspective*/) override
{
m_ParentWidget->UpdateTreeList();
}
void PerspectiveDeactivated(const berry::IWorkbenchPage::Pointer& /*page*/,
const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override
{
m_ParentWidget->m_ActivePerspective = nullptr;
}
void PerspectiveOpened(const berry::IWorkbenchPage::Pointer& /*page*/,
const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override
{
m_ParentWidget->UpdateTreeList();
}
void PerspectiveClosed(const berry::IWorkbenchPage::Pointer& /*page*/,
const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override
{
m_ParentWidget->m_ActivePerspective = nullptr;
}
using IPerspectiveListener::PerspectiveChanged;
void PerspectiveChanged(const berry::IWorkbenchPage::Pointer& /*page*/,
const berry::IPerspectiveDescriptor::Pointer& /*perspective*/,
const berry::IWorkbenchPartReference::Pointer& partRef, const std::string& changeId)
{
if (changeId == "viewHide" && partRef->GetId() == "org.mitk.views.viewnavigator")
berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->RemovePerspectiveListener(m_ParentWidget->m_PerspectiveListener.data());
else
m_ParentWidget->UpdateTreeList();
}
private:
QmitkViewNavigatorWidget* m_ParentWidget;
};
class ViewNavigatorViewListener: public berry::IPartListener
{
public:
ViewNavigatorViewListener(QmitkViewNavigatorWidget* parent)
: m_ParentWidget(parent)
{
}
Events::Types GetPartEventTypes() const override
{
return Events::OPENED | Events::CLOSED;
}
void PartOpened(const berry::IWorkbenchPartReference::Pointer& partRef) override
{
if (partRef->GetId() != "org.mitk.views.viewnavigator")
{
m_ParentWidget->UpdateTreeList((partRef->GetPart(false)).GetPointer());
}
else
{
m_ParentWidget->FillTreeList();
m_ParentWidget->UpdateTreeList();
}
}
void PartClosed(const berry::IWorkbenchPartReference::Pointer& partRef) override
{
if (partRef->GetId() != "org.mitk.views.viewnavigator")
{
m_ParentWidget->UpdateTreeList();
}
}
private:
QmitkViewNavigatorWidget* m_ParentWidget;
};
bool compareViews(const berry::IViewDescriptor::Pointer& a, const berry::IViewDescriptor::Pointer& b)
{
if (a.IsNull() || b.IsNull())
{
return false;
}
return a->GetLabel().compare(b->GetLabel()) < 0;
}
bool comparePerspectives(const berry::IPerspectiveDescriptor::Pointer& a, const berry::IPerspectiveDescriptor::Pointer& b)
{
if (a.IsNull() || b.IsNull())
{
return false;
}
return a->GetLabel().compare(b->GetLabel()) < 0;
}
bool compareQStandardItems(const QStandardItem* a, const QStandardItem* b)
{
if (nullptr == a || nullptr== b)
{
return false;
}
return a->text().compare(b->text()) < 0;
}
QmitkViewNavigatorWidget::QmitkViewNavigatorWidget(berry::IWorkbenchWindow::Pointer window,
QWidget* parent,
Qt::WindowFlags)
: QWidget(parent)
, m_Window(window)
{
this->CreateQtPartControl(this);
}
QmitkViewNavigatorWidget::~QmitkViewNavigatorWidget()
{
m_Window->RemovePerspectiveListener(m_PerspectiveListener.data());
m_Window->GetPartService()->RemovePartListener(m_ViewPartListener.data());
}
void QmitkViewNavigatorWidget::SetFocus()
{
m_Controls.lineEdit->setFocus();
}
void QmitkViewNavigatorWidget::UpdateTreeList(berry::IWorkbenchPart* workbenchPart)
{
berry::IWorkbenchPage::Pointer page = m_Window->GetActivePage();
if (page.IsNull())
{
return;
}
m_ActivePerspective = page->GetPerspective();
QList<berry::IViewPart::Pointer> viewParts = page->GetViews();
// iterate over all tree items
for (const auto& item : m_TreeModel->findItems("*", Qt::MatchWildcard | Qt::MatchRecursive))
{
- QFont font;
+ QFont font = qApp->font();
// check if the item is a view item and if it is equal to any opened view
QmitkViewItem* viewItem = dynamic_cast<QmitkViewItem *>(item);
if (nullptr != viewItem)
{
if (nullptr != workbenchPart && workbenchPart->GetPartName() == viewItem->m_ItemDescriptor->GetLabel())
{
font.setBold(true);
}
else
{
for (const auto& viewPart : viewParts)
{
if (viewPart->GetPartName() == viewItem->m_ItemDescriptor->GetLabel())
{
font.setBold(true);
break;
}
}
}
viewItem->setFont(font);
}
else
{
// check if the item is a perspective item and if it is equal to the current perspective
QmitkPerspectiveItem* perspectiveItem = dynamic_cast<QmitkPerspectiveItem*>(item);
if (nullptr != perspectiveItem)
{
if (m_ActivePerspective.IsNotNull() && m_ActivePerspective->GetId() == perspectiveItem->m_ItemDescriptor->GetId())
{
font.setBold(true);
}
perspectiveItem->setFont(font);
}
}
}
}
bool QmitkViewNavigatorWidget::FillTreeList()
{
// initialize tree model
m_TreeModel->clear();
// add all available views
this->AddViewsToTree();
// add all available perspectives
this->AddPerspectivesToTree();
m_Controls.m_PluginTreeView->expandAll();
return true;
}
void QmitkViewNavigatorWidget::FilterChanged()
{
QString filterString = m_Controls.lineEdit->text();
m_Controls.m_PluginTreeView->expandAll();
Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive;
QString strPattern = "^*" + filterString;
QRegExp regExp(strPattern, caseSensitivity);
m_FilterProxyModel->setFilterRegExp(regExp);
}
void QmitkViewNavigatorWidget::ItemClicked(const QModelIndex &index)
{
QStandardItem* item = m_TreeModel->itemFromIndex(m_FilterProxyModel->mapToSource(index));
QmitkPerspectiveItem* perspectiveItem = dynamic_cast<QmitkPerspectiveItem*>(item);
if (nullptr != perspectiveItem)
{
try
{
berry::PlatformUI::GetWorkbench()->ShowPerspective(
perspectiveItem->m_ItemDescriptor->GetId(), berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow());
}
catch (...)
{
QMessageBox::critical(nullptr, "Opening Perspective Failed",
QString("The requested perspective could not be opened.\nSee the log for details."));
}
return;
}
QmitkViewItem* viewItem = dynamic_cast<QmitkViewItem*>(item);
if (nullptr != viewItem)
{
berry::IWorkbenchPage::Pointer page =
berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage();
if (page.IsNotNull())
{
try
{
page->ShowView(viewItem->m_ItemDescriptor->GetId());
}
catch (const berry::PartInitException& e)
{
BERRY_ERROR << "Error: " << e.what() << std::endl;
}
}
}
}
void QmitkViewNavigatorWidget::SaveCurrentPerspectiveAs()
{
berry::IWorkbenchPage::Pointer page = m_Window->GetActivePage();
berry::IPerspectiveDescriptor::Pointer currentPerspective = page->GetPerspective();
bool ok = false;
QString perspectiveLabel = QInputDialog::getText(this, "Save perspective as ...",
"New perspective name:", QLineEdit::Normal,
"", &ok);
if (!ok)
{
return;
}
if (perspectiveLabel.isEmpty())
{
QMessageBox::information(this, "Save perspective as ...", "Please select a valid perspective name.");
return;
}
berry::IPerspectiveRegistry* perspectiveRegistry = berry::PlatformUI::GetWorkbench()->GetPerspectiveRegistry();
berry::IPerspectiveDescriptor::Pointer newPerspective = perspectiveRegistry->CreatePerspective(perspectiveLabel, currentPerspective);
if (nullptr == newPerspective)
{
QMessageBox::information(this, "Save perspective as ...", "The selected perspective name is already in use.");
return;
}
page->SavePerspectiveAs(newPerspective);
this->FillTreeList();
this->UpdateTreeList();
}
void QmitkViewNavigatorWidget::ResetCurrentPerspective()
{
if (QMessageBox::Yes == QMessageBox(QMessageBox::Question, "Please confirm",
"Do you really want to reset the current perspective?",
QMessageBox::Yes | QMessageBox::No).exec())
{
berry::IWorkbenchPage::Pointer page = m_Window->GetActivePage();
page->ResetPerspective();
}
}
void QmitkViewNavigatorWidget::ClosePerspective()
{
if (QMessageBox::Yes == QMessageBox(QMessageBox::Question, "Please confirm",
"Do you really want to close the current perspective?",
QMessageBox::Yes | QMessageBox::No).exec())
{
berry::IWorkbenchPage::Pointer page = m_Window->GetActivePage();
page->ClosePerspective(page->GetPerspective(), true, true);
}
}
void QmitkViewNavigatorWidget::CloseAllPerspectives()
{
if (QMessageBox::Yes == QMessageBox(QMessageBox::Question, "Please confirm",
"Do you really want to close all perspectives?",
QMessageBox::Yes | QMessageBox::No).exec())
{
berry::IWorkbenchPage::Pointer page = m_Window->GetActivePage();
page->CloseAllPerspectives(true, true);
}
}
void QmitkViewNavigatorWidget::ExpandAll()
{
m_Controls.m_PluginTreeView->expandAll();
}
void QmitkViewNavigatorWidget::CollapseAll()
{
m_Controls.m_PluginTreeView->collapseAll();
}
void QmitkViewNavigatorWidget::CustomMenuRequested(QPoint pos)
{
QModelIndex index = m_Controls.m_PluginTreeView->indexAt(pos);
QStandardItem* item = m_TreeModel->itemFromIndex(m_FilterProxyModel->mapToSource(index));
if (nullptr == m_ContextMenu)
return;
m_ContextMenu->clear();
QmitkPerspectiveItem* perspectiveItem = dynamic_cast<QmitkPerspectiveItem*>(item);
if (nullptr != perspectiveItem)
{
berry::IPerspectiveDescriptor::Pointer perspectiveDescriptor = perspectiveItem->m_ItemDescriptor;
if (this->m_ActivePerspective.IsNotNull() && this->m_ActivePerspective == perspectiveDescriptor)
{
QAction* saveAsAction = new QAction("Save perspective as ...", this);
m_ContextMenu->addAction(saveAsAction);
connect(saveAsAction, SIGNAL(triggered()), SLOT(SaveCurrentPerspectiveAs()));
m_ContextMenu->addSeparator();
}
}
QAction* resetAction = new QAction("Reset current perspective", this);
m_ContextMenu->addAction(resetAction);
connect(resetAction, SIGNAL(triggered()), SLOT(ResetCurrentPerspective()));
QAction* closeAction = new QAction("Close perspective", this);
m_ContextMenu->addAction(closeAction);
connect(closeAction, SIGNAL(triggered()), SLOT(ClosePerspective()));
QAction* closeAllAction = new QAction("Close all perspectives", this);
m_ContextMenu->addAction(closeAllAction);
connect(closeAllAction, SIGNAL(triggered()), SLOT(CloseAllPerspectives()));
m_ContextMenu->addSeparator();
QAction* expandAction = new QAction("Expand tree", this);
m_ContextMenu->addAction(expandAction);
connect(expandAction, SIGNAL(triggered()), SLOT(ExpandAll()));
QAction* collapseAction = new QAction("Collapse tree", this);
m_ContextMenu->addAction(collapseAction);
connect(collapseAction, SIGNAL(triggered()), SLOT(CollapseAll()));
m_ContextMenu->popup(m_Controls.m_PluginTreeView->viewport()->mapToGlobal(pos));
}
void QmitkViewNavigatorWidget::CreateQtPartControl(QWidget* parent)
{
// active workbench window available?
if (m_Window.IsNull())
{
return;
}
m_Controls.setupUi(parent);
connect(m_Controls.m_PluginTreeView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(CustomMenuRequested(QPoint)));
connect(m_Controls.m_PluginTreeView, SIGNAL(doubleClicked(const QModelIndex&)), SLOT(ItemClicked(const QModelIndex&)));
connect(m_Controls.lineEdit, SIGNAL(textChanged(QString)), SLOT(FilterChanged()));
m_ContextMenu = new QMenu(m_Controls.m_PluginTreeView);
m_Controls.m_PluginTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
// Create a new TreeModel for the data
m_TreeModel = new QStandardItemModel();
m_FilterProxyModel = new ClassFilterProxyModel(this);
m_FilterProxyModel->setSourceModel(m_TreeModel);
m_Controls.m_PluginTreeView->setModel(m_FilterProxyModel);
m_PerspectiveListener.reset(new ViewNavigatorPerspectiveListener(this));
m_Window->AddPerspectiveListener(m_PerspectiveListener.data());
m_ViewPartListener.reset(new ViewNavigatorViewListener(this));
m_Window->GetPartService()->AddPartListener(m_ViewPartListener.data());
}
void QmitkViewNavigatorWidget::AddPerspectivesToTree()
{
berry::IPerspectiveRegistry* perspRegistry = berry::PlatformUI::GetWorkbench()->GetPerspectiveRegistry();
QList<berry::IPerspectiveDescriptor::Pointer> perspectiveDescriptors(perspRegistry->GetPerspectives());
qSort(perspectiveDescriptors.begin(), perspectiveDescriptors.end(), comparePerspectives);
QStandardItem* perspectiveRootItem = new QStandardItem("Perspectives");
- perspectiveRootItem->setFont(QFont("", 12, QFont::Normal));
+ perspectiveRootItem->setFont(getLargeFont());
perspectiveRootItem->setEditable(false);
QStandardItem* treeRootItem = m_TreeModel->invisibleRootItem();
treeRootItem->appendRow(perspectiveRootItem);
this->AddItemsToTree<QList<berry::IPerspectiveDescriptor::Pointer>, QmitkPerspectiveItem>(
perspectiveDescriptors, perspectiveRootItem);
}
void QmitkViewNavigatorWidget::AddViewsToTree()
{
berry::IViewRegistry* viewRegistry = berry::PlatformUI::GetWorkbench()->GetViewRegistry();
QList<berry::IViewDescriptor::Pointer> viewDescriptors(viewRegistry->GetViews());
qSort(viewDescriptors.begin(), viewDescriptors.end(), compareViews);
+ auto largeFont = getLargeFont();
+
QStandardItem* viewRootItem = new QStandardItem("Views");
- viewRootItem->setFont(QFont("", 12, QFont::Normal));
+ viewRootItem->setFont(largeFont);
viewRootItem->setEditable(false);
QStandardItem* treeRootItem = m_TreeModel->invisibleRootItem();
treeRootItem->appendRow(viewRootItem);
QStandardItem* miscellaneousCategoryItem = new QStandardItem("Miscellaneous");
- miscellaneousCategoryItem->setFont(QFont("", 12, QFont::Normal));
+ miscellaneousCategoryItem->setFont(largeFont);
miscellaneousCategoryItem->setEditable(false);
QStringList viewExcludeList;
// internal view used for the intro screen, will crash when opened directly, see T22352
viewExcludeList.append(QString("org.blueberry.ui.internal.introview"));
viewExcludeList.append(QString("org.mitk.views.controlvisualizationpropertiesview"));
viewExcludeList.append(QString("org.mitk.views.modules"));
viewExcludeList.append(QString("org.mitk.views.viewnavigator"));
this->AddItemsToTree<QList<berry::IViewDescriptor::Pointer>, QmitkViewItem>(
viewDescriptors, viewRootItem, miscellaneousCategoryItem, viewExcludeList);
}
template<typename D, typename I>
void QmitkViewNavigatorWidget::AddItemsToTree(D itemDescriptors, QStandardItem* rootItem,
QStandardItem* miscellaneousItem, const QStringList& itemExcludeList)
{
KeywordRegistry keywordRegistry;
std::vector<QStandardItem*> categoryItems;
for (const auto& itemDescriptor : itemDescriptors)
{
bool excludeView = itemExcludeList.contains(itemDescriptor->GetId());
if (excludeView)
{
continue;
}
QIcon icon = itemDescriptor->GetImageDescriptor();
I* item = new I(icon, itemDescriptor->GetLabel());
item->m_ItemDescriptor = itemDescriptor;
item->m_Description = itemDescriptor->GetDescription();
item->setToolTip(itemDescriptor->GetDescription());
QStringList keylist = itemDescriptor->GetKeywordReferences();
item->m_Tags = keywordRegistry.GetKeywords(keylist);
item->setEditable(false);
QStringList categoryPath = itemDescriptor->GetCategoryPath();
if (categoryPath.empty())
{
// If a root item for general / non-categorized item views is given, use it.
// Otherwise put the non-categorized item views into the top root item.
if (nullptr != miscellaneousItem)
{
miscellaneousItem->appendRow(item);
}
else
{
rootItem->appendRow(item);
}
}
else
{
QStandardItem* categoryItem = nullptr;
for (const auto& currentCategoryItem : categoryItems)
{
if (currentCategoryItem->text() == categoryPath.front())
{
categoryItem = currentCategoryItem;
break;
}
}
if (nullptr == categoryItem)
{
categoryItem = new QStandardItem(QIcon(), categoryPath.front());
categoryItems.push_back(categoryItem);
}
- categoryItem->setFont(QFont("", 12, QFont::Normal));
+ auto font = getLargeFont();
+
+ categoryItem->setFont(font);
categoryItem->setEditable(false);
categoryItem->appendRow(item);
}
}
std::sort(categoryItems.begin(), categoryItems.end(), compareQStandardItems);
for (const auto& categoryItem : categoryItems)
{
rootItem->appendRow(categoryItem);
}
if (nullptr != miscellaneousItem && miscellaneousItem->hasChildren())
{
rootItem->appendRow(miscellaneousItem);
}
}
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 0170559e19..cba95f5cf5 100755
--- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp
+++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp
@@ -1,243 +1,245 @@
/*============================================================================
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 <vtkSmartVolumeMapper.h>
#include <mitkImage.h>
+#include <mitkTimeNavigationController.h>
+
#include <mitkTransferFunction.h>
#include <mitkTransferFunctionInitializer.h>
#include <mitkTransferFunctionProperty.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateProperty.h>
#include <mitkProperties.h>
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<mitk::Image>::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<std::string> names;
mitk::TransferFunctionInitializer::GetPresetNames(names);
for (const auto& name : names)
{
m_Controls->transferFunctionGeneratorWidget->AddPreset(QString::fromStdString(name));
}
// see vtkVolumeMapper::BlendModes
m_Controls->blendMode->addItem("Composite", vtkVolumeMapper::COMPOSITE_BLEND);
m_Controls->blendMode->addItem("Maximum intensity", vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND);
m_Controls->blendMode->addItem("Minimum intensity", vtkVolumeMapper::MINIMUM_INTENSITY_BLEND);
m_Controls->blendMode->addItem("Average intensity", vtkVolumeMapper::AVERAGE_INTENSITY_BLEND);
m_Controls->blendMode->addItem("Additive", vtkVolumeMapper::ADDITIVE_BLEND);
connect(m_Controls->volumeSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged,
this, &QmitkVolumeVisualizationView::OnCurrentSelectionChanged);
connect(m_Controls->enableRenderingCB, SIGNAL(toggled(bool)), this, SLOT(OnEnableRendering(bool)));
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->transferFunctionWidget->setEnabled(false);
m_Controls->transferFunctionGeneratorWidget->setEnabled(false);
m_Controls->volumeSelectionWidget->SetAutoSelectNewNodes(true);
this->m_TimePointChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_TimePointChangeListener,
&QmitkSliceNavigationListener::SelectedTimePointChanged,
this,
&QmitkVolumeVisualizationView::OnSelectedTimePointChanged);
}
void QmitkVolumeVisualizationView::RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart)
{
this->m_TimePointChangeListener.RenderWindowPartActivated(renderWindowPart);
}
void QmitkVolumeVisualizationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart)
{
this->m_TimePointChangeListener.RenderWindowPartDeactivated(renderWindowPart);
}
void QmitkVolumeVisualizationView::OnMitkInternalPreset(int mode)
{
auto node = m_SelectedNode.Lock();
if (node.IsNull())
{
return;
}
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<mitk::DataNode::Pointer> nodes)
{
m_SelectedNode = nullptr;
if (nodes.empty() || nodes.front().IsNull())
{
UpdateInterface();
return;
}
auto selectedNode = nodes.front();
auto image = dynamic_cast<mitk::Image*>(selectedNode->GetData());
if (nullptr != image)
{
m_SelectedNode = selectedNode;
}
UpdateInterface();
}
void QmitkVolumeVisualizationView::OnEnableRendering(bool state)
{
auto selectedNode = m_SelectedNode.Lock();
if (selectedNode.IsNull())
{
return;
}
selectedNode->SetProperty("volumerendering", mitk::BoolProperty::New(state));
UpdateInterface();
RequestRenderWindowUpdate();
}
void QmitkVolumeVisualizationView::OnBlendMode(int index)
{
auto selectedNode = m_SelectedNode.Lock();
if (selectedNode.IsNull())
return;
int mode = m_Controls->blendMode->itemData(index).toInt();
selectedNode->SetProperty("volumerendering.blendmode", mitk::IntProperty::New(mode));
this->RequestRenderWindowUpdate();
}
void QmitkVolumeVisualizationView::OnSelectedTimePointChanged(const mitk::TimePointType & /*newTimePoint*/)
{
this->UpdateInterface();
}
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->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->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);
// Determine Combo Box mode
int blendMode;
if (selectedNode->GetIntProperty("volumerendering.blendmode", blendMode))
m_Controls->blendMode->setCurrentIndex(blendMode);
- auto time = this->GetRenderWindowPart()->GetTimeNavigationController()->GetSelectedTimeStep();
- m_Controls->transferFunctionWidget->SetDataNode(selectedNode, time);
+ const auto timeStep = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimeStep();
+ m_Controls->transferFunctionWidget->SetDataNode(selectedNode, timeStep);
m_Controls->transferFunctionWidget->setEnabled(true);
- m_Controls->transferFunctionGeneratorWidget->SetDataNode(selectedNode, time);
+ m_Controls->transferFunctionGeneratorWidget->SetDataNode(selectedNode, timeStep);
m_Controls->transferFunctionGeneratorWidget->setEnabled(true);
}
diff --git a/Plugins/org.mitk.gui.qt.xnat/src/internal/QmitkXnatSessionManager.cpp b/Plugins/org.mitk.gui.qt.xnat/src/internal/QmitkXnatSessionManager.cpp
index c467e93497..e7e098d26c 100644
--- a/Plugins/org.mitk.gui.qt.xnat/src/internal/QmitkXnatSessionManager.cpp
+++ b/Plugins/org.mitk.gui.qt.xnat/src/internal/QmitkXnatSessionManager.cpp
@@ -1,103 +1,103 @@
/*============================================================================
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 "QmitkXnatSessionManager.h"
#include "QmitkXnatTreeBrowserView.h"
#include "org_mitk_gui_qt_xnatinterface_Activator.h"
#include <mitkCoreServices.h>
#include <mitkIPreferencesService.h>
#include <mitkIPreferences.h>
-#include "mitkLogMacros.h"
+#include "mitkLog.h"
#include <QApplication>
#include <QMessageBox>
#include <QNetworkProxy>
#include "ctkXnatSession.h"
#include "ctkXnatException.h"
QmitkXnatSessionManager::QmitkXnatSessionManager()
: m_Session(nullptr)
{
}
QmitkXnatSessionManager::~QmitkXnatSessionManager()
{
if(m_SessionRegistration != nullptr)
{
m_SessionRegistration.Unregister();
}
if(m_Session != nullptr)
{
delete m_Session;
}
}
void QmitkXnatSessionManager::OpenXnatSession()
{
ctkXnatSession* session = mitk::org_mitk_gui_qt_xnatinterface_Activator::GetXnatModuleContext()->GetService(m_SessionRegistration.GetReference());
if(session == nullptr) return;
if(!session->isOpen())
{
session->open();
}
}
void QmitkXnatSessionManager::CreateXnatSession()
{
auto* prefService = mitk::CoreServices::GetPreferencesService();
auto* nodeConnectionPref = prefService->GetSystemPreferences()->Node(QmitkXnatTreeBrowserView::VIEW_ID.toStdString());
QUrl url(QString::fromStdString(nodeConnectionPref->Get("Server Address", "")));
url.setPort(std::stoi(nodeConnectionPref->Get("Port", "")));
ctkXnatLoginProfile profile;
profile.setName("Default");
profile.setServerUrl(url);
profile.setUserName(QString::fromStdString(nodeConnectionPref->Get("Username", "")));
profile.setPassword(QString::fromStdString(nodeConnectionPref->Get("Password", "")));
profile.setDefault(true);
m_Session = new ctkXnatSession(profile);
if (nodeConnectionPref->Get("Proxy Server Address", "").length() != 0)
{
QNetworkProxy proxy;
proxy.setType(QNetworkProxy::HttpProxy);
proxy.setHostName(QString::fromStdString(nodeConnectionPref->Get("Proxy Server Address", "")));
proxy.setPort(QString::fromStdString(nodeConnectionPref->Get("Proxy Port", "")).toUShort());
if (nodeConnectionPref->Get("Proxy Username", "").length() != 0 &&
nodeConnectionPref->Get("Proxy Password", "").length() != 0)
{
proxy.setUser(QString::fromStdString(nodeConnectionPref->Get("Proxy Username", "")));
proxy.setPassword(QString::fromStdString(nodeConnectionPref->Get("Proxy Password", "")));
}
// Setting the proxy
m_Session->setHttpNetworkProxy(proxy);
}
m_SessionRegistration = mitk::org_mitk_gui_qt_xnatinterface_Activator::GetXnatModuleContext()->RegisterService(m_Session);
}
void QmitkXnatSessionManager::CloseXnatSession()
{
ctkXnatSession* session = mitk::org_mitk_gui_qt_xnatinterface_Activator::GetXnatModuleContext()->GetService(m_SessionRegistration.GetReference());
session->close();
m_SessionRegistration.Unregister();
m_SessionRegistration = 0;
delete m_Session;
m_Session = nullptr;
}
diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt
index c1f812e720..54520c7140 100644
--- a/Utilities/CMakeLists.txt
+++ b/Utilities/CMakeLists.txt
@@ -1,7 +1,6 @@
SUPPRESS_ALL_WARNINGS()
set(MITK_MODULE_NAME_REGEX_MATCH )
set(MITK_MODULE_NAME_REGEX_NOT_MATCH )
set(MITK_MODULE_NAME_PREFIX )
-add_subdirectory(mbilog)
add_subdirectory(qtsingleapplication)
diff --git a/Utilities/mbilog/CMakeLists.txt b/Utilities/mbilog/CMakeLists.txt
deleted file mode 100644
index 57d2e11c80..0000000000
--- a/Utilities/mbilog/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-project(mbilog)
-
-option(MBILOG_ENABLE_DEBUG_MESSAGES "Enable extra debug log output" OFF)
-mark_as_advanced(MBILOG_ENABLE_DEBUG_MESSAGES)
-
-if(MBILOG_ENABLE_DEBUG_MESSAGES)
- set(_define_enable_debug "#define MBILOG_ENABLE_DEBUG")
-endif(MBILOG_ENABLE_DEBUG_MESSAGES)
-
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mbilogConfig.cmake.in"
-"${CMAKE_CURRENT_BINARY_DIR}/mbilogConfig.cmake" @ONLY)
-
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mbilogConfig.h.in"
-"${CMAKE_CURRENT_BINARY_DIR}/mbilogConfig.h" @ONLY)
-
-mitk_create_module(
- NO_INIT
-)
diff --git a/Utilities/mbilog/files.cmake b/Utilities/mbilog/files.cmake
deleted file mode 100644
index a339028b0b..0000000000
--- a/Utilities/mbilog/files.cmake
+++ /dev/null
@@ -1,18 +0,0 @@
-set(H_FILES
- mbilog.h
- mbilogLoggingTypes.h
- mbilogTextDictionary.h
- mbilogExports.h
- mbilogLogMessage.h
- mbilogBackendBase.h
- mbilogTextBackendBase.h
- mbilogBackendCout.h
-)
-
-set(CPP_FILES
- mbilog.cpp
- mbilogLogMessage.cpp
- mbilogBackendCout.cpp
- mbilogBackendBase.cpp
- mbilogTextBackendBase.cpp
-)
diff --git a/Utilities/mbilog/mbilog.h b/Utilities/mbilog/mbilog.h
deleted file mode 100644
index 3e797863a3..0000000000
--- a/Utilities/mbilog/mbilog.h
+++ /dev/null
@@ -1,221 +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.
-
-============================================================================*/
-
-#ifndef _MBILOG_H
-#define _MBILOG_H
-
-#include <sstream>
-
-#include "mbilogBackendBase.h"
-#include "mbilogBackendCout.h"
-#include "mbilogConfig.h"
-#include "mbilogExports.h"
-#include "mbilogLogMessage.h"
-#include "mbilogLoggingTypes.h"
-
-namespace mbilog
-{
- /** \brief Registeres a backend to the mbi logging mechanism. If a backend is registered here, all mbilog messages
- * are relayed to this backend through the method ProcessMessage. If no backend is registered the default
- * backend is used.
- */
- void MBILOG_EXPORT RegisterBackend(BackendBase *backend);
-
- /** \brief Unregisters a backend.
- */
- void MBILOG_EXPORT UnregisterBackend(BackendBase *backend);
-
- /** \brief Distributes the given message to all registered backends. Should only be called by objects
- * of the class pseudo stream.
- */
- void MBILOG_EXPORT DistributeToBackends(LogMessage &l);
-
- /**
- * Enable the output of a backend.
- **/
- void MBILOG_EXPORT EnableBackends(OutputType type);
- /**
- * Disable the output of a backend.
- **/
- void MBILOG_EXPORT DisableBackends(OutputType type);
- /**
- * Checks wether the output of this backend is enabled.
- **/
- bool MBILOG_EXPORT IsBackendEnabled(OutputType type);
-
- /**
- * \brief An object of this class simulates a std::cout stream. This means messages can be added by
- * using the bit shift operator (<<). Should only be used by the macros defined in the file mbilog.h
- * \ingroup mbilog
- */
- class MBILOG_EXPORT PseudoStream
- {
- protected:
- bool disabled;
- LogMessage msg;
- std::stringstream ss;
-
- public:
- inline PseudoStream(int level, const char *filePath, int lineNumber, const char *functionName)
- : disabled(false), msg(LogMessage(level, filePath, lineNumber, functionName)), ss(std::stringstream::out)
- {
- }
-
- /** \brief The message which is stored in the member ss is written to the backend. */
- inline ~PseudoStream()
- {
- if (!disabled)
- {
- msg.message = ss.str();
- msg.moduleName = MBILOG_MODULENAME;
- DistributeToBackends(msg);
- }
- }
-
- /** \brief Definition of the bit shift operator for this class.*/
- template <class T>
- inline PseudoStream &operator<<(const T &data)
- {
- if (!disabled)
- {
- std::locale C("C");
- std::locale originalLocale = ss.getloc();
- ss.imbue(C);
-
- ss << data;
-
- ss.imbue(originalLocale);
- }
- return *this;
- }
-
- /** \brief Definition of the bit shift operator for this class (for non const data).*/
- template <class T>
- inline PseudoStream &operator<<(T &data)
- {
- if (!disabled)
- {
- std::locale C("C");
- std::locale originalLocale = ss.getloc();
- ss.imbue(C);
-
- ss << data;
-
- ss.imbue(originalLocale);
- }
- return *this;
- }
-
- /** \brief Definition of the bit shift operator for this class (for functions).*/
- inline PseudoStream &operator<<(std::ostream &(*func)(std::ostream &))
- {
- if (!disabled)
- {
- std::locale C("C");
- std::locale originalLocale = ss.getloc();
- ss.imbue(C);
-
- ss << func;
-
- ss.imbue(originalLocale);
- }
- return *this;
- }
-
- /** \brief Sets the category of this PseudoStream object. If there already is a category it is appended, seperated
- * by a dot.*/
- inline PseudoStream &operator()(const char *category)
- {
- if (!disabled)
- {
- if (msg.category.length())
- msg.category += ".";
- msg.category += category;
- }
- return *this;
- }
-
- /** \brief Enables/disables the PseudoStream. If set to false parsing and output is suppressed. */
- inline PseudoStream &operator()(bool enabled)
- {
- disabled |= !enabled;
- return *this;
- }
- };
-
- /**
- * \brief An object of this class simulates a std::cout stream but does nothing. This class is for dummy objects, bit
- * shift
- * operators are availiable but doing nothing. Should only be used by the macros defined in the file mbilog.h
- * \ingroup mbilog
- */
- class MBILOG_EXPORT NullStream
- {
- public:
- template <class T>
- inline NullStream &operator<<(const T & /*data*/)
- {
- return *this;
- }
- template <class T>
- inline NullStream &operator<<(T & /*data*/)
- {
- return *this;
- }
- inline NullStream &operator<<(std::ostream &(*)(std::ostream &)) { return *this; }
- inline NullStream &operator()(const char *) { return *this; }
- inline NullStream &operator()(bool) { return *this; }
- };
-
- // /** \brief templated backend: one can define a class and a method to create a new backend. */
- // template<typename T>
- // struct DelegateBackend : public BackendBase
- // {
- //
- // typedef void(T::*Callback)(const mbilog::LogMessage&);
- //
- // DelegateBackend(T* obj, Callback callback) : m_Obj(obj), m_Callback(callback)
- // {
- // }
- //
- // void ProcessMessage(const mbilog::LogMessage& msg)
- // {
- // m_Obj->*m_Callback(msg);
- // }
- //
- // private:
- //
- // T* m_Obj;
- // Callback m_Callback;
- // };
-}
-
-/** \brief Macros for different message levels. Creates an instance of class PseudoStream with the corresponding message
- * level.
- * Other parameters are the name of the source file, line of the source code and function name which are
- * generated
- * by the compiler.
- */
-#define MBI_INFO mbilog::PseudoStream(mbilog::Info, __FILE__, __LINE__, __FUNCTION__)
-#define MBI_WARN mbilog::PseudoStream(mbilog::Warn, __FILE__, __LINE__, __FUNCTION__)
-#define MBI_ERROR mbilog::PseudoStream(mbilog::Error, __FILE__, __LINE__, __FUNCTION__)
-#define MBI_FATAL mbilog::PseudoStream(mbilog::Fatal, __FILE__, __LINE__, __FUNCTION__)
-
-/** \brief Macro for the debug messages. The messages are disabled if the cmake variable MBILOG_ENABLE_DEBUG is false.
- */
-#ifdef MBILOG_ENABLE_DEBUG
-#define MBI_DEBUG mbilog::PseudoStream(mbilog::Debug, __FILE__, __LINE__, __FUNCTION__)
-#else
-#define MBI_DEBUG true ? mbilog::NullStream() : mbilog::NullStream() // this is magic by markus
-#endif
-
-#endif
diff --git a/Utilities/mbilog/mbilogBackendBase.h b/Utilities/mbilog/mbilogBackendBase.h
deleted file mode 100644
index c82696b5e6..0000000000
--- a/Utilities/mbilog/mbilogBackendBase.h
+++ /dev/null
@@ -1,58 +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.
-
-============================================================================*/
-
-#ifndef _mbilogBackendBase_H
-#define _mbilogBackendBase_H
-
-#include "mbilogExports.h"
-#include "mbilogLogMessage.h"
-
-namespace mbilog
-{
- /** This enum defines the type of the output of a backend.
- * Console: output generated to the console
- * File: output generated to a file
- * Other: all other kinds of output
- */
- enum OutputType
- {
- Console = 0,
- File,
- Other = 100
- };
- /**
- * \brief This class is an interface for logging backends that can be registered in the mbi logging mechanism.
- *
- * \ingroup mbilog
- */
- class MBILOG_EXPORT BackendBase
- {
- public:
- virtual ~BackendBase();
-
- /**
- * \brief This method is called by the mbi logging mechanism if the object is registered in
- * the mbi logging mechanism and a logging message is emitted.
- *
- * \param logMessage Logging message which was emitted.
- *
- */
- virtual void ProcessMessage(const mbilog::LogMessage &logMessage) = 0;
-
- /**
- * @return The type of this backend.
- */
- virtual OutputType GetOutputType() const = 0;
- };
-}
-
-#endif
diff --git a/Utilities/mbilog/mbilogBackendCout.cpp b/Utilities/mbilog/mbilogBackendCout.cpp
deleted file mode 100644
index bd9604f3c1..0000000000
--- a/Utilities/mbilog/mbilogBackendCout.cpp
+++ /dev/null
@@ -1,44 +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 <ctime>
-#include <iomanip>
-#include <list>
-
-#include "mbilogBackendCout.h"
-
-mbilog::BackendCout::BackendCout()
-{
- m_useFullOutput = false;
-}
-
-mbilog::BackendCout::~BackendCout()
-{
-}
-
-void mbilog::BackendCout::SetFull(bool full)
-{
- m_useFullOutput = full;
-}
-
-void mbilog::BackendCout::ProcessMessage(const mbilog::LogMessage &l)
-{
- if (m_useFullOutput)
- FormatFull(l);
- else
- FormatSmart(l);
-}
-
-mbilog::OutputType mbilog::BackendCout::GetOutputType() const
-{
- return mbilog::Console;
-}
diff --git a/Utilities/mbilog/mbilogBackendCout.h b/Utilities/mbilog/mbilogBackendCout.h
deleted file mode 100644
index daba4f6645..0000000000
--- a/Utilities/mbilog/mbilogBackendCout.h
+++ /dev/null
@@ -1,60 +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.
-
-============================================================================*/
-
-#ifndef _mbilogBackendCout_H
-#define _mbilogBackendCout_H
-
-#include <iostream>
-
-#include "mbilogExports.h"
-#include "mbilogLogMessage.h"
-#include "mbilogLoggingTypes.h"
-#include "mbilogTextBackendBase.h"
-
-namespace mbilog
-{
- /**
- * \brief Default backend of the mbi logging mechanism. This backend is used if no other backend is registered.
- * The backend formats the logging messages to a normal string and writes them to std::cout.
- * \ingroup mbilog
- */
- class MBILOG_EXPORT BackendCout : public TextBackendBase
- {
- public:
- BackendCout();
- ~BackendCout() override;
-
- /** \brief This method is called by the mbi logging mechanism if the object is registered in
- * the mbi logging mechanism and a logging message is emitted. The method formats the
- * logging messages to a normal string (depending on formatting mode) and writes it to std::cout.
- *
- * \param l Logging message.
- */
- void ProcessMessage(const mbilog::LogMessage &l) override;
-
- /** \brief Sets the formatting mode. If true long messages will be displayed. Default is false (short/smart
- * messages).
- * Long messages provide all informations and are also capable to be postproccessed (e.g. in a web viewer).
- */
- void SetFull(bool full);
-
- OutputType GetOutputType() const override;
-
- private:
- /** \brief The formatting mode of this backend. True is full/long message formatting mode. False is short/smart
- * message formatting mode
- */
- bool m_useFullOutput;
- };
-}
-
-#endif
diff --git a/Utilities/mbilog/mbilogConfig.cmake.in b/Utilities/mbilog/mbilogConfig.cmake.in
deleted file mode 100644
index 26c061154e..0000000000
--- a/Utilities/mbilog/mbilogConfig.cmake.in
+++ /dev/null
@@ -1,7 +0,0 @@
-
-set(mbilog_IS_ENABLED "1")
-set(mbilog_INCLUDE_DIRS @CMAKE_CURRENT_SOURCE_DIR@ @CMAKE_CURRENT_BINARY_DIR@)
-set(mbilog_TARGET "mbilog")
-set(mbilog_DEPENDS "")
-set(mbilog_PACKAGE_DEPENDS "")
-set(mbilog_LIBRARY_DIRS "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@")
diff --git a/Utilities/mbilog/mbilogConfig.h.in b/Utilities/mbilog/mbilogConfig.h.in
deleted file mode 100644
index ac5ed9321b..0000000000
--- a/Utilities/mbilog/mbilogConfig.h.in
+++ /dev/null
@@ -1,29 +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.
-
-============================================================================*/
-
-#ifndef _MBILOG_CONFIG_H_
-#define _MBILOG_CONFIG_H_
-
-@_define_enable_debug@
-
-#define _MBILOG_STR_(x) #x
-#define _MBILOG_STR(x) _MBILOG_STR_(x)
-
-#ifndef MBILOG_MODULENAME
- #if defined(US_MODULE_NAME)
- #define MBILOG_MODULENAME _MBILOG_STR(US_MODULE_NAME)
- #else
- #define MBILOG_MODULENAME "n/a"
- #endif
-#endif
-
-#endif /* _MBILOG_CONFIG_H_ */
diff --git a/Utilities/mbilog/mbilogLogMessage.h b/Utilities/mbilog/mbilogLogMessage.h
deleted file mode 100644
index 82edb8d750..0000000000
--- a/Utilities/mbilog/mbilogLogMessage.h
+++ /dev/null
@@ -1,71 +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.
-
-============================================================================*/
-
-#ifndef _mbilogLogMessage_H
-#define _mbilogLogMessage_H
-
-#include <string>
-
-#include "mbilogExports.h"
-
-namespace mbilog
-{
- /** Documentation
- * \brief An object of this class represents a single logging message (logging event) of the
- * mbi logging mechanism. Logging message should only be generated by the macros in the class mbilog.h
- *
- * \ingroup mbilog
- */
-
- // todo convert to Struct
- class MBILOG_EXPORT LogMessage
- {
- public:
- // TODO: all member names m_[...]
-
- /** \brief Logging level which is defined in the enum mbilogLoggingTypes.h TODO: convert to enum.*/
- const int level;
-
- // the data of the following section is generated by the c-compiler
-
- /** \brief File name of the source file where the logging message was emitted which is generated by the macros in
- * file mbilog.h*/
- const char *filePath;
- /** \brief Line of the source source file where the logging message was emitted which is generated by the macros in
- * file mbilog.h*/
- const int lineNumber;
- /** \brief Name of the method where the logging message was emitted which is generated by the macros in file
- * mbilog.h*/
- const char *functionName;
-
- // the data of the following section is generated by the mitk module system
-
- /** \brief Name of the module where the logging message was emitted which is generated by the macros in file
- * mbilog.h. Is empty if there module defined.*/
- const char *moduleName;
-
- // user parameters
-
- /** \brief Category of the logging event, which was defined by the user.*/
- std::string category;
-
- /** \brief The actual logging message.*/
- std::string message;
-
- LogMessage(const int _level, const char *_filePath, const int _lineNumber, const char *_functionName)
- : level(_level), filePath(_filePath), lineNumber(_lineNumber), functionName(_functionName)
- {
- }
- };
-}
-
-#endif
diff --git a/Utilities/mbilog/mbilogLoggingTypes.h b/Utilities/mbilog/mbilogLoggingTypes.h
deleted file mode 100644
index d503fd02b8..0000000000
--- a/Utilities/mbilog/mbilogLoggingTypes.h
+++ /dev/null
@@ -1,35 +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.
-
-============================================================================*/
-
-#ifndef _MBILOG_LOGGINGTYPES_H_
-#define _MBILOG_LOGGINGTYPES_H_
-
-namespace mbilog
-{
- /** \brief This enum defines the message/event levels of the mbi logging mechanism.
- * Info: TODO
- * Warn: TODO
- * Error: TODO
- * Fatal: TODO
- * Debug: TODO
- */
- enum
- {
- Info,
- Warn,
- Error,
- Fatal,
- Debug
- };
-}
-
-#endif
diff --git a/Utilities/mbilog/mbilogTextBackendBase.h b/Utilities/mbilog/mbilogTextBackendBase.h
deleted file mode 100644
index 46a4e9bd77..0000000000
--- a/Utilities/mbilog/mbilogTextBackendBase.h
+++ /dev/null
@@ -1,77 +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.
-
-============================================================================*/
-
-#ifndef _mbilogTextBackendBase_H
-#define _mbilogTextBackendBase_H
-
-#include "mbilogBackendBase.h"
-#include "mbilogExports.h"
-
-namespace mbilog
-{
- /** Documentation
- * \brief This class is an abstract superclass for logging text backends. It adds string formatting methods
- * to the backend interface BackendBase. Accordingly backends that inherit from this class can be
- * registered in the mbi logging mechanism.
- *
- * \ingroup mbilog
- */
- class MBILOG_EXPORT TextBackendBase : public BackendBase
- {
- public:
- ~TextBackendBase() override;
-
- /** \brief This method is called by the mbi logging mechanism if the object is registered in
- * the mbi logging mechanism and a logging message is emitted.
- *
- * \param logMessage Logging message which was emitted.
- *
- */
- void ProcessMessage(const mbilog::LogMessage &logMessage) override = 0;
-
- protected:
- /** \brief Method formats the given LogMessage in the smart/short format and writes it to std::cout.
- * \param l
- * \param threadID Can be set to the threadID where the logging message was emitted. Is 0 by default.
- */
- void FormatSmart(const LogMessage &l, int threadID = 0);
-
- /** \brief Method formats the given LogMessage in the full/long format and writes it to std::cout.
- * \param l
- * \param threadID Can be set to the threadID where the logging message was emitted. Is 0 by default.
- */
- void FormatFull(const LogMessage &l, int threadID = 0);
-
- /** \brief Method formats the given LogMessage in the smart/short format and writes it to the given std::ostream.
- * \param out
- * \param l
- * \param threadID Can be set to the threadID where the logging message was emitted. Is 0 by default.
- */
- void FormatSmart(std::ostream &out, const LogMessage &l, int threadID = 0);
-
- /** \brief Method formats the given LogMessage in the full/long format and writes it to the given std::ostream.
- * \param out
- * \param l
- * \param threadID Can be set to the threadID where the logging message was emitted. Is 0 by default.
- */
- void FormatFull(std::ostream &out, const LogMessage &l, int threadID = 0);
-
- /** \brief Writes the system time to the given stream.*/
- void AppendTimeStamp(std::ostream &out);
-
- /** \brief Special variant of method FormatSmart which uses colored messages (only for windows).*/
- // TODO: implement for linux?
- void FormatSmartWindows(const mbilog::LogMessage &l, int /*threadID*/);
- };
-}
-
-#endif

File Metadata

Mime Type
application/octet-stream
Expires
Tue, Oct 1, 1:18 AM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
JboFiPcQ5jWJ
Default Alt Text
(5 MB)

Event Timeline