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 #! _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/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 std::vector 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/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. Debug (MITK_DEBUG): 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. Info (MITK_INFO): 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 Warning (MITK_WARN): 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 Error (MITK_ERROR): 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 Fatal (MITK_FATAL): 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/Starting/SettingUpMITK/BuildInstructions.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox index 65fa8cf44b..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: -# Git (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. -# CMake (version \minimumCMakeVersion or higher) -# Qt \minimumQt5Version if you plan to develop Qt-based applications -# If you are using macOS 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 online installers for all supported platforms. 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 required components: - QtWebEngine - QtScript On Windows, the Qt installer offers a welcome and straight forward way to install OpenSSL. 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 MITK dashboard 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 www.mitk.org. 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 Windows 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: - CMAKE_PREFIX_PATH The path to your Qt installation, e.g., C:/Qt/5.12.9/msvc2017_64 or /home/user/Qt/5.12.9/gcc_64 - MITK_USE_BLUEBERRY Build the BlueBerry application framework - MITK_USE_Boost_LIBRARIES If you need binary Boost libraries, specify them here. - MITK_USE_OpenCV Build MITK code which depends on OpenCV (this will download and build OpenCV 2.4) - MITK_USE_Python3 Enables Python wrapping in MITK. This will also configure ITK, VTK, and OpenCV (if enabled) to build Python wrappers. - MITK_USE_Qt5 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". Linux and macOS users usually just enter "make" (optionally supplying the number threads to be used for a parallel build): \code make -j6 \endcode Windows users using Visual Studio can open the generated MITK-superbuild.sln solution file in the MITK-superbuild directory and start the build by building the BUILD_ALL 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 MITK-superbuild 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 MITK-superbuild/MITK-build/bin On Windows, the PATH 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 MITK-superbuild/MITK-build/bin. \section BuildInstructions_Documentation Documentation If you have the Doxygen 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 MITK_DOXYGEN_OUTPUT_DIR 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 find_package(MITK REQUIRED) to your CMakeLists.txt and make use of the CMake macros mitk_create_module() and mitk_create_executable() 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 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 -#include +#include 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 EXTERNAL_ prefix, for example when providing their values on a command line call to CMake. - EXTERNAL_BOOST_ROOT Set this variable to your custom Boost installation - EXTERNAL_CTK_DIR Set this variable to your CTK binary tree (the directory containing the CTKConfig.cmake file) - EXTERNAL_CableSwig_DIR Set this variable to your CableSwig binary tree for Python wrapping (the directory containing the CableSwigConfig.cmake file) - EXTERNAL_DCMTK_DIR Set this variable to your DCMTK binary tree (the directory containing the DCMTKConfig.cmake file) - EXTERNAL_GDCM_DIR Set this variable to your GDCM binary tree (the directory containing the GDCMConfig.cmake file) - EXTERNAL_ITK_DIR Set this variable to your ITK binary tree (the directory containing the ITKConfig.cmake file) - EXTERNAL_OpenCV_DIR Set this variable to your OpenCV binary tree (the directory containing the OpenCVConfig.cmake file) - EXTERNAL_VTK_DIR 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/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 -#include +#include namespace mitk { std::vector ExampleIOMimeTypes::Get() { std::vector 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 -#include -int main(int /*argc*/, char ** /*argv*/) +#include +#include + +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/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 -#include +#include 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(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 -#include +#include #include template 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 736557984b..68948a6607 100644 --- a/Modules/AppUtil/src/mitkBaseApplication.cpp +++ b/Modules/AppUtil/src/mitkBaseApplication.cpp @@ -1,902 +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 #include #include #include -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 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_) 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(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 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(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(d->m_QApp)->setSafeMode(safeMode) : static_cast(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: * * The executable path is: * * 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 .ini file and parsing any // command line arguments this->loadConfiguration(); // 5. Add configuration data from the command line and the // optional .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(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_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(new QmitkSingleApplication(d->m_Argc, d->m_Argv, this->getSafeMode())) : static_cast(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 &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(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(d, &Impl::handleBooleanOption)); options.addOption(newInstanceOption); Poco::Util::Option cleanOption(ARG_CLEAN.toStdString(), "", "cleans the plugin cache"); cleanOption.callback(Poco::Util::OptionCallback(d, &Impl::handleClean)); options.addOption(cleanOption); Poco::Util::Option productOption(ARG_PRODUCT.toStdString(), "", "the id of the product to be launched"); productOption.argument("").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("").binding(PROP_APPLICATION.toStdString()); options.addOption(appOption); Poco::Util::Option provOption(ARG_PROVISIONING.toStdString(), "", "the location of a provisioning file"); provOption.argument("").binding(ARG_PROVISIONING.toStdString()); options.addOption(provOption); Poco::Util::Option storageDirOption(ARG_STORAGE_DIR.toStdString(), "", "the location for storing persistent application data"); storageDirOption.argument("").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(d, &Impl::handleBooleanOption)); options.addOption(consoleLogOption); Poco::Util::Option debugOption(ARG_DEBUG.toStdString(), "", "enable debug mode"); debugOption.argument("", 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(d, &Impl::handleBooleanOption)); options.addOption(forcePluginOption); Poco::Util::Option preloadLibsOption(ARG_PRELOAD_LIBRARY.toStdString(), "", "preload a library"); preloadLibsOption.argument("") .repeatable(true) .callback(Poco::Util::OptionCallback(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(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(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(d, &Impl::handleBooleanOption)); options.addOption(registryMultiLanguageOption); Poco::Util::Option splashScreenOption(ARG_SPLASH_IMAGE.toStdString(), "", "optional picture to use as a splash screen"); splashScreenOption.argument("").binding(ARG_SPLASH_IMAGE.toStdString()); options.addOption(splashScreenOption); Poco::Util::Option xargsOption(ARG_XARGS.toStdString(), "", "Extended argument list"); xargsOption.argument("").binding(ARG_XARGS.toStdString()); options.addOption(xargsOption); Poco::Util::Option logQtMessagesOption(ARG_LOG_QT_MESSAGES.toStdString(), "", "log Qt messages"); logQtMessagesOption.callback(Poco::Util::OptionCallback(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("").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("").binding(ARG_SEGMENTATION_LABEL_SUGGESTIONS.toStdString()); options.addOption(labelSuggestionsOption); Poco::Util::Application::defineOptions(options); } QSharedPointer 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 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(this->getQApplication()); if (nullptr != app) app->isRunning(); mitkThrow() << "Method not implemented."; } void BaseApplication::sendMessage(const QByteArray msg) { auto app = dynamic_cast(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 +#include #include #include #include #include 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 ProvisioningInfo::getPluginsToInstall() const { return pluginsToInstall; } QList 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/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 #include #include -#include +#include #include #include namespace mitk { std::vector MitkCESTIOMimeTypes::Get() { std::vector 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/Classification/CLImportanceWeighting/src/mitkGeneralizedLinearModel.cpp b/Modules/Classification/CLImportanceWeighting/src/mitkGeneralizedLinearModel.cpp index f97cd28264..842bc5ce97 100644 --- a/Modules/Classification/CLImportanceWeighting/src/mitkGeneralizedLinearModel.cpp +++ b/Modules/Classification/CLImportanceWeighting/src/mitkGeneralizedLinearModel.cpp @@ -1,279 +1,279 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include #include #include #include -#include +#include #include #include static void _UpdateXMatrix(const vnl_matrix &xData, bool addConstant, v3p_netlib_doublereal *x); static void _UpdatePermXMatrix(const vnl_matrix &xData, bool addConstant, const vnl_vector &permutation, vnl_matrix &x); static void _InitMuEta(mitk::DistSimpleBinominal *dist, mitk::LogItLinking *link, const vnl_vector &yData, vnl_vector &mu, vnl_vector &eta); static void _FinalizeBVector(vnl_vector &b, vnl_vector &perm, int cols); double mitk::GeneralizedLinearModel::Predict( const vnl_vector &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 mitk::GeneralizedLinearModel::Predict(const vnl_matrix &x) { LogItLinking link; vnl_vector 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 mitk::GeneralizedLinearModel::B() { return m_B; } vnl_vector mitk::GeneralizedLinearModel::ExpMu(const vnl_matrix &x) { LogItLinking link; vnl_vector 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 &xData, const vnl_vector &yData, bool addConstantColumn) : m_AddConstantColumn(addConstantColumn) { EstimatePermutation(xData); DistSimpleBinominal dist; LogItLinking link; vnl_matrix x; int rows = xData.rows(); int cols = m_Permutation.size(); vnl_vector mu(rows); vnl_vector eta(rows); vnl_vector weightedY(rows); vnl_matrix weightedX(rows, cols); vnl_vector 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::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 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 &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::epsilon(); // Calculate the rank of the matrix int m_Rank = 0; for (int i = 0; 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 &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 &xData, bool addConstant, const vnl_vector &permutation, vnl_matrix &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 &yData, vnl_vector &mu, vnl_vector &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 &b, vnl_vector &perm, int cols) { vnl_vector 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/CLMiniApps/CLWeighting.cpp b/Modules/Classification/CLMiniApps/CLWeighting.cpp index c55b10a061..549d70b033 100644 --- a/Modules/Classification/CLMiniApps/CLWeighting.cpp +++ b/Modules/Classification/CLMiniApps/CLWeighting.cpp @@ -1,213 +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 mitkForest_cpp #define mitkForest_cpp #include "time.h" #include #include #include "mitkCommandLineParser.h" #include #include -#include - //#include #include struct TrainingSet { vnl_matrix feature; vnl_vector label; double ratio; }; const vnl_matrix ReadMatrix(std::string path) { std::fstream file(path); std::vector > 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 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 > listOfRows; std::vector 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 resultMatrix(listOfRows.size(), listOfRows[0].size()); vnl_vector 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 parsedArgs = parser.parseArguments(argc, argv); std::string trainingPath = us::any_cast(parsedArgs["training"]); std::string predictionPath = us::any_cast(parsedArgs["prediction"]); std::string outputPath = us::any_cast(parsedArgs["output"]); //std::string algorithm = us::any_cast(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(argv[2]); //col->AddData(sur.GetPointer(),"sur"); //MITK_INFO << "Arg 3 " << argv[3]; //mitk::Image::Pointer mask=mitk::IOUtil::Load(argv[3]); //col->AddData(mask.GetPointer(),"mask"); //std::vector 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(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/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 +#include namespace itk { namespace Statistics { template EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter() : m_NumberOfBinsPerAxis( itkGetStaticConstMacro( DefaultBinsPerAxis ) ), m_Min( NumericTraits::NonpositiveMin() ), m_Max( NumericTraits::max() ), m_MinDistance( NumericTraits::ZeroValue() ), m_MaxDistance( NumericTraits::max() ), m_InsidePixelValue( NumericTraits::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( 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 void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::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 void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::AddOffsets( const std::vector _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 void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::SetInput( const ImageType *image ) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput( 0, const_cast( image ) ); } template void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::SetMaskImage( const ImageType *image ) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput( 1, const_cast( image ) ); } template const TImageType * EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::GetInput() const { if( this->GetNumberOfInputs() < 1 ) { return ITK_NULLPTR; } return static_cast( this->ProcessObject::GetInput( 0 ) ); } template const TImageType * EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::GetMaskImage() const { if( this->GetNumberOfInputs() < 2 ) { return ITK_NULLPTR; } return static_cast( this->ProcessObject::GetInput( 1 ) ); } template const typename EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter::HistogramType * EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::GetOutput() const { const HistogramType *output = static_cast( this->ProcessObject::GetOutput( 0 ) ); return output; } template double* EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::GetSiMatrix() const { return m_siMatrix; } template typename EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter::DataObjectPointer EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::MakeOutput( DataObjectPointerArraySizeType itkNotUsed( idx ) ) { return HistogramType::New().GetPointer(); } template void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::GenerateData() { HistogramType *output = static_cast( 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 FloatImageType; typedef itk::CastImageFilter 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 LabelImageType; typedef itk::CastImageFilter 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::quiet_NaN()); maskFilter->Update(); FloatImageType::Pointer floatImageMasked = maskFilter->GetOutput(); typedef ConstNeighborhoodIterator 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(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["< Values are now niMatrix: " << output->GetFrequency(hIndex) << "/" << run; } } template void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::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 void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::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 void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::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 void EnhancedScalarImageToNeighbourhoodGreyLevelDifferenceMatrixFilter ::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 +#include namespace itk { namespace Statistics { template EnhancedScalarImageToSizeZoneMatrixFilter ::EnhancedScalarImageToSizeZoneMatrixFilter() : m_NumberOfBinsPerAxis( itkGetStaticConstMacro( DefaultBinsPerAxis ) ), m_Min( NumericTraits::NonpositiveMin() ), m_Max( NumericTraits::max() ), m_MinDistance( NumericTraits::ZeroValue() ), m_MaxDistance( NumericTraits::max() ), m_InsidePixelValue( NumericTraits::OneValue() ) { this->SetNumberOfRequiredInputs( 1 ); this->SetNumberOfRequiredOutputs( 1 ); const unsigned int measurementVectorSize = 2; this->ProcessObject::SetNthOutput( 0, this->MakeOutput( 0 ) ); HistogramType *output = const_cast( 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 void EnhancedScalarImageToSizeZoneMatrixFilter ::SetOffset( const OffsetType offset ) { OffsetVectorPointer offsetVector = OffsetVector::New(); offsetVector->push_back( offset ); this->SetOffsets( offsetVector ); } template void EnhancedScalarImageToSizeZoneMatrixFilter ::SetInput( const ImageType *image ) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput( 0, const_cast( image ) ); } template void EnhancedScalarImageToSizeZoneMatrixFilter ::SetMaskImage( const ImageType *image ) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput( 1, const_cast( image ) ); } template const TImageType * EnhancedScalarImageToSizeZoneMatrixFilter ::GetInput() const { if( this->GetNumberOfInputs() < 1 ) { return ITK_NULLPTR; } return static_cast( this->ProcessObject::GetInput( 0 ) ); } template const TImageType * EnhancedScalarImageToSizeZoneMatrixFilter ::GetMaskImage() const { if( this->GetNumberOfInputs() < 2 ) { return ITK_NULLPTR; } return static_cast( this->ProcessObject::GetInput( 1 ) ); } template const typename EnhancedScalarImageToSizeZoneMatrixFilter::HistogramType * EnhancedScalarImageToSizeZoneMatrixFilter ::GetOutput() const { const HistogramType *output = static_cast( this->ProcessObject::GetOutput( 0 ) ); return output; } template typename EnhancedScalarImageToSizeZoneMatrixFilter::DataObjectPointer EnhancedScalarImageToSizeZoneMatrixFilter ::MakeOutput( DataObjectPointerArraySizeType itkNotUsed( idx ) ) { return HistogramType::New().GetPointer(); } template void EnhancedScalarImageToSizeZoneMatrixFilter ::GenerateData() { HistogramType *output = static_cast( 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 FloatImageType; typedef itk::CastImageFilter 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 LabelImageType; typedef itk::CastImageFilter 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 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 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 void EnhancedScalarImageToSizeZoneMatrixFilter ::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 void EnhancedScalarImageToSizeZoneMatrixFilter ::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 void EnhancedScalarImageToSizeZoneMatrixFilter ::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/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/files.cmake b/Modules/Core/files.cmake index cff9510c3c..7a28848686 100644 --- a/Modules/Core/files.cmake +++ b/Modules/Core/files.cmake @@ -1,328 +1,328 @@ 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/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/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 Pointer; \ typedef itk::SmartPointer ConstPointer; \ static const char *GetStaticNameOfClass() { return #className; } \ virtual std::vector GetClassHierarchy() const override { return mitk::GetClassHierarchy(); } \ itkTypeMacro(className, SuperClassName); #define mitkClassMacroItkParent(className, SuperClassName) \ typedef className Self; \ typedef SuperClassName Superclass; \ typedef itk::SmartPointer Pointer; \ typedef itk::SmartPointer ConstPointer; \ static const char *GetStaticNameOfClass() { return #className; } \ virtual std::vector GetClassHierarchy() const { return mitk::GetClassHierarchy(); } \ 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 Pointer; \ typedef itk::SmartPointer ConstPointer; \ static const char *GetStaticNameOfClass() { return #className; } \ virtual std::vector GetClassHierarchy() const { return mitk::GetClassHierarchy(); } \ 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 #include "mitkFileWriterWithInformation.h" #include "mitkMapper.h" #include #include #include 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 FileWriterList; typedef std::multimap 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 -#include +#include #include #include #include #include #include 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 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 static bool Unget(S *service, us::ModuleContext *context = us::GetModuleContext()) { return Unget(context, us_service_interface_iid(), 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 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 #include -#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 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 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/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 -#include +#include #include /** 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 \ 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 \ 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/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 -#include - -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 " 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 +#include + +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: + *
    + *
  • 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 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 " 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 - -#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 #endif 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 +#include 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/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 +#include #include 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/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 #include 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 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(rankProp); } auto id = us::any_cast(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 FileReaderWriterBase::RegisterMimeType(us::ModuleContext *context) { if (context == nullptr) throw std::invalid_argument("The context argument must not be nullptr."); CoreServicePointer mimeTypeProvider(CoreServices::GetMimeTypeProvider(context)); const std::vector 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(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 #include "itkGDCMImageIO.h" #include "itkMetaDataObject.h" #include #include 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 files; for (unsigned long idx = 0; idxMatchesExtension(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(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 IOMimeTypes::Get() { std::vector mimeTypes; // order matters here (descending rank for mime types) mimeTypes.push_back(NRRD_MIMETYPE().Clone()); mimeTypes.push_back(NIFTI_MIMETYPE().Clone()); mimeTypes.push_back(VTK_IMAGE_MIMETYPE().Clone()); mimeTypes.push_back(VTK_PARALLEL_IMAGE_MIMETYPE().Clone()); mimeTypes.push_back(VTK_IMAGE_LEGACY_MIMETYPE().Clone()); mimeTypes.push_back(DICOM_MIMETYPE().Clone()); mimeTypes.push_back(VTK_POLYDATA_MIMETYPE().Clone()); mimeTypes.push_back(VTK_PARALLEL_POLYDATA_MIMETYPE().Clone()); mimeTypes.push_back(VTK_POLYDATA_LEGACY_MIMETYPE().Clone()); mimeTypes.push_back(STEREOLITHOGRAPHY_MIMETYPE().Clone()); mimeTypes.push_back(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 #include 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 -#include -#include +#include #include #include #include #include #include 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 #include #include #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(us::GetModuleContext(), this); } m_Tracker->Open(); } void MimeTypeProvider::Stop() { m_Tracker->Close(); } std::vector MimeTypeProvider::GetMimeTypes() const { std::vector result; for (const auto &elem : m_NameToMimeType) { result.push_back(elem.second); } return result; } std::vector MimeTypeProvider::GetMimeTypesForFile(const std::string &filePath) const { std::vector 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 MimeTypeProvider::GetMimeTypesForCategory(const std::string &category) const { std::vector 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 MimeTypeProvider::GetCategories() const { std::vector 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 &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(rankProp); } auto id = us::any_cast(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 +#include 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(numOfComponents); break; case VTK_UNSIGNED_CHAR: return mitk::MakePixelType(numOfComponents); break; case VTK_SHORT: return mitk::MakePixelType(numOfComponents); break; case VTK_UNSIGNED_SHORT: return mitk::MakePixelType(numOfComponents); break; case VTK_INT: return mitk::MakePixelType(numOfComponents); break; case VTK_UNSIGNED_INT: return mitk::MakePixelType(numOfComponents); break; case VTK_LONG: return mitk::MakePixelType(numOfComponents); break; case VTK_UNSIGNED_LONG: return mitk::MakePixelType(numOfComponents); break; case VTK_FLOAT: return mitk::MakePixelType(numOfComponents); break; case VTK_DOUBLE: return mitk::MakePixelType(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/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 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 +#include #include 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::Properties(), "", nullptr, this); } mitk::XMLPreferencesStorage::~XMLPreferencesStorage() { } void mitk::XMLPreferencesStorage::Flush() { tinyxml2::XMLDocument xmlDocument; xmlDocument.InsertEndChild(xmlDocument.NewDeclaration()); Serialize(static_cast(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/Rendering/mitkVideoRecorder.cpp b/Modules/Core/src/Rendering/mitkVideoRecorder.cpp index 064c0efd5a..1de3fcfb9a 100644 --- a/Modules/Core/src/Rendering/mitkVideoRecorder.cpp +++ b/Modules/Core/src/Rendering/mitkVideoRecorder.cpp @@ -1,409 +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 #include #include #include #include #include #include -#include +#include #include #include #include #include #include #include #include #include #include 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 m_WindowToImageFilter; vtkNew m_ImageResize; vtkNew 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(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(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() << ' ' << "-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); 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() << 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 m_FFmpegPath; std::filesystem::path m_OutputPath; std::optional m_OutputFormat; std::string m_RenderWindowName; unsigned int m_FrameRate; std::unique_ptr m_RecordingSession; }; } mitk::VideoRecorder::VideoRecorder() : m_Impl(std::make_unique()) { } 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 +#include #include #include #include #include #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(clientData); vtkRenderWindowInteractor *rwi = static_cast(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 #include #include #include #include #include #include #include // used for acos etc. #include // used for PI #include -#include +#include 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 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 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 void vtkApplyLookupTableOnRGBA(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], double *clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkLookupTable *lookupTable; const int maxC = inData->GetNumberOfScalarComponents(); double tableRange[2]; lookupTable = dynamic_cast(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(*inputSI); inputSI++; rgb[1] = static_cast(*inputSI); inputSI++; rgb[2] = static_cast(*inputSI); inputSI++; RGBtoHSI(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(hsi, rgb); *outputSI = static_cast(rgb[0]); outputSI++; *outputSI = static_cast(rgb[1]); outputSI++; *outputSI = static_cast(rgb[2]); outputSI++; unsigned char finalAlpha = 255; // RGBA case if (maxC >= 4) { // level/window mechanism for opacity alpha = static_cast(*inputSI); inputSI++; alpha = alpha * scaleOpac - biasOpac; if (alpha > 255.0) { alpha = 255.0; } else if (alpha < 0.0) { alpha = 0.0; } finalAlpha = static_cast(alpha); for (int c = 4; c < maxC; c++) inputSI++; } *outputSI = static_cast(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 void vtkApplyLookupTableOnScalarsFast( vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); double tableRange[2]; // access vtkLookupTable auto *lookupTable = dynamic_cast(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(std::max(0, static_cast(*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 void vtkApplyLookupTableOnScalars(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], double *clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator 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(*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(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 void vtkApplyLookupTableOnScalarsCTF(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], double *clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); auto *lookupTable = dynamic_cast(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(*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(255.0 * rgba[i] + 0.5); } } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI += 4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(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(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(this->GetLookupTable()); auto *ctf = dynamic_cast(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(nullptr))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else if (useFast) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalarsFast(this, inData, outData, extent, static_cast(nullptr))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { switch (inData->GetScalarType()) { vtkTemplateMacro(vtkApplyLookupTableOnScalars( this, inData, outData, extent, m_ClippingBounds, static_cast(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/mitkExtractSliceFilterTest.cpp b/Modules/Core/test/mitkExtractSliceFilterTest.cpp index 96916a6240..3c726ccdd9 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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 static void TestSphereRadiusByItk(itk::Image *inputImage) { typedef itk::Image 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 indicesX; std::vector 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 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 static void TestSphereAreaByItk(itk::Image *inputImage) { typedef itk::Image InputImageType; typedef itk::ImageRegionConstIterator 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 ImageType; typedef itk::ImageRegionConstIterator 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->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 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 VolumeReadAccessorType; typedef mitk::ImagePixelReadAccessor 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 imageInVtk = imageInMitk->GetVtkImageData(); vtkSmartPointer 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 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 Image2DType; Image2DType::Pointer img = Image2DType::New(); CastToItkImage(slice, img); typedef itk::ImageRegionConstIterator 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(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 TestVolumeType; typedef itk::ImageRegionConstIterator 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->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 static void CalcTestFailureDeviation(itk::Image *inputImage) { typedef itk::Image InputImageType; typedef itk::ImageRegionConstIterator 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(filename); vtkSmartPointer slicer = vtkSmartPointer::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 vtkPlane = vtkSmartPointer::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 imageMapper = vtkSmartPointer::New(); imageMapper->SetInputConnection(vtkPlane->GetOutputPort()); vtkSmartPointer lookupTable = vtkSmartPointer::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 texture = vtkSmartPointer::New(); texture->SetInput(slicer->GetOutput()); texture->SetLookupTable(lookupTable); texture->SetMapColorScalarsThroughLookupTable(true); vtkSmartPointer imageActor = vtkSmartPointer::New(); imageActor->SetMapper(imageMapper); imageActor->SetTexture(texture); // Setup renderers vtkSmartPointer renderer = vtkSmartPointer::New(); renderer->AddActor(imageActor); // Setup render window vtkSmartPointer renderWindow = vtkSmartPointer::New(); renderWindow->AddRenderer(renderer); // Setup render window interactor vtkSmartPointer renderWindowInteractor = vtkSmartPointer::New(); vtkSmartPointer style = vtkSmartPointer::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/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 #include +#include +#include #include #include #include #include /** 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(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 threadIDs; std::vector 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 // MITK includes #include "mitkPixelType.h" -#include +#include // ITK includes #include "itkImage.h" #include // VTK includes #include 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, 3> ItkImageType; typedef itk::Image MyObscureImageType; typedef itk::VectorImage VectorImageType; typedef itk::Image> FixedVectorImageType; public: void setUp() override { } void tearDown() override { } void GetComponentType_Success() { mitk::PixelType ptype = mitk::MakePixelType(); MITK_INFO << "m_Ptype = mitk::MakePixelType();"; MITK_INFO << "m_ItkPtype = mitk::MakePixelType();\n with itk::Image, 3> ItkImageType"; CPPUNIT_ASSERT_MESSAGE("GetComponentType()", ptype.GetComponentType() == itk::IOComponentEnum::INT); } void GetPixelTypeAsString_Success() { mitk::PixelType ptype = mitk::MakePixelType(); MITK_INFO << ptype.GetPixelTypeAsString(); MITK_INFO << typeid(ItkImageType).name(); } void GetBpePtype_Success() { mitk::PixelType ptype = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("[m_Ptype] GetBpe()", ptype.GetBpe() == 8 * sizeof(int) * 5); } void GetNumberOfComponentsPtype_Success() { mitk::PixelType ptype = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("[ptype]GetNumberOfComponents()", ptype.GetNumberOfComponents() == 5); } void GetBitsPerComponentPtype_Success() { mitk::PixelType ptype = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("[ptype]GetBitsPerComponent()", ptype.GetBitsPerComponent() == 8 * sizeof(int)); } void GetBpeItkPtype_Success() { mitk::PixelType itkPtype = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("[itkPType] GetBpe()", itkPtype.GetBpe() == 8 * sizeof(int) * 5); } void GetNumberOfComponentsItkPtype_Success() { mitk::PixelType itkPtype = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("[itkPType] GetNumberOfComponents()", itkPtype.GetNumberOfComponents() == 5); } void GetBitsPerComponentItkPtype_Success() { mitk::PixelType itkPtype = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("[itkPType] GetBitsPerComponent()", itkPtype.GetBitsPerComponent() == 8 * sizeof(int)); } void ConstructorWithBrackets_Success() { mitk::PixelType ptype = mitk::MakePixelType(); 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(); 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(); mitk::PixelType ptype2 = ptype; CPPUNIT_ASSERT_MESSAGE("operator ==", ptype == ptype2); } void NotEqualityOperator_Success() { mitk::PixelType ptype = mitk::MakePixelType(); mitk::PixelType ptype3 = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("operator !=", ptype != ptype3); } void GetPixelTypeUnknown_Success() { // test instantiation mitk::PixelType obscurePixelType = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("PixelTypeId is 'UNKNOWN' ", obscurePixelType.GetPixelType() == itk::IOPixelEnum::UNKNOWNPIXELTYPE); } void SetLengthCorrectly_Success() { mitk::PixelType obscurePixelType = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("Length was set correctly", obscurePixelType.GetNumberOfComponents() == MyObscurePixelType::Length); } void ValueTypeCorresponds_Success() { mitk::PixelType obscurePixelType = mitk::MakePixelType(); CPPUNIT_ASSERT_MESSAGE("ValueType corresponds.", obscurePixelType.GetComponentType() == mitk::MapPixelComponentType::value); } void ImageTypeTraitInt3D_Success() { // test ImageTypeTrait traits class CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid int 3D equals ITK typeid", typeid(mitk::ImageTypeTrait::ImageType) == typeid(itk::Image)); CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image", (mitk::ImageTypeTrait::IsVectorImage == false)); } void ImageTypeTraitShort2D_Success() { CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid short 2D equals ITK typeid", typeid(mitk::ImageTypeTrait, 3>::ImageType) == typeid(itk::Image, 3>)); CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image", (mitk::ImageTypeTrait, 3>::IsVectorImage == false)); } void ImageTypeTraitVectorShort3D_Success() { CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid short 3D equals ITK typeid", typeid(mitk::ImageTypeTrait, 3>::ImageType) == typeid(itk::VectorImage)); CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is a vector image", (mitk::ImageTypeTrait, 3>::IsVectorImage == true)); } void ImageTypeTraitItkInt3D_Success() { CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid ITK int 3D equals ITK typeid", typeid(mitk::ImageTypeTrait>::ImageType) == typeid(itk::Image)); CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image", (mitk::ImageTypeTrait>::IsVectorImage == false)); } void ImageTypeTraitItkShort2D_Success() { CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid ITK short 2D equals ITK typeid", typeid(mitk::ImageTypeTrait, 3>>::ImageType) == typeid(itk::Image, 3>)); CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is no vector image", (mitk::ImageTypeTrait, 3>>::IsVectorImage == false)); } void ImageTypeTraitItkVectorShort3D_Success() { CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait typeid ITK short 3D equals ITK typeid", typeid(mitk::ImageTypeTrait>::ImageType) == typeid(itk::VectorImage)); CPPUNIT_ASSERT_MESSAGE("ImageTypeTrait is a vector image", (mitk::ImageTypeTrait>::IsVectorImage == true)); } }; MITK_TEST_SUITE_REGISTRATION(mitkPixelType) 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 // MITK includes #include #include #include #include #include #include #include #include #include #include #include -#include +#include // ITK includes #include // VTK includes #include struct PropertyModifiedListener { typedef itk::SimpleMemberCommand 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 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 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 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 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 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(false, true, "0", "1"); } void TestIntProperty_Success() { TestProperty(3, 5, "3", "5"); } void TestFloatProperty_Success() { TestProperty(0.3f, -23.5f, "0.3", "-23.5"); } void TestDoubleProperty_Success() { TestProperty(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(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(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(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(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(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(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(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(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(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(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(sp1, sp2, spp1->GetReferenceUIDFor(sp1), spp2->GetReferenceUIDFor(sp2)); } void TestStringProperty_Success() { TestProperty("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(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(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(lut1, lut2, strLUT1, strLUT2); } }; MITK_TEST_SUITE_REGISTRATION(mitkProperty) 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 // MITK includes #include "mitkUIDGenerator.h" -#include +#include #include #include 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/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 #include #include -#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 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 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 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(m_NumberOfSlicesApart) * static_cast(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(m_NumberOfSlicesApart); } double mitk::GantryTiltInformation::GetRealZSpacing() const { return m_ShiftNormal / static_cast(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 +#include #include #include #include #include namespace mitk { std::vector MitkDICOMPMIOMimeTypes::Get() { std::vector 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 +#include // CTK #include #include // Qt #include #include #include 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 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 // Qt #include #include #include #include #include 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 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/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 #include #include 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(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(nd)); this->CreateOutputsForAllInputs(); } const mitk::NavigationData* mitk::NavigationDataToPointSetFilter::GetInput( void ) { if (this->GetNumberOfInputs() < 1) return nullptr; return static_cast(this->ProcessObject::GetInput(0)); } const mitk::NavigationData* mitk::NavigationDataToPointSetFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) return nullptr; return static_cast(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 counterVec(this->GetNumberOfIndexedOutputs(),0); //vector of old timesteps for each output std::vector 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]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]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/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 #include #include #include #include #include #include #include #include #include #include #include "QmitkCustomVariants.h" //#include #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(""), m_RepresentatonCellDefaultText("") { 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(t)->GetSROMDataLength() > 0) m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem("SROM file loaded")); // SROM file else m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem(m_SROMCellDefaultText)); // SROM file m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::TypeCol, new QTableWidgetItem("")); // Type if (t->IsEnabled()) m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Enabled")); // Status else m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Disabled")); // Status m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::NodeCol, new QTableWidgetItem("")); // Node m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(m_RepresentatonCellDefaultText)); // Representation /* set read-only/editable flags */ m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::IndexCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Index m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Name m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::SROMCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // SROM file m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::TypeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Type m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::StatusCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Status m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Node m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags); // Representation surface file } m_Controls->m_ToolTable->resizeColumnsToContents(); //connect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // listen to table changes again connect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &))); connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & ))); } void QmitkNDIConfigurationWidget::OnDiscoverDevices() { PortDeviceMap portsAndDevices; QString status = "Scanning "; #ifdef WIN32 QString devName; for (unsigned int i = 1; i < 40; ++i) { if (i<10) devName = QString("COM%1").arg(i); else devName = QString("\\\\.\\COM%1").arg(i); // prepend "\\.\ to COM ports >9, to be able to allow connection" portsAndDevices[devName]; status += QString("COM%1").arg(i) + ", "; } #else //linux/posix systems for(unsigned int i = 1; i < 6; ++i) { QString devName = QString("/dev/ttyS%1").arg(i); portsAndDevices[devName]; status += devName + ", "; } for(unsigned int i = 0; i <7; ++i) { QString devName = QString("/dev/ttyUSB%1").arg(i); portsAndDevices[devName]; status += devName + ", "; } #endif status.chop(2); // remove last ", " status += " for NDI tracking devices..."; m_Controls->m_DeviceStatus->setText(status); ScanPortsForNDITrackingDevices(portsAndDevices); m_Controls->m_ComPortSelector->clear(); QString result = "The following tracking devices were found:
\n"; for (PortDeviceMap::const_iterator it = portsAndDevices.begin(); it != portsAndDevices.end(); ++it) { QString tmpComPort = it.key(); if (tmpComPort.startsWith("\\")) { tmpComPort.remove(0,4); // remove "\\.\" for nice ui visualisation } result += tmpComPort + ": "; if (mitk::NDIPolarisTypeInformation::GetTrackingDeviceName() == it.value() || mitk::NDIAuroraTypeInformation::GetTrackingDeviceName() == it.value()) { result += QString::fromStdString(it.value()); result += "
\n"; m_Controls->m_ComPortSelector->addItem(tmpComPort); } else { result += "No NDI tracking device found
\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 (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 QmitkNDIConfigurationWidget::GetToolAndTypes() const { QMap 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 QmitkNDIConfigurationWidget::GetToolsByToolType( QString toolType ) const { QList 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(); } void QmitkNDIConfigurationWidget::HidePolarisOptionsGroupbox( bool on ) { m_Controls->m_gbPolarisOptions->setHidden(on); } void QmitkNDIConfigurationWidget::HideAuroraOptionsGroupbox( bool on ) { m_Controls->m_gbAuroraOptions->setHidden(on); } void QmitkNDIConfigurationWidget::ShowToolRepresentationColumn() { int cols = m_Controls->m_ToolTable->columnCount(); //checking if representation column is inserted at right index if(cols != QmitkNDIToolDelegate::RepCol) { //throw std::exception("Representation Column is not inserted at it's designated index!"); return; } m_Controls->m_ToolTable->insertColumn(cols); // insert new column at end of table m_Controls->m_ToolTable->setHorizontalHeaderItem(QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(QString("Representation"))); // inser column header for new colum //m_Controls->m_ToolTable->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers); int rows = m_Controls->m_ToolTable->rowCount(); // make all representation colum items not editable for(int i=0; i < rows; ++i) { m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem("")); // Representation m_Controls->m_ToolTable->item(i,QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags); } //connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & ))); } void QmitkNDIConfigurationWidget::OnDisoverDevicesBtnInfo() { QMessageBox *infoBox = new QMessageBox(this); infoBox->setText("Click \"Scan Ports\" to get a list of all connected NDI tracking devices. This will clear the selection menu below and add the ports for discovered NDI tracking devices. Use this function, if a port is not listed."); infoBox->exec(); delete infoBox; } void QmitkNDIConfigurationWidget::OnTableCellChanged(int row, int column) { if(m_Tracker.IsNull()) return; QString toolName; switch (column) { case QmitkNDIToolDelegate::NameCol: toolName = m_Controls->m_ToolTable->item(row,column)->text(); m_Controls->m_ToolSelectionComboBox->setItemText(row, toolName); emit SignalToolNameChanged(row, toolName); break; default: break; } } void QmitkNDIConfigurationWidget::OnSaveTool() { if(m_Tracker.IsNull() || m_Tracker->GetToolCount() <= 0) return; int currId = m_Controls->m_ToolSelectionComboBox->currentIndex(); QString filename = QFileDialog::getSaveFileName(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(m_Tracker->GetTool(currSelectedToolID))->SetToolName(navTool->GetToolName().c_str()); // also setting name to tool directly //calibration file (.srom) filename m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(navTool->GetCalibrationFile().c_str()); //type if(navTool->GetType() == mitk::NavigationTool::Instrument) m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Instrument"); else if(navTool->GetType() == mitk::NavigationTool::Fiducial) m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Fiducial"); else if(navTool->GetType() == mitk::NavigationTool::Skinmarker) m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Skinmarker"); else m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Unknown"); //representation m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(m_RepresentatonCellDefaultText); emit SignalLoadTool(currId, navTool->GetDataNode()); } mitk::NavigationTool::Pointer QmitkNDIConfigurationWidget::GenerateNavigationTool(mitk::TrackingTool* tool) { mitk::NavigationTool::Pointer navTool = mitk::NavigationTool::New(); mitk::NDIPassiveTool::Pointer passiveTool = dynamic_cast(tool); if(passiveTool.IsNull()) throw std::runtime_error("Could not cast TrackingTool to PassiveTool"); int currSelectedToolID = m_Controls->m_ToolSelectionComboBox->currentIndex(); QString sromFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::SROMCol)->text(); QString surfaceFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::RepCol)->text(); //calibration file (.srom) filename QFile sromFile(sromFileName); if(sromFile.exists()) navTool->SetCalibrationFile(sromFileName.toStdString()); //serial number navTool->SetSerialNumber(passiveTool->GetSerialNumber()); // name and surface as dataNode mitk::DataNode::Pointer node = mitk::DataNode::New(); mitk::Surface::Pointer toolSurface; try{ toolSurface = this->LoadSurfaceFromSTLFile(surfaceFileName); } catch( ... ) { QMessageBox::warning(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(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/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 + +#include + +#include + +#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 + 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 + 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 + NullLogStream& operator<<(const T&) + { + return *this; + } + + template + 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 +#include + +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 + +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 + +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/Core/include/mitkLogMacros.h b/Modules/Log/include/mitkLogLevel.h similarity index 64% copy from Modules/Core/include/mitkLogMacros.h copy to Modules/Log/include/mitkLogLevel.h index 8ed99172df..ae96189eff 100644 --- a/Modules/Core/include/mitkLogMacros.h +++ b/Modules/Log/include/mitkLogLevel.h @@ -1,24 +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 mitkLogMacros_h -#define mitkLogMacros_h - -#include - -#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 +#ifndef mitkLogLevel_h +#define mitkLogLevel_h + +namespace mitk +{ + /** \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 + +#include + +#include + +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 +#include + #include #include -#include "mbilog.h" - -static std::list backends; -static std::set disabledBackendTypes; - -namespace mbilog -{ - static const std::string NA_STRING = "n/a"; -} +static std::list backends; +static std::set 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::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% copy from Utilities/mbilog/mbilogBackendBase.cpp copy 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 -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 + +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 +#include + #include #include #include #include #ifdef _WIN32 -#define USE_WIN32COLOREDCONSOLE -#include -#include "mbilogTextDictionary.h" +#define MITK_WIN32_CONSOLE_COLOR +#include +#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 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(strlen(mbilog::replace[r])); + int s = static_cast(strlen(mitk::replace[r])); int xs = static_cast(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(a.size()); int bs = static_cast(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(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(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(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(strlen(l.filePath)); + int size = static_cast(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/Utilities/mbilog/mbilogBackendBase.cpp b/Modules/Log/src/mitkLogMessage.cpp similarity index 56% rename from Utilities/mbilog/mbilogBackendBase.cpp rename to Modules/Log/src/mitkLogMessage.cpp index 3ac534e66a..51b067be7c 100644 --- a/Utilities/mbilog/mbilogBackendBase.cpp +++ b/Modules/Log/src/mitkLogMessage.cpp @@ -1,17 +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 "mbilogBackendBase.h" +#include -mbilog::BackendBase::~BackendBase() +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) { } 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 -#include +#include #include #include #include #include namespace mitk { std::vector MitkDICOMSEGIOMimeTypes::Get() { std::vector 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(myfile.tellg()); if (fileSize < offset + bufferSize) return false; myfile.seekg(offset); std::array 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/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 -#include +#include #include #include #include #include #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("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(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::MitkMultilabelIOMimeTypes::Get() { std::vector mimeTypes; mimeTypes.push_back(SEGMENTATIONTASKLIST_MIMETYPE().Clone()); mimeTypes.push_back(LEGACYLABELSET_MIMETYPE().Clone()); return mimeTypes; } 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 //#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 ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(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 +#include #include //usService #include "usServiceReference.h" #include #include #include #include #include #include //standard library #include 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 ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(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 ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(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 eos; std::string source(std::istreambuf_iterator(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 ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(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(GetModuleContext()->GetServiceReference()); 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 #include 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 ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(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; im_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 ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(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 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 -#include +#include //itk #include #include //ocl #include "mitkOclUtils.h" #include #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 #include 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 +#include #include #include #include // qt #include #include 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(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 splitterSizeRow; for (int row = 0; row < m_MultiWidget->GetRowCount(); ++row) { splitterSizeRow.push_back(1000); QList 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 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 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 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 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 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 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 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 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/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 -#include +#include #include #include #include #include #include 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 > providerRegisters = us::GetModuleContext()->GetServiceReferences(filter); if (!providerRegisters.empty()) { if (providerRegisters.size() > 1) { MITK_WARN << "Multiple provider for class id'" << id << "' found. Using just one."; } result = us::GetModuleContext()->GetService(providerRegisters.front()); } return result; }; mitk::DataStorageInspectorGenerator::ProviderMapType mitk::DataStorageInspectorGenerator::GetProviders() { std::vector > providerRegisters = us::GetModuleContext()->GetServiceReferences(); ProviderMapType result; for (const auto ®s : providerRegisters) { auto provider = us::GetModuleContext()->GetService(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 -#include +#include #include #include #include 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> 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/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 #include #include #include #include -#include +#include mitk::RESTManager::RESTManager() {} mitk::RESTManager::~RESTManager() {} pplx::task mitk::RESTManager::SendRequest( const web::uri &uri, const RequestType &type, const std::map headers) { pplx::task 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 mitk::RESTManager::SendBinaryRequest( const web::uri &uri, const RequestType &type, const std::vector *content, const std::map headers) { pplx::task 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 mitk::RESTManager::SendJSONRequest( const web::uri &uri, const RequestType &type, const web::json::value *content, const std::map headers, const utility::string_t &filePath) { pplx::task 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 &mitk::RESTManager::GetServerMap() { return m_ServerMap; } std::map, 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 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 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, 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 key, IRESTObserver *observer) { m_Observers[key] = observer; } 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 #include 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(&e); if (pEvent) { testCOUT = testCOUT + pEvent->GetOutput(); MITK_INFO << testCOUT; } const auto *pErrEvent = dynamic_cast(&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 #include #include #include /** * @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/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 #include -#include +#include /**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/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 +#include #include -#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 -#include +#include namespace berry { LogImpl::LogImpl(const QSharedPointer& plugin) : plugin(plugin) { } LogImpl::~LogImpl() { } void LogImpl::AddLogListener(ILogListener* /*listener*/) { } QSharedPointer LogImpl::GetBundle() const { return plugin; } void LogImpl::Log(const SmartPointer& 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 #include #include #include #include #include #include #include #include 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 *tmp=m_Active; m_Active=m_Pending; m_Pending=tmp; m_Mutex.unlock(); int num = static_cast(m_Pending->size()); if (num > 0) { int row = static_cast(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; m_Pending=new QList; 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(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; messagerowCount(QModelIndex()); message++) { for (int column=0; columncolumnCount(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 #include #include #include #include "berryLog.h" #include 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 m_Entries; QList *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.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 #include #include #include "internal/mitkDataStorageService.h" #include #include #include #include #include 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(lightObjectToQObjectAdapter) void* qt_metacast(const char *_clname) override { if (!_clname) return nullptr; if (!strcmp(_clname, "InterfaceMapToQObjectAdapter")) return static_cast(const_cast(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(dataStorageService.data()); // Get the MitkCore Module Context mitkContext = us::ModuleRegistry::GetModule(1)->GetModuleContext(); // Process all already registered services std::vector refs = mitkContext->GetServiceReferences(""); for (std::vector::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(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(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(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(ref.GetProperty(us::ServiceConstants::SERVICE_ID())); props.insert("mitk.serviceid", QVariant::fromValue(mitkServiceId)); // Add all other properties from the MITK micro service std::vector keys; ref.GetPropertyKeys(keys); for (std::vector::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(value))); } else if (objType == typeid(std::vector)) { const std::vector& list = us::ref_any_cast >(value); QStringList qlist; for (std::vector::const_iterator str = list.begin(); str != list.end(); ++str) { qlist << QString::fromStdString(*str); } props.insert(key, qlist); } else if (objType == typeid(std::list)) { const std::list& list = us::ref_any_cast >(value); QStringList qlist; for (std::list::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(value))); } else if (objType == typeid(unsigned char)) { props.insert(key, QChar(us::ref_any_cast(value))); } else if (objType == typeid(bool)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(short)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(unsigned short)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(int)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(unsigned int)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(float)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(double)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(long long int)) { props.insert(key, us::any_cast(value)); } else if (objType == typeid(unsigned long long int)) { props.insert(key, us::any_cast(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.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 #include "internal/org_mitk_gui_qt_application_Activator.h" #include #include #include #include #include -#include +#include #include #include #include using namespace std; static std::vector 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 prefPages(xpService->GetConfigurationElementsFor("org.blueberry.ui.preferencePages")); QList keywordExts(xpService->GetConfigurationElementsFor("org.blueberry.ui.keywords")); QList::iterator prefPagesIt; QList::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 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::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 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::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::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.
* Therefore this method flushes all the preferences, every time a change in the preferences is
* 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 selectedItems = d->m_PreferencesTree->selectedItems(); if(selectedItems.size()>0) { d->m_CurrentPage = 0; berry::IWorkbench* workbench = berry::PlatformUI::GetWorkbench(); for(QList::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("class"); it->prefPage = dynamic_cast(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 items; std::list< QList::iterator > deferredItems; for (QList::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 ¤tItemContent : 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::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::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 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.common/src/QmitkAbstractView.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp index caefe8515f..ba86a491f2 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp @@ -1,521 +1,521 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) 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 +#include #include #include #include #include #include #include #include // berry Includes #include #include #include #include // CTK Includes #include // Qt Includes #include #include #include #include #include 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(q)) return; if(selection.IsNull()) { q->OnNullSelection(sourcepart); return; } mitk::DataNodeSelection::ConstPointer _DataNodeSelection = selection.Cast(); q->OnSelectionChanged(sourcepart, this->DataNodeSelectionToQList(_DataNodeSelection)); } /** * Converts a mitk::DataNodeSelection to a QList (possibly empty) */ QList DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const; QmitkAbstractView* const q; ctkServiceTracker 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 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(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 ( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) ); this->GetDataStorage()->ChangedNodeEvent.AddListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) ); this->GetDataStorage()->RemoveNodeEvent.AddListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy ) ); // REGISTER PREFERENCES LISTENER auto* prefs = this->GetPreferences(); if (prefs != nullptr) prefs->OnChanged.AddListener(mitk::MessageDelegate1(this, &QmitkAbstractView::OnPreferencesChanged)); // REGISTER FOR WORKBENCH SELECTION EVENTS d->m_BlueBerrySelectionListener.reset(new berry::NullSelectionChangedAdapter( 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 ( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) ); this->GetDataStorage()->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy) ); this->GetDataStorage()->ChangedNodeEvent.RemoveListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) ); auto* prefs = this->GetPreferences(); if(prefs != nullptr) prefs->OnChanged.RemoveListener(mitk::MessageDelegate1(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(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 QmitkAbstractView::GetCurrentSelection() const { berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection()); mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast(); return d->DataNodeSelectionToQList(currentSelection); } bool QmitkAbstractView::IsCurrentSelectionValid() const { return this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection(); } QList QmitkAbstractView::GetDataManagerSelection() const { berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast(); 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()->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& /*nodes*/) { } void QmitkAbstractView::OnNullSelection(berry::IWorkbenchPart::Pointer /*part*/) { } QList QmitkAbstractViewPrivate::DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const { if (currentSelection.IsNull()) return QList(); return QList::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 nodes; nodes << node; this->FireNodesSelected(nodes); } void QmitkAbstractView::FireNodesSelected( const QList& 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/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 -#include +#include #include #include "QmitkNodeSelectionPreferencePage.h" #include 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 #include -#include +#include #include #include #include #include #include #include #include "mitkImage.h" #include #include #include #include #include #include #include #include #include #include "mitkBaseDICOMReaderService.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 > readerOutput = doseReader->Read(); if (!readerOutput.empty()){ mitk::Image::Pointer doseImage = dynamic_cast(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* storageService = mitk::PluginActivator::getContext()->getService(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 > readerOutput = structReader->Read(); if (readerOutput.empty()){ MITK_ERROR << "No structure sets were created" << endl; } else { std::vector modelVector; ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); for (const auto& aStruct : readerOutput){ mitk::ContourModelSet::Pointer countourModelSet = dynamic_cast(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 > readerOutput = planReader->Read(); if (!readerOutput.empty()){ //there is no image, only the properties are interesting mitk::Image::Pointer planDummyImage = dynamic_cast(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* storageService = mitk::PluginActivator::getContext()->getService(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* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); std::vector 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(); if (ref) { ctkEventAdmin* eventAdmin = mitk::PluginActivator::getContext()->getService(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 #include -#include +#include #include #include 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 #include -#include +#include #include #include #include #include #include #include #include #include #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(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.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 -#include +#include #include #include #include #include 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* configAdmin = nullptr; if (cmRef) { configAdmin = context->getService(cmRef); } // Use the CTK Configuration Admin service to configure the BlueBerry help system if (configAdmin) { ctkConfigurationPtr conf = configAdmin->getConfiguration("org.blueberry.services.help", QString()); ctkDictionary helpProps; helpProps.insert("homePage", "qthelp://org.mitk.gui.qt.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.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 #include // Qmitk #include "QmitkIGTTrackingSemiAutomaticMeasurementView.h" // Qt #include #include #include #include // MITK #include #include -#include +#include #include "mitkHummelProtocolEvaluation.h" // POCO #include #include const std::string QmitkIGTTrackingSemiAutomaticMeasurementView::VIEW_ID = "org.mitk.views.igttrackingsemiautomaticmeasurement"; QmitkIGTTrackingSemiAutomaticMeasurementView::QmitkIGTTrackingSemiAutomaticMeasurementView() : m_Controls(nullptr) { m_NextFile = 0; m_FilenameVector = std::vector(); 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 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(); 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(); 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(); 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("NOT OK!"); m_referenceValid = false; } else { m_Controls->m_ReferenceOK->setText("OK"); 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(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(m_FilenameVector.size())) label << "Next Measurement: "; 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(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 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 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(); } -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 #include -#include "mbilogExports.h" -#include "mbilogTextBackendBase.h" -#include "mbilogLogMessage.h" -#include "mbilogLoggingTypes.h" +#include +#include +#include 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 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 m_lastNavigationMessages; std::vector 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 #include "IO/mitkUSNavigationStepTimer.h" #include #include #include #include #include #include #include "QmitkRenderWindow.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" #include "mitkCameraController.h" #include "mitkLayoutAnnotationRenderer.h" #include // scene serialization #include #include #include #include #include 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(m_AblationZonesVector.size()) < id) || (id < 0)) { return; } MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize; // create a vtk sphere with given radius vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(newSize / 2); vtkSphere->SetCenter(0, 0, 0); vtkSphere->SetPhiResolution(20); vtkSphere->SetThetaResolution(20); vtkSphere->Update(); mitk::Surface::Pointer zoneSurface = dynamic_cast(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 vtkSphere = vtkSmartPointer::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)), this, SLOT(OnSettingsChanged(itk::SmartPointer))); } 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(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(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(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(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(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(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 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( 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 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(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> refs = context->GetServiceReferences(); 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 #include // Qmitk #include "QmitkMITKIGTTrackingToolboxView.h" // Qt #include #include -#include +#include // MITK #include #include #include #include #include #include -#include +#include #include #include #include //for exceptions #include #include #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()); QList serviceReference = pluginContext->getServiceReferences(interfaceName); if (serviceReference.size() > 0) { m_DeviceTypeServiceReference = serviceReference.at(0); const ctkServiceReference& r = serviceReference.at(0); m_DeviceTypeCollection = pluginContext->getService(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 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(""); 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(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 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(""); //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: "<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.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 -#include +#include #include #include #include #include #include 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.viewnavigator/src/QmitkViewNavigatorWidget.cpp b/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkViewNavigatorWidget.cpp index a87411cba5..d431fa5643 100644 --- a/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkViewNavigatorWidget.cpp +++ b/Plugins/org.mitk.gui.qt.viewnavigator/src/QmitkViewNavigatorWidget.cpp @@ -1,730 +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 #include #include // Blueberry #include #include #include #include #include #include #include #include // MITK -#include +#include // Qt #include #include #include #include #include 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 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(sourceModel())->itemFromIndex(index); if (type.contains(filterRegExp())) { return true; } QmitkViewItem* viewItem = dynamic_cast(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(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 viewParts = page->GetViews(); // iterate over all tree items for (const auto& item : m_TreeModel->findItems("*", Qt::MatchWildcard | Qt::MatchRecursive)) { 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(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(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(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(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(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 perspectiveDescriptors(perspRegistry->GetPerspectives()); qSort(perspectiveDescriptors.begin(), perspectiveDescriptors.end(), comparePerspectives); QStandardItem* perspectiveRootItem = new QStandardItem("Perspectives"); perspectiveRootItem->setFont(getLargeFont()); perspectiveRootItem->setEditable(false); QStandardItem* treeRootItem = m_TreeModel->invisibleRootItem(); treeRootItem->appendRow(perspectiveRootItem); this->AddItemsToTree, QmitkPerspectiveItem>( perspectiveDescriptors, perspectiveRootItem); } void QmitkViewNavigatorWidget::AddViewsToTree() { berry::IViewRegistry* viewRegistry = berry::PlatformUI::GetWorkbench()->GetViewRegistry(); QList viewDescriptors(viewRegistry->GetViews()); qSort(viewDescriptors.begin(), viewDescriptors.end(), compareViews); auto largeFont = getLargeFont(); QStandardItem* viewRootItem = new QStandardItem("Views"); viewRootItem->setFont(largeFont); viewRootItem->setEditable(false); QStandardItem* treeRootItem = m_TreeModel->invisibleRootItem(); treeRootItem->appendRow(viewRootItem); QStandardItem* miscellaneousCategoryItem = new QStandardItem("Miscellaneous"); 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, QmitkViewItem>( viewDescriptors, viewRootItem, miscellaneousCategoryItem, viewExcludeList); } template void QmitkViewNavigatorWidget::AddItemsToTree(D itemDescriptors, QStandardItem* rootItem, QStandardItem* miscellaneousItem, const QStringList& itemExcludeList) { KeywordRegistry keywordRegistry; std::vector 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); } 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.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 #include #include -#include "mitkLogMacros.h" +#include "mitkLog.h" #include #include #include #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 - -#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 - 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 - 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 - inline NullStream &operator<<(const T & /*data*/) - { - return *this; - } - template - 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 - // 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 -#include -#include - -#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 - -#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 - -#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