diff --git a/CMake/Whitelists/Wrapping.cmake b/CMake/Whitelists/Wrapping.cmake new file mode 100644 index 0000000000..33ae5929a0 --- /dev/null +++ b/CMake/Whitelists/Wrapping.cmake @@ -0,0 +1,10 @@ +set(enabled_modules + Core + CommandLine + CppMicroServices + Classification +) + +set(enabled_plugins + "" +) \ No newline at end of file diff --git a/CMake/mitkLanguageOptions.cmake b/CMake/mitkLanguageOptions.cmake new file mode 100644 index 0000000000..5b469dd9c5 --- /dev/null +++ b/CMake/mitkLanguageOptions.cmake @@ -0,0 +1,258 @@ +# +# - This module finds the languages supported by MITK, and +#present the option to enable support +# + +# +# Currently this will search for Python, +# Java, TCL, Ruby, C#, R, and additionally it give the option to wrap LUA. will be added +# This script is based on SimpleITK scripts. +# + +#include(sitkTargetLinkLibrariesWithDynamicLookup) +# +#sitk_check_dynamic_lookup(MODULE +# SHARED +# SITK_UNDEFINED_SYMBOLS_ALLOWED +# ) + +option(WRAP_DEFAULT "The default initial value for wrapping a language when it is detected on the system." ON) +mark_as_advanced(WRAP_DEFAULT) + +# +# Macro to set "_QUIET" and "_QUIET_LIBRARY" based on the first +# argument being defined and true, to either REQUIRED or QUIET. +# +macro(set_QUIET var) + if ( DEFINED ${var} AND ${var} ) + set( _QUIET "REQUIRED" ) + else() + set( _QUIET "QUIET" ) + endif() + if ( SITK_UNDEFINED_SYMBOLS_ALLOWED ) + set( _QUIET_LIBRARY "QUIET" ) + else() + set( _QUIET_LIBRARY ${_QUIET} ) + endif() +endmacro() + +# +# Setup the option for each language +# + +#----------------------------------------------------------- +# Lua + +#set_QUIET( WRAP_LUA ) +#find_package ( Lua ${_QUIET} ) +# +#if ( LUA_FOUND ) +# set( WRAP_LUA_DEFAULT ${WRAP_DEFAULT} ) +#else() +# set( WRAP_LUA_DEFAULT OFF ) +#endif() +# +#set( LUA_ADDITIONAL_LIBRARIES "" CACHE STRING "Additional libraries which may be needed for lua such as readline.") +#mark_as_advanced( LUA_ADDITIONAL_LIBRARIES ) +# +#option ( WRAP_LUA "Wrap Lua" ${WRAP_LUA_DEFAULT} ) +# +#if ( WRAP_LUA ) +# find_package( LuaInterp REQUIRED ) +# list( APPEND SITK_LANGUAGES_VARS +# LUA_EXECUTABLE +# LUA_LIBRARIES +# LUA_INCLUDE_DIR +# LUA_VERSION_STRING +# LUA_MATH_LIBRARY +# LUA_ADDITIONAL_LIBRARIES +# ) +#endif() + + +#----------------------------------------------------------- +# Python + +set_QUIET( WRAP_PYTHON ) +find_package ( PythonInterp ${_QUIET}) +if ( PYTHONINTERP_FOUND ) + find_package ( PythonLibs ${PYTHON_VERSION_STRING} EXACT ${_QUIET_LIBRARY} ) +else () + find_package ( PythonLibs ${_QUIET_LIBRARY} ) +endif() + +if ( PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND + AND (PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING) ) + set( WRAP_PYTHON_DEFAULT ${WRAP_DEFAULT} ) +else() + set( WRAP_PYTHON_DEFAULT OFF ) +endif() + +option( WRAP_PYTHON "Wrap Python" ${WRAP_PYTHON_DEFAULT} ) + +if ( WRAP_PYTHON AND PYTHON_VERSION_STRING VERSION_LESS 2.7 ) + message( WARNING "Python version less than 2.7: \"${PYTHON_VERSION_STRING}\"." ) +endif() + +if ( WRAP_PYTHON ) + list( APPEND SITK_LANGUAGES_VARS + PYTHON_DEBUG_LIBRARY + PYTHON_EXECUTABLE + PYTHON_LIBRARY + PYTHON_INCLUDE_DIR + # PYTHON_INCLUDE_PATH ( deprecated ) + ) +# Debian "jessie" has this additional variable required to match +# python versions. + if(PYTHON_INCLUDE_DIR2) + list( APPEND SITK_LANGUAGES_VARS + PYTHON_INCLUDE_DIR2 + ) + endif() +endif () + + +#----------------------------------------------------------- +# Java + +#set_QUIET( WRAP_JAVA ) +#find_package ( Java COMPONENTS Development Runtime ${_QUIET} ) +#find_package ( JNI ${_QUIET} ) +#if ( JAVA_FOUND AND JNI_FOUND ) +# set( WRAP_JAVA_DEFAULT ${WRAP_DEFAULT} ) +#else ( ${JAVA_FOUND} AND JNI_FOUND ) +# set( WRAP_JAVA_DEFAULT OFF ) +#endif ( ) +# +#option ( WRAP_JAVA "Wrap Java" ${WRAP_JAVA_DEFAULT} ) +# +#if ( WRAP_JAVA ) +# list( APPEND SITK_LANGUAGES_VARS +# Java_JAVA_EXECUTABLE +# Java_JAVAC_EXECUTABLE +# Java_JAR_EXECUTABLE +# Java_JAVADOC_EXECUTABLE +# Java_JAVAH_EXECUTABLE +# Java_VERSION_STRING +# Java_VERSION_MAJOR +# Java_VERSION_MINOR +# Java_VERSION_PATCH +# Java_VERSION_TWEAK +# Java_VERSION +# Java_INCLUDE_DIRS +# Java_LIBRARIES +# JNI_INCLUDE_DIRS +# JNI_LIBRARIES +# JAVA_AWT_LIBRARY +# JAVA_JVM_LIBRARY +# JAVA_INCLUDE_PATH +# JAVA_INCLUDE_PATH2 +# JAVA_AWT_INCLUDE_PATH +# ) +#endif() +# + +#----------------------------------------------------------- +# Tcl + +#set_QUIET(WRAP_TCL) +# +#find_package ( TCL ${_QUIET} ) +# +#if ( TCL_FOUND ) +# set ( WRAP_TCL_DEFAULT ${WRAP_DEFAULT} ) +#else ( ) +# set ( WRAP_TCL_DEFAULT OFF ) +#endif ( ) +# +#option ( WRAP_TCL "Wrap Tcl" ${WRAP_TCL_DEFAULT} ) +# +#if ( WRAP_TCL ) +# list( APPEND SITK_LANGUAGES_VARS +# TCL_LIBRARY +# TCL_INCLUDE_PATH +# TCL_TCLSH +# TK_LIBRARY +# TK_INCLUDE_PATH +# TK_WISH +# ) +#endif() +# +# +##----------------------------------------------------------- +## Ruby +# +#set_QUIET( WRAP_RUBY ) +# +#find_package ( Ruby ${_QUIET} ) +#if ( RUBY_FOUND ) +# set ( WRAP_RUBY_DEFAULT ${WRAP_DEFAULT} ) +#else ( ) +# set ( WRAP_RUBY_DEFAULT OFF ) +#endif ( ) +# +#option ( WRAP_RUBY "Wrap Ruby" ${WRAP_RUBY_DEFAULT} ) +# +#if ( WRAP_RUBY ) +# list( APPEND SITK_LANGUAGES_VARS +# RUBY_EXECUTABLE +# RUBY_INCLUDE_DIRS +# RUBY_LIBRARY +# RUBY_VERSION +# RUBY_FOUND +# RUBY_INCLUDE_PATH +# ) +#endif() +# +# +##----------------------------------------------------------- +## CSharp +# +#set_QUIET( WRAP_CSHARP ) +# +#find_package( CSharp ${_QUIET} ) +#if ( CSHARP_FOUND AND NOT MINGW ) +# set ( WRAP_CSHARP_DEFAULT ${WRAP_DEFAULT} ) +#else () +# set ( WRAP_CSHARP_DEFAULT OFF ) +#endif () +# +#option ( WRAP_CSHARP "Wrap C#" ${WRAP_CSHARP_DEFAULT} ) +# +#if ( WRAP_CSHARP ) +# list( APPEND SITK_LANGUAGES_VARS +# CSHARP_COMPILER +# CSHARP_INTERPRETER +# CSHARP_PLATFORM +# ) +#endif() +# +# +##----------------------------------------------------------- +## R +# +#set_QUIET( WRAP_R ) +# +#find_package(R ${_QUIET}) +#if ( R_FOUND AND NOT WIN32 ) +# set ( WRAP_R_DEFAULT ${WRAP_DEFAULT} ) +#else( ) +# set ( WRAP_R_DEFAULT OFF ) +#endif( ) +# +#option ( WRAP_R "Wrap R" ${WRAP_R_DEFAULT} ) +# +#if ( WRAP_R ) +# list( APPEND SITK_LANGUAGES_VARS +# R_INCLUDE_DIR +# R_LIBRARIES +# R_LIBRARY_BASE +# R_COMMAND +# RSCRIPT_EXECUTABLE ) +#endif() +# +# +#if( WIN32 ) +# mark_as_advanced( WRAP_R ) +#endif() +# \ No newline at end of file diff --git a/CMake/mitkSWIGConfigurePythonfileBuildtime.cmake b/CMake/mitkSWIGConfigurePythonfileBuildtime.cmake new file mode 100644 index 0000000000..87391853f4 --- /dev/null +++ b/CMake/mitkSWIGConfigurePythonfileBuildtime.cmake @@ -0,0 +1,19 @@ +INCLUDE(GetPrerequisites) + +#file(GLOB_RECURSE TARGET_LIBRARY_FILE ${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/*/${MITK_BINARY_MODULE}) +find_file(TARGET_LIBRARY_FILE "${MITK_BINARY_MODULE}" + ${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../lib/Release + ${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../lib + ${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/.. + ${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY} + ${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release) +get_filename_component(TARGET_LIBRARY_DIR ${TARGET_LIBRARY_FILE} DIRECTORY ) + +#mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH release) +list(APPEND MITK_RUNTIME_PATH + "${TARGET_LIBRARY_DIR}") +list(REMOVE_DUPLICATES MITK_RUNTIME_PATH) + +get_prerequisites(${TARGET_LIBRARY_FILE} PYTHON_LIB_DEPENDENCIES 1 1 "" "${MITK_RUNTIME_PATH}") + +configure_file( "${CONFIGUREBUILDTIME_filename}" "${CONFIGUREBUILDTIME_out_filename}" ) diff --git a/CMake/mitkSwigAddLibraryDependencies.cmake b/CMake/mitkSwigAddLibraryDependencies.cmake new file mode 100644 index 0000000000..534d77ed80 --- /dev/null +++ b/CMake/mitkSwigAddLibraryDependencies.cmake @@ -0,0 +1,43 @@ +#! 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" +#! + + +# 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. + foreach(INCLUDE_PATH ${LIBRARY_INCLUDES}) + file(GLOB_RECURSE header_files "${INCLUDE_PATH}/*.h") + list(APPEND SWIG_MODULE_${swig_module}_EXTRA_DEPS ${header_files}) + # export variable to parent scope + set(SWIG_MODULE_${swig_module}_EXTRA_DEPS + ${SWIG_MODULE_${swig_module}_EXTRA_DEPS} PARENT_SCOPE) + endforeach() + endforeach() + + # In addition include python dependencies: + include_directories( ${PYTHON_INCLUDE_DIR}) + list(APPEND SWIG_MODULE_${swig_module}_EXTRA_DEPS ${PYTHON_INCLUDE_DIR}) + #swig_link_libraries(${swig_module} ${PYTHON_LIBRARIES} ) + + # Add additional include paths, for example to the common files: + list(APPEND SWIG_MODULE_${swig_module}_EXTRA_DEPS ${SWIG_EXTRA_DEPS}) + + set(SWIG_MODULE_${swig_module}_EXTRA_DEPS + ${SWIG_MODULE_${swig_module}_EXTRA_DEPS} PARENT_SCOPE) +endfunction() diff --git a/CMake/mitkSwigPrepareFiles.cmake b/CMake/mitkSwigPrepareFiles.cmake new file mode 100644 index 0000000000..8408f7e9f6 --- /dev/null +++ b/CMake/mitkSwigPrepareFiles.cmake @@ -0,0 +1,39 @@ + +# This function is used to prepare all includes and files +# that are necessary for a general swig project. +function(mitkSwigPrepareFiles swig_file library_names) + # Ensure that the input file is parsed as a c++ file. This is done via + # an additional source file property. + set_source_files_properties ( ${swig_file} PROPERTIES CPLUSPLUS ON ) + + # This variable is used to add additional parameters to SWIG. + # Using a list is necessary in order to be able to pass multiple parameters + # which are given as optional parameters to the input file. + set(ADDITIONAL_TMP_SWIG_INCLUDES "") + + foreach(library_name ${library_names}) + # 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) + # Adding each include path as an additional swig parameter using + # the swig-option "-I": + foreach(INCLUDE_PATH ${LIBRARY_INCLUDES}) + list(APPEND ADDITIONAL_TMP_SWIG_INCLUDES -I${INCLUDE_PATH} ) + endforeach() + endforeach() + + # Add the Common Folder to the include system of SWIG + list(APPEND ADDITIONAL_TMP_SWIG_INCLUDES -I${MITK_WRAPPING_COMMON_DIR} ) + + # This is necessary, because SWIG hard-codeds the integer size. See + # https://github.com/swig/swig/issues/568 + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + list(APPEND ADDITIONAL_TMP_SWIG_INCLUDES -DSWIGWORDSIZE64) + endif() + + + # Set the additional parameters to the input project file: + set_property(SOURCE ${swig_file} PROPERTY SWIG_FLAGS ${ADDITIONAL_TMP_SWIG_INCLUDES} ) +endfunction() diff --git a/CMake/mitkTargetLinkLibrariesWithDynamicLookup.cmake b/CMake/mitkTargetLinkLibrariesWithDynamicLookup.cmake new file mode 100644 index 0000000000..941d25044e --- /dev/null +++ b/CMake/mitkTargetLinkLibrariesWithDynamicLookup.cmake @@ -0,0 +1,581 @@ +#.rst: +# +# Public Functions +# ^^^^^^^^^^^^^^^^ +# +# The following functions are defined: +# +# .. cmake:command:: mitk_target_link_libraries_with_dynamic_lookup +# +# :: +# +# mitk_target_link_libraries_with_dynamic_lookup( []) +# +# +# Useful to "weakly" link a loadable module. For example, it should be used +# when compiling a loadable module when the symbols should be resolve from +# the run-time environment where the module is loaded, and not a specific +# system library. +# +# Like proper linking, except that the given ```` are not necessarily +# linked. Instead, the ```` is produced in a manner that allows for +# symbols unresolved within it to be resolved at runtime, presumably by the +# given ````. If such a target can be produced, the provided +# ```` are not actually linked. +# +# It links a library to a target such that the symbols are resolved at +# run-time not link-time. +# +# The linker is checked to see if it supports undefined +# symbols when linking a shared library. If it does then the library +# is not linked when specified with this function. +# +# On platforms that do not support weak-linking, this function works just +# like ``mitk_target_link_libraries``. +# +# .. note:: +# +# For OSX it uses ``undefined dynamic_lookup``. This is similar to using +# ``-shared`` on Linux where undefined symbols are ignored. +# +# For more details, see `blog `_ +# from Tim D. Smith. +# +# +# .. cmake:command:: mitk_check_dynamic_lookup +# +# Check if the linker requires a command line flag to allow leaving symbols +# unresolved when producing a target of type ```` that is +# weakly-linked against a dependency of type ````. +# +# ```` +# can be one of "STATIC", "SHARED", "MODULE", or "EXE". +# +# ```` +# can be one of "STATIC", "SHARED", or "MODULE". +# +# Long signature: +# +# :: +# +# mitk_check_dynamic_lookup( +# +# +# []) +# +# +# Short signature: +# +# :: +# +# mitk_check_dynamic_lookup() # set to "MODULE" +# # set to "SHARED" +# +# +# The result is cached between invocations and recomputed only when the value +# of CMake's linker flag list changes; ``CMAKE_STATIC_LINKER_FLAGS`` if +# ```` is "STATIC", and ``CMAKE_SHARED_LINKER_FLAGS`` otherwise. +# +# +# Defined variables: +# +# ```` +# Whether the current C toolchain supports weak-linking for target binaries of +# type ```` that are weakly-linked against a dependency target of +# type ````. +# +# ```` +# List of flags to add to the linker command to produce a working target +# binary of type ```` that is weakly-linked against a dependency +# target of type ````. +# +# ``HAS_DYNAMIC_LOOKUP__`` +# Cached, global alias for ```` +# +# ``DYNAMIC_LOOKUP_FLAGS__`` +# Cached, global alias for ```` +# +# +# Private Functions +# ^^^^^^^^^^^^^^^^^ +# +# The following private functions are defined: +# +# .. warning:: These functions are not part of the scikit-build API. They +# exist purely as an implementation detail and may change from version +# to version without notice, or even be removed. +# +# We mean it. +# +# +# .. cmake:command:: _get_target_type +# +# :: +# +# _get_target_type( ) +# +# +# Shorthand for querying an abbreviated version of the target type +# of the given ````. +# +# ```` is set to: +# +# - "STATIC" for a STATIC_LIBRARY, +# - "SHARED" for a SHARED_LIBRARY, +# - "MODULE" for a MODULE_LIBRARY, +# - and "EXE" for an EXECUTABLE. +# +# Defined variables: +# +# ```` +# The abbreviated version of the ````'s type. +# +# +# .. cmake:command:: _test_weak_link_project +# +# :: +# +# _test_weak_link_project( +# +# +# ) +# +# +# Attempt to compile and run a test project where a target of type +# ```` is weakly-linked against a dependency of type ````: +# +# - ```` can be one of "STATIC", "SHARED", "MODULE", or "EXE". +# - ```` can be one of "STATIC", "SHARED", or "MODULE". +# +# Defined variables: +# +# ```` +# Whether the current C toolchain can produce a working target binary of type +# ```` that is weakly-linked against a dependency target of type +# ````. +# +# ```` +# List of flags to add to the linker command to produce a working target +# binary of type ```` that is weakly-linked against a dependency +# target of type ````. +# + +function(_get_target_type result_var target) + set(target_type "SHARED_LIBRARY") + if(TARGET ${target}) + get_property(target_type TARGET ${target} PROPERTY TYPE) + endif() + + set(result "STATIC") + + if(target_type STREQUAL "STATIC_LIBRARY") + set(result "STATIC") + endif() + + if(target_type STREQUAL "SHARED_LIBRARY") + set(result "SHARED") + endif() + + if(target_type STREQUAL "MODULE_LIBRARY") + set(result "MODULE") + endif() + + if(target_type STREQUAL "EXECUTABLE") + set(result "EXE") + endif() + + set(${result_var} ${result} PARENT_SCOPE) +endfunction() + + +function(_test_weak_link_project + target_type + lib_type + can_weak_link_var + project_name) + + set(gnu_ld_ignore "-Wl,--unresolved-symbols=ignore-all") + set(osx_dynamic_lookup "-undefined dynamic_lookup") + set(no_flag "") + + foreach(link_flag_spec gnu_ld_ignore osx_dynamic_lookup no_flag) + set(link_flag "${${link_flag_spec}}") + + set(test_project_dir "${PROJECT_BINARY_DIR}/CMakeTmp") + set(test_project_dir "${test_project_dir}/${project_name}") + set(test_project_dir "${test_project_dir}/${link_flag_spec}") + set(test_project_dir "${test_project_dir}/${target_type}") + set(test_project_dir "${test_project_dir}/${lib_type}") + + set(test_project_src_dir "${test_project_dir}/src") + set(test_project_bin_dir "${test_project_dir}/build") + + file(MAKE_DIRECTORY ${test_project_src_dir}) + file(MAKE_DIRECTORY ${test_project_bin_dir}) + + set(mod_type "STATIC") + set(link_mod_lib TRUE) + set(link_exe_lib TRUE) + set(link_exe_mod FALSE) + + if("${target_type}" STREQUAL "EXE") + set(link_exe_lib FALSE) + set(link_exe_mod TRUE) + else() + set(mod_type "${target_type}") + endif() + + if("${mod_type}" STREQUAL "MODULE") + set(link_mod_lib FALSE) + endif() + + + file(WRITE "${test_project_src_dir}/CMakeLists.txt" " + cmake_minimum_required(VERSION ${CMAKE_VERSION}) + project(${project_name} C) + + include_directories(${test_project_src_dir}) + + add_library(number ${lib_type} number.c) + add_library(counter ${mod_type} counter.c) + ") + + if("${mod_type}" STREQUAL "MODULE") + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + set_target_properties(counter PROPERTIES PREFIX \"\") + ") + endif() + + if(link_mod_lib) + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + target_link_libraries(counter number) + ") + elseif(NOT link_flag STREQUAL "") + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + set_target_properties(counter PROPERTIES LINK_FLAGS \"${link_flag}\") + ") + endif() + + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + add_executable(main main.c) + ") + + if(link_exe_lib) + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + target_link_libraries(main number) + ") + elseif(NOT link_flag STREQUAL "") + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + target_link_libraries(main \"${link_flag}\") + ") + endif() + + if(link_exe_mod) + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + target_link_libraries(main counter) + ") + else() + file(APPEND "${test_project_src_dir}/CMakeLists.txt" " + target_link_libraries(main \"${CMAKE_DL_LIBS}\") + ") + endif() + + file(WRITE "${test_project_src_dir}/number.c" " + #include + + static int _number; + void set_number(int number) { _number = number; } + int get_number() { return _number; } + ") + + file(WRITE "${test_project_src_dir}/number.h" " + #ifndef _NUMBER_H + #define _NUMBER_H + extern void set_number(int); + extern int get_number(void); + #endif + ") + + file(WRITE "${test_project_src_dir}/counter.c" " + #include + int count() { + int result = get_number(); + set_number(result + 1); + return result; + } + ") + + file(WRITE "${test_project_src_dir}/counter.h" " + #ifndef _COUNTER_H + #define _COUNTER_H + extern int count(void); + #endif + ") + + file(WRITE "${test_project_src_dir}/main.c" " + #include + #include + #include + ") + + if(NOT link_exe_mod) + file(APPEND "${test_project_src_dir}/main.c" " + #include + ") + endif() + + file(APPEND "${test_project_src_dir}/main.c" " + int my_count() { + int result = get_number(); + set_number(result + 1); + return result; + } + + int main(int argc, char **argv) { + int result; + ") + + if(NOT link_exe_mod) + file(APPEND "${test_project_src_dir}/main.c" " + void *counter_module; + int (*count)(void); + + counter_module = dlopen(\"./counter.so\", RTLD_LAZY | RTLD_GLOBAL); + if(!counter_module) goto error; + + count = dlsym(counter_module, \"count\"); + if(!count) goto error; + ") + endif() + + file(APPEND "${test_project_src_dir}/main.c" " + result = count() != 0 ? EXIT_FAILURE : + my_count() != 1 ? EXIT_FAILURE : + my_count() != 2 ? EXIT_FAILURE : + count() != 3 ? EXIT_FAILURE : + count() != 4 ? EXIT_FAILURE : + count() != 5 ? EXIT_FAILURE : + my_count() != 6 ? EXIT_FAILURE : EXIT_SUCCESS; + ") + + if(NOT link_exe_mod) + file(APPEND "${test_project_src_dir}/main.c" " + goto done; + error: + fprintf(stderr, \"Error occured:\\n %s\\n\", dlerror()); + result = 1; + + done: + if(counter_module) dlclose(counter_module); + ") + endif() + + file(APPEND "${test_project_src_dir}/main.c" " + return result; + } + ") + + set(_rpath_arg) + if(APPLE AND ${CMAKE_VERSION} VERSION_GREATER 2.8.11) + set(_rpath_arg "-DCMAKE_MACOSX_RPATH='${CMAKE_MACOSX_RPATH}'") + endif() + + try_compile(project_compiles + "${test_project_bin_dir}" + "${test_project_src_dir}" + "${project_name}" + CMAKE_FLAGS + "-DCMAKE_SHARED_LINKER_FLAGS='${CMAKE_SHARED_LINKER_FLAGS}'" + "-DCMAKE_ENABLE_EXPORTS=ON" + ${_rpath_arg} + OUTPUT_VARIABLE compile_output) + + set(project_works 1) + set(run_output) + + if(project_compiles) + execute_process(COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} + "${test_project_bin_dir}/main" + WORKING_DIRECTORY "${test_project_bin_dir}" + RESULT_VARIABLE project_works + OUTPUT_VARIABLE run_output + ERROR_VARIABLE run_output) + endif() + + set(test_description + "Weak Link ${target_type} -> ${lib_type} (${link_flag_spec})") + + if(project_works EQUAL 0) + set(project_works TRUE) + message(STATUS "Performing Test ${test_description} - Success") + else() + set(project_works FALSE) + message(STATUS "Performing Test ${test_description} - Failed") + file(APPEND ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing Test ${test_description} failed with the " + "following output:\n" + "BUILD\n-----\n${compile_output}\nRUN\n---\n${run_output}\n") + endif() + + set(${can_weak_link_var} ${project_works} PARENT_SCOPE) + if(project_works) + set(${project_name} ${link_flag} PARENT_SCOPE) + break() + endif() + endforeach() +endfunction() + +function(mitk_check_dynamic_lookup) + # Two signatures are supported: + + if(ARGC EQUAL "1") + # + # mitk_check_dynamic_lookup() + # + set(target_type "MODULE") + set(lib_type "SHARED") + set(has_dynamic_lookup_var "${ARGV0}") + set(link_flags_var "unused") + + elseif(ARGC GREATER "2") + # + # mitk_check_dynamic_lookup( + # + # + # []) + # + set(target_type "${ARGV0}") + set(lib_type "${ARGV1}") + set(has_dynamic_lookup_var "${ARGV2}") + if(ARGC EQUAL "3") + set(link_flags_var "unused") + else() + set(link_flags_var "${ARGV3}") + endif() + else() + message(FATAL_ERROR "missing arguments") + endif() + + _check_dynamic_lookup( + ${target_type} + ${lib_type} + ${has_dynamic_lookup_var} + ${link_flags_var} + ) + set(${has_dynamic_lookup_var} ${${has_dynamic_lookup_var}} PARENT_SCOPE) + if(NOT "x${link_flags_var}x" MATCHES "^xunusedx$") + set(${link_flags_var} ${${link_flags_var}} PARENT_SCOPE) + endif() +endfunction() + +function(_check_dynamic_lookup + target_type + lib_type + has_dynamic_lookup_var + link_flags_var + ) + + # hash the CMAKE_FLAGS passed and check cache to know if we need to rerun + if("${target_type}" STREQUAL "STATIC") + string(MD5 cmake_flags_hash "${CMAKE_STATIC_LINKER_FLAGS}") + else() + string(MD5 cmake_flags_hash "${CMAKE_SHARED_LINKER_FLAGS}") + endif() + + set(cache_var "HAS_DYNAMIC_LOOKUP_${target_type}_${lib_type}") + set(cache_hash_var "HAS_DYNAMIC_LOOKUP_${target_type}_${lib_type}_hash") + set(result_var "DYNAMIC_LOOKUP_FLAGS_${target_type}_${lib_type}") + + if( NOT DEFINED ${cache_hash_var} + OR NOT "${${cache_hash_var}}" STREQUAL "${cmake_flags_hash}") + unset(${cache_var} CACHE) + endif() + + if(NOT DEFINED ${cache_var}) + set(skip_test FALSE) + + if(CMAKE_CROSSCOMPILING AND NOT CMAKE_CROSSCOMPILING_EMULATOR) + set(skip_test TRUE) + endif() + + if(skip_test) + set(has_dynamic_lookup FALSE) + set(link_flags) + else() + _test_weak_link_project(${target_type} + ${lib_type} + has_dynamic_lookup + link_flags) + endif() + + set(caveat " (when linking ${target_type} against ${lib_type})") + + set(${cache_var} "${has_dynamic_lookup}" + CACHE BOOL + "linker supports dynamic lookup for undefined symbols${caveat}") + mark_as_advanced(${cache_var}) + + set(${result_var} "${link_flags}" + CACHE STRING + "linker flags for dynamic lookup${caveat}") + mark_as_advanced(${result_var}) + + set(${cache_hash_var} "${cmake_flags_hash}" + CACHE INTERNAL "hashed flags for ${cache_var} check") + endif() + + set(${has_dynamic_lookup_var} "${${cache_var}}" PARENT_SCOPE) + set(${link_flags_var} "${${result_var}}" PARENT_SCOPE) +endfunction() + +function(mitk_target_link_libraries_with_dynamic_lookup target) + _get_target_type(target_type ${target}) + + set(link_props) + set(link_items) + set(link_libs) + + foreach(lib ${ARGN}) + _get_target_type(lib_type ${lib}) + mitk_check_dynamic_lookup(${target_type} + ${lib_type} + has_dynamic_lookup + dynamic_lookup_flags) + + if(has_dynamic_lookup) + if(dynamic_lookup_flags) + if("${target_type}" STREQUAL "EXE") + list(APPEND link_items "${dynamic_lookup_flags}") + else() + list(APPEND link_props "${dynamic_lookup_flags}") + endif() + endif() + else() + list(APPEND link_libs "${lib}") + endif() + endforeach() + + if(link_props) + list(REMOVE_DUPLICATES link_props) + endif() + + if(link_items) + list(REMOVE_DUPLICATES link_items) + endif() + + if(link_libs) + list(REMOVE_DUPLICATES link_libs) + endif() + + if(link_props) + set_target_properties(${target} + PROPERTIES LINK_FLAGS "${link_props}") + endif() + + set(links "${link_items}" "${link_libs}") + if(links) + target_link_libraries(${target} "${links}") + endif() +endfunction() + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ebef5008d..dac545eb49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1345 +1,1347 @@ set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.5) cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION}) #----------------------------------------------------------------------------- # See http://www.cmake.org/cmake/help/v3.5/manual/cmake-policies.7.html for details #----------------------------------------------------------------------------- set(project_policies ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # MITK Extension Feature #----------------------------------------------------------------------------- set(MITK_EXTENSION_DIRS "" CACHE STRING "") mark_as_advanced(MITK_EXTENSION_DIRS) #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Build MITK and the projects it depends on via SuperBuild.cmake." ON) if(MITK_USE_SUPERBUILD) project(MITK-superbuild) set(MITK_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(MITK_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(MITK VERSION 2016.11.99) include_directories(SYSTEM ${MITK_SUPERBUILD_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Update CMake module path #----------------------------------------------------------------------------- set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake) set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR}) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_CMAKE_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMake) get_filename_component(MITK_CMAKE_EXTENSION_DIR ${MITK_CMAKE_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_CMAKE_EXTENSION_DIR}) list(APPEND CMAKE_MODULE_PATH ${MITK_CMAKE_EXTENSION_DIR}) endif() endforeach() #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- # Standard CMake macros include(FeatureSummary) include(CTestUseLaunchers) include(CMakeParseArguments) include(FindPackageHandleStandardArgs) # MITK macros include(mitkFunctionGetGccVersion) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionEnableBuildConfiguration) include(mitkFunctionWhitelists) include(mitkFunctionAddExternalProject) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Check miminum Mac OS X version #----------------------------------------------------------------------------- # The minimum supported Mac OS X version is 10.9. If you use a version less than 10.9, there is no guarantee that the build still works. if(APPLE) exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE osx_version) if (osx_version VERSION_LESS "10.9") message(WARNING "Detected OS X version \"${osx_version}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") endif() if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.9) message(WARNING "Detected OS X deployment target \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") endif() endif() #----------------------------------------------------------------------------- # Check miminum compiler versions #----------------------------------------------------------------------------- if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # require at least gcc 4.9 as provided by ppa:ubuntu-toolchain-r/test for Ubuntu 14.04 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) message(FATAL_ERROR "GCC version must be at least 4.9 If you are using Ubuntu 14.04, you can easily install gcc and g++ 4.9 (or any later version available) in addition to your version ${CMAKE_CXX_COMPILER_VERSION}: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-4.9 g++-4.9 Make sure to explicitly specify these compilers when configuring MITK: CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-4.9 CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-4.9 For more information on the proposed PPA see the Toolchain Updates section of https://wiki.ubuntu.com/ToolChain.") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least clang 3.4 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) message(FATAL_ERROR "Clang version must be at least 3.4") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") # require at least clang 5.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) message(FATAL_ERROR "Apple Clang version must be at least 5.0") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # require at least Visual Studio 2015 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) message(FATAL_ERROR "Microsoft Visual Studio 2015 Update 3 or newer required") endif() else() message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang (Linux or Apple), GCC and MSVC.") endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) else() set(GCC_VERSION 0) endif() set(MITK_CXX_STANDARD 14) set(CMAKE_CXX_EXTENSIONS 0) set(CMAKE_CXX_STANDARD ${MITK_CXX_STANDARD}) set(CMAKE_CXX_STANDARD_REQUIRED 1) # This is necessary to avoid problems with compile feature checks. # CMAKE_CXX_STANDARD seems to only set the -std=c++14 flag for targets. # However, compile flag checks also need to be done with -std=c++14. # The MITK_CXX14_FLAG variable is also used for external projects # build during the MITK super-build. mitkFunctionCheckCompilerFlags("-std=c++14" MITK_CXX14_FLAG) #----------------------------------------------------------------------------- # Warn if source or build path is too long #----------------------------------------------------------------------------- if(WIN32) set(_src_dir_length_max 50) set(_bin_dir_length_max 50) if(MITK_USE_SUPERBUILD) set(_src_dir_length_max 34) # _src_dir_length_max - strlen(ep/src/ITK-build) set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build) endif() string(LENGTH "${MITK_SOURCE_DIR}" _src_n) string(LENGTH "${MITK_BINARY_DIR}" _bin_n) # The warnings should be converted to errors if(_src_n GREATER _src_dir_length_max) message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})." "Please move the MITK source code directory to a directory with a shorter path." ) endif() if(_bin_n GREATER _bin_dir_length_max) message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})." "Please move the MITK build directory to a directory with a shorter path." ) endif() endif() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- macro(env_option name doc value) set(_value $ENV{${name}}) if("${_value}" STREQUAL "") set(_value ${value}) endif() option(${name} "${doc}" ${_value}) endmacro() # ----------------------------------------- # General build options option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" OFF) option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON) mark_as_advanced(MITK_BUILD_ALL_APPS MITK_ENABLE_PIC_READER ) # ----------------------------------------- # Qt version related variables env_option(MITK_USE_Qt5 "Use Qt 5 library" ON) if(MITK_USE_Qt5) set(MITK_QT5_MINIMUM_VERSION 5.6.0) set(MITK_QT5_COMPONENTS Concurrent OpenGL PrintSupport Script Sql Svg Widgets Xml XmlPatterns WebEngineWidgets UiTools Help LinguistTools) if(APPLE) set(MITK_QT5_COMPONENTS ${MITK_QT5_COMPONENTS} DBus) endif() find_package(Qt5 ${MITK_QT5_MINIMUM_VERSION} COMPONENTS ${MITK_QT5_COMPONENTS} REQUIRED) if(Qt5_DIR) get_filename_component(_Qt5_DIR "${Qt5_DIR}/../../../" ABSOLUTE) list(FIND CMAKE_PREFIX_PATH "${_Qt5_DIR}" _result) if(_result LESS 0) set(CMAKE_PREFIX_PATH "${_Qt5_DIR};${CMAKE_PREFIX_PATH}" CACHE PATH "" FORCE) endif() endif() endif() set_property(GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS "") include(CMakeExternals/ExternalProjectList.cmake) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMakeExternals) get_filename_component(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_CMAKE_EXTERNALS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/ExternalProjectList.cmake) include(${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/ExternalProjectList.cmake) endif() endforeach() # ----------------------------------------- # Other MITK_USE_* options not related to # external projects build via the # MITK superbuild env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) #----------------------------------------------------------------------------- # Build configurations #----------------------------------------------------------------------------- set(_buildConfigs "Custom") file(GLOB _buildConfigFiles CMake/BuildConfigurations/*.cmake) foreach(_buildConfigFile ${_buildConfigFiles}) get_filename_component(_buildConfigFile ${_buildConfigFile} NAME_WE) list(APPEND _buildConfigs ${_buildConfigFile}) endforeach() set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations") set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS ${_buildConfigs}) mitkFunctionEnableBuildConfiguration() mitkFunctionCreateWhitelistPaths(MITK) mitkFunctionFindWhitelists(MITK) # ----------------------------------------- # Custom dependency logic option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF) set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries") # only windows can't build python in debug mode if(MITK_USE_Python AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" AND WIN32) message(WARNING "Disabling Python support. Building MITK Python in debug mode on Windowsis not supported!") set(MITK_USE_Python OFF CACHE BOOL "Use python wrapping in MITK" FORCE) set(MITK_USE_Numpy OFF CACHE BOOL "Use Numpy" FORCE) set(MITK_USE_SimpleITK OFF CACHE BOOL "Use SimpleITK" FORCE) elseif(MITK_USE_Python) set(MITK_USE_ZLIB ON) if(NOT MITK_USE_Numpy) message("> Forcing MITK_USE_Numpy to ON because of MITK_USE_Python") set(MITK_USE_Numpy ON CACHE BOOL "Use Numpy" FORCE) endif() if(NOT MITK_USE_SimpleITK) message("> Forcing MITK_USE_SimpleITK to ON because of MITK_USE_Python") set(MITK_USE_SimpleITK ON CACHE BOOL "Use SimpleITK" FORCE) endif() option(MITK_USE_SYSTEM_PYTHON "Use the system python runtime" OFF) if(MITK_USE_SYSTEM_PYTHON) find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) endif() elseif(MITK_USE_Python AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" AND WIN32) message(WARNING "Disabling Python support. Building MITK Python in debug mode on Windowsis not supported!") set(MITK_USE_Python OFF CACHE BOOL "Use python wrapping in MITK" FORCE) endif() if(BUILD_TESTING AND NOT MITK_USE_CppUnit) message("> Forcing MITK_USE_CppUnit to ON because BUILD_TESTING=ON") set(MITK_USE_CppUnit ON CACHE BOOL "Use CppUnit for unit tests" FORCE) endif() if(MITK_USE_BLUEBERRY) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) mark_as_advanced(MITK_BUILD_ALL_PLUGINS) if(NOT MITK_USE_CTK) message("> Forcing MITK_USE_CTK to ON because of MITK_USE_BLUEBERRY") set(MITK_USE_CTK ON CACHE BOOL "Use CTK in MITK" FORCE) endif() endif() #----------------------------------------------------------------------------- # Pixel type multiplexing #----------------------------------------------------------------------------- # Customize the default pixel types for multiplex macros set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS ) # consistency checks if(NOT MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES) set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES) set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES) set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) string(REPLACE "," ";" _integral_types ${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES}) string(REPLACE "," ";" _floating_types ${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES}) foreach(_scalar_type ${_integral_types} ${_floating_types}) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}itk::VariableLengthVector<${_scalar_type}>,") endforeach() string(LENGTH "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" _length) math(EXPR _length "${_length} - 1") string(SUBSTRING "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" 0 ${_length} MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES ${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} CACHE STRING "List of vector pixel types used in AccessByItk and InstantiateAccessFunction macros for itk::VectorImage types" FORCE) endif() if(NOT MITK_ACCESSBYITK_DIMENSIONS) set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") endif() #----------------------------------------------------------------------------- # Project.xml #----------------------------------------------------------------------------- # A list of topologically ordered targets set(CTEST_PROJECT_SUBPROJECTS) list(APPEND CTEST_PROJECT_SUBPROJECTS MITK-Core MITK-CoreUI MITK-IGT MITK-ToF MITK-DTI MITK-Modules # all modules not contained in a specific subproject MITK-Plugins # all plugins not contained in a specific subproject MITK-Examples Unlabeled # special "subproject" catching all unlabeled targets and tests ) # Configure CTestConfigSubProject.cmake that could be used by CTest scripts configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in ${MITK_BINARY_DIR}/CTestConfigSubProject.cmake) if(CTEST_PROJECT_ADDITIONAL_TARGETS) # those targets will be executed at the end of the ctest driver script # and they also get their own subproject label set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}") else() set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}") endif() # Generate Project.xml file expected by the CTest driver script mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD}) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(MITK_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") # Print configuration summary message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL) return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(WriteBasicConfigVersionFile) include(CheckCXXSourceCompiles) include(GenerateExportHeader) include(mitkFunctionAddCustomModuleTest) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCompileSnippets) include(mitkFunctionConfigureVisualStudioUserProjectFile) include(mitkFunctionConvertXPSchema) include(mitkFunctionCreateBlueBerryApplication) include(mitkFunctionCreateCommandLineApp) include(mitkFunctionCreateModule) include(mitkFunctionCreatePlugin) include(mitkFunctionCreateProvisioningFile) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionInstallCTKPlugin) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallThirdPartyCTKPlugins) include(mitkFunctionOrganizeSources) include(mitkFunctionTestPlugin) include(mitkFunctionUseModules) if( ${MITK_USE_MatchPoint} ) include(mitkFunctionCreateMatchPointDeployedAlgorithm) endif() include(mitkMacroConfigureItkPixelTypes) include(mitkMacroCreateExecutable) include(mitkMacroCreateModuleTests) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroMultiplexPicType) # Deprecated include(mitkMacroCreateCTKPlugin) #----------------------------------------------------------------------------- # Global CMake variables #----------------------------------------------------------------------------- # Required and enabled C++14 features for all MITK code. # These are added as PUBLIC compile features to all MITK modules. set(MITK_CXX_FEATURES cxx_auto_type cxx_decltype cxx_enum_forward_declarations cxx_extended_friend_declarations cxx_extern_templates cxx_final cxx_lambdas cxx_local_type_template_args cxx_long_long_type cxx_nullptr cxx_override cxx_range_for cxx_right_angle_brackets cxx_rvalue_references cxx_static_assert cxx_strong_enums cxx_template_template_parameters cxx_trailing_return_types cxx_variadic_macros ) if(NOT DEFINED CMAKE_DEBUG_POSTFIX) # We can't do this yet because the CTK Plugin Framework # cannot cope with a postfix yet. #set(CMAKE_DEBUG_POSTFIX d) endif() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- set(_default_LIBRARY_output_dir lib) set(_default_RUNTIME_output_dir bin) set(_default_ARCHIVE_output_dir lib) foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(MITK_CMAKE_${type}_OUTPUT_DIRECTORY AND NOT EXISTS ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) message("Creating directory MITK_CMAKE_${type}_OUTPUT_DIRECTORY: ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") file(MAKE_DIRECTORY "${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") endif() if(MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) else() set(CMAKE_${type}_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${_default_${type}_output_dir}) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY}) endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY} CACHE INTERNAL "Output directory for ${type} files.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # Look for optional Doxygen package find_package(Doxygen) option(BLUEBERRY_DEBUG_SMARTPOINTER "Enable code for debugging smart pointers" OFF) mark_as_advanced(BLUEBERRY_DEBUG_SMARTPOINTER) # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON) mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW) # TODO: check if necessary option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON) mark_as_advanced(USE_ITKZLIB) if(NOT MITK_FAST_TESTING) if(DEFINED MITK_CTEST_SCRIPT_MODE AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") ) set(MITK_FAST_TESTING 1) endif() endif() if(NOT UNIX AND NOT MINGW) set(MITK_WIN32_FORCE_STATIC "STATIC" CACHE INTERNAL "Use this variable to always build static libraries on non-unix platforms") endif() if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() # Configure pixel types used for ITK image access multiplexing mitkMacroConfigureItkPixelTypes() # Configure module naming conventions set(MITK_MODULE_NAME_REGEX_MATCH "^[A-Z].*$") set(MITK_MODULE_NAME_REGEX_NOT_MATCH "^[Mm][Ii][Tt][Kk].*$") set(MITK_DEFAULT_MODULE_NAME_PREFIX "Mitk") set(MITK_MODULE_NAME_PREFIX ${MITK_DEFAULT_MODULE_NAME_PREFIX}) set(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME 1) #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK) # MITK_VERSION set(MITK_VERSION_STRING "${MITK_VERSION_MAJOR}.${MITK_VERSION_MINOR}.${MITK_VERSION_PATCH}") if(MITK_VERSION_PATCH STREQUAL "99") set(MITK_VERSION_STRING "${MITK_VERSION_STRING}-${MITK_REVISION_SHORTID}") endif() #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on Mac OSX all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(MITK_USE_BLUEBERRY AND APPLE) include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) list(GET target_info_list 0 app_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} Mitk${app_name}) endif() endforeach() endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # MITK C/CXX Flags #----------------------------------------------------------------------------- set(MITK_C_FLAGS "${COVERAGE_C_FLAGS}") set(MITK_C_FLAGS_DEBUG ) set(MITK_C_FLAGS_RELEASE ) set(MITK_CXX_FLAGS "${COVERAGE_CXX_FLAGS} ${MITK_CXX14_FLAG}") set(MITK_CXX_FLAGS_DEBUG ) set(MITK_CXX_FLAGS_RELEASE ) set(MITK_EXE_LINKER_FLAGS ) set(MITK_SHARED_LINKER_FLAGS ) find_package(OpenMP) if (OPENMP_FOUND) set(MITK_C_FLAGS "${MITK_C_FLAGS} ${OpenMP_C_FLAGS}") set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif() if(WIN32) set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -D_WIN32_WINNT=0x0501 -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN -DNOMINMAX") mitkFunctionCheckCompilerFlags("/wd4005" MITK_CXX_FLAGS) # warning C4005: macro redefinition mitkFunctionCheckCompilerFlags("/wd4231" MITK_CXX_FLAGS) # warning C4231: nonstandard extension used : 'extern' before template explicit instantiation # the following line should be removed after fixing bug 17637 mitkFunctionCheckCompilerFlags("/wd4316" MITK_CXX_FLAGS) # warning C4316: object alignment on heap mitkFunctionCheckCompilerFlags("/wd4180" MITK_CXX_FLAGS) # warning C4180: qualifier applied to function type has no meaning endif() if(NOT MSVC_VERSION) foreach(_flag -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Wno-error=gnu -Wno-error=unknown-pragmas # The strict-overflow warning is generated by ITK template code -Wno-error=strict-overflow -Woverloaded-virtual -Wstrict-null-sentinel #-Wold-style-cast #-Wsign-promo -Wno-array-bounds -fdiagnostics-show-option ) mitkFunctionCheckCAndCXXCompilerFlags(${_flag} MITK_C_FLAGS MITK_CXX_FLAGS) endforeach() endif() if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" MITK_SHARED_LINKER_FLAGS) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" MITK_SHARED_LINKER_FLAGS) endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) if(MINGW) # suppress warnings about auto imported symbols set(MITK_SHARED_LINKER_FLAGS "-Wl,--enable-auto-import ${MITK_SHARED_LINKER_FLAGS}") endif() set(MITK_CXX_FLAGS_RELEASE "-U_FORTIFY_SOURCES -D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}") endif() set(MITK_MODULE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(MITK_EXE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_PACKAGE_DEPENDS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMake/PackageDepends) get_filename_component(MITK_PACKAGE_DEPENDS_EXTENSION_DIR ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR}) list(APPEND MODULES_PACKAGE_DEPENDS_DIRS ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR}) endif() endforeach() if(NOT MITK_USE_SYSTEM_Boost) set(Boost_NO_SYSTEM_PATHS 1) endif() set(Boost_USE_MULTITHREADED 1) set(Boost_USE_STATIC_LIBS 0) set(Boost_USE_STATIC_RUNTIME 0) set(Boost_ADDITIONAL_VERSIONS "1.65" "1.65.1") # We need this later for a DCMTK workaround set(_dcmtk_dir_orig ${DCMTK_DIR}) # This property is populated at the top half of this file get_property(MITK_EXTERNAL_PROJECTS GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(MITK_USE_${ep} AND _package) if(_components) find_package(${_package} COMPONENTS ${_components} REQUIRED CONFIG) else() # Prefer config mode first because it finds external # Config.cmake files pointed at by _DIR variables. # Otherwise, existing Find.cmake files could fail. find_package(${_package} QUIET CONFIG) string(TOUPPER "${_package}" _package_uc) if(NOT (${_package}_FOUND OR ${_package_uc}_FOUND)) find_package(${_package} REQUIRED) endif() endif() endif() endforeach() # Ensure that the MITK CMake module path comes first set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) if(MITK_USE_DCMTK) # Due to the preferred CONFIG mode in find_package calls above, # the DCMTKConfig.cmake file is read, which does not provide useful # package information. We explictly need MODULE mode to find DCMTK. if(${_dcmtk_dir_orig} MATCHES "${MITK_EXTERNAL_PROJECT_PREFIX}.*") # Help our FindDCMTK.cmake script find our super-build DCMTK set(DCMTK_DIR ${MITK_EXTERNAL_PROJECT_PREFIX}) else() # Use the original value set(DCMTK_DIR ${_dcmtk_dir_orig}) endif() find_package(DCMTK REQUIRED MODULE) endif() if(MITK_USE_DCMQI) # Due to the preferred CONFIG mode in find_package calls above, # the DCMQIConfig.cmake file is read, which does not provide useful # package information. We explictly need MODULE mode to find DCMQI. # Help our FindDCMQI.cmake script find our super-build DCMQI set(DCMQI_DIR ${MITK_EXTERNAL_PROJECT_PREFIX}) find_package(DCMQI REQUIRED) endif() if(MITK_USE_Python) find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) if(MITK_USE_Numpy) find_package(Numpy REQUIRED) endif() endif() link_directories(${Boost_LIBRARY_DIRS}) if(MITK_USE_OpenIGTLink) link_directories(${OpenIGTLink_LIBRARY_DIRS}) endif() if(MITK_USE_SimpleITK) link_directories(${SimpleITK_LIBRARY_DIRS}) endif() if(MITK_USE_OpenCL) find_package(OpenCL REQUIRED) endif() # Qt support if(MITK_USE_Qt5) find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED) # at least Core required get_target_property(_qmake_exec Qt5::qmake LOCATION) execute_process(COMMAND ${_qmake_exec} -query QT_INSTALL_BINS RESULT_VARIABLE _result OUTPUT_VARIABLE QT_BINARY_DIR ERROR_VARIABLE _error ) string(STRIP "${QT_BINARY_DIR}" QT_BINARY_DIR) if(_result OR NOT EXISTS "${QT_BINARY_DIR}") message(FATAL_ERROR "Could not determine Qt binary directory: ${_result} ${QT_BINARY_DIR} ${_error}") endif() find_program(QT_HELPGENERATOR_EXECUTABLE NAMES qhelpgenerator qhelpgenerator-qt5 qhelpgenerator5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_COLLECTIONGENERATOR_EXECUTABLE NAMES qcollectiongenerator qcollectiongenerator-qt5 qcollectiongenerator5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_ASSISTANT_EXECUTABLE NAMES assistant assistant-qt5 assistant5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_XMLPATTERNS_EXECUTABLE NAMES xmlpatterns PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) mark_as_advanced(QT_HELPGENERATOR_EXECUTABLE QT_COLLECTIONGENERATOR_EXECUTABLE QT_ASSISTANT_EXECUTABLE QT_XMLPATTERNS_EXECUTABLE ) if(MITK_USE_BLUEBERRY) option(BLUEBERRY_USE_QT_HELP "Enable support for integrating plugin documentation into Qt Help" ${DOXYGEN_FOUND}) mark_as_advanced(BLUEBERRY_USE_QT_HELP) # Sanity checks for in-application BlueBerry plug-in help generation if(BLUEBERRY_USE_QT_HELP) set(_force_blueberry_use_qt_help_to_off 0) if(NOT DOXYGEN_FOUND) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen was not found.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(DOXYGEN_FOUND AND DOXYGEN_VERSION VERSION_LESS 1.8.7) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen version 1.8.7 or newer not found.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT QT_HELPGENERATOR_EXECUTABLE) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because QT_HELPGENERATOR_EXECUTABLE is empty.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT MITK_USE_Qt5) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because MITK_USE_Qt5 is OFF.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT QT_XMLPATTERNS_EXECUTABLE) message("You have enabled Qt Help support, but QT_XMLPATTERNS_EXECUTABLE is empty") set(_force_blueberry_use_qt_help_to_off 1) endif() if(_force_blueberry_use_qt_help_to_off) set(BLUEBERRY_USE_QT_HELP OFF CACHE BOOL "Enable support for integrating plugin documentation into Qt Help" FORCE) endif() endif() if(BLUEBERRY_QT_HELP_REQUIRED AND NOT BLUEBERRY_USE_QT_HELP) message(FATAL_ERROR "BLUEBERRY_USE_QT_HELP is required to be set to ON") endif() endif() endif() #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_RENDERING_TESTING OFF "Enable the MITK rendering tests. Requires x-server in Linux.") #Rendering testing does not work for Linux nightlies, thus it is disabled per default #and activated for Mac and Windows. if(WIN32 OR APPLE) set(MITK_ENABLE_RENDERING_TESTING ON) endif() mark_as_advanced( MITK_ENABLE_RENDERING_TESTING ) # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Initial cache for ProjectTemplate and PluginGenerator tests configure_file( CMake/mitkTestInitialCache.txt.in ${MITK_BINARY_DIR}/mitkTestInitialCache.txt @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output") if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR}) file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR}) endif() # Test the external project template if(MITK_USE_BLUEBERRY) include(mitkTestProjectTemplate) endif() # Test the package target include(mitkPackageTest) endif() configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h) #----------------------------------------------------------------------------- # MITK_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild. # In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR) set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Set C/CXX and linker flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MITK_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MITK_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MITK_C_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MITK_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MITK_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MITK_MODULE_LINKER_FLAGS}") #----------------------------------------------------------------------------- # Add custom targets representing CDash subprojects #----------------------------------------------------------------------------- foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") add_custom_target(${subproject}) endif() endforeach() #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Utilities) add_subdirectory(Modules) include("${CMAKE_CURRENT_SOURCE_DIR}/Modules/ModuleList.cmake") mitkFunctionWhitelistModules(MITK MITK_MODULES) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_MODULES_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Modules) get_filename_component(MITK_MODULES_EXTENSION_DIR ${MITK_MODULES_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_MODULES_EXTENSION_DIR}/ModuleList.cmake) set(MITK_MODULES "") include(${MITK_MODULES_EXTENSION_DIR}/ModuleList.cmake) foreach(mitk_module ${MITK_MODULES}) add_subdirectory(${MITK_MODULES_EXTENSION_DIR}/${mitk_module} Modules/${mitk_module}) endforeach() endif() set(MITK_MODULE_NAME_PREFIX ${MITK_DEFAULT_MODULE_NAME_PREFIX}) endforeach() +add_subdirectory(Wrapping) + if(MITK_USE_BLUEBERRY) set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/) # Plug-in testing (needs some work to be enabled again) if(BUILD_TESTING) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp") if(TARGET CoreApp) get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE) if(APPLE AND _is_macosx_bundle) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp") endif() endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") mitkFunctionWhitelistPlugins(MITK MITK_PLUGINS) set(mitk_plugins_fullpath "") foreach(mitk_plugin ${MITK_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() set(MITK_PLUGIN_REGEX_LIST "") foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_PLUGINS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Plugins) get_filename_component(MITK_PLUGINS_EXTENSION_DIR ${MITK_PLUGINS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_PLUGINS_EXTENSION_DIR}/PluginList.cmake) set(MITK_PLUGINS "") include(${MITK_PLUGINS_EXTENSION_DIR}/PluginList.cmake) foreach(mitk_plugin ${MITK_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PLUGINS_EXTENSION_DIR}/${mitk_plugin}) endforeach() endif() endforeach() if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake) include(${MITK_PRIVATE_MODULES}/PluginList.cmake) foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin}) endforeach() endif() if(MITK_BUILD_EXAMPLES) include("${CMAKE_CURRENT_SOURCE_DIR}/Examples/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) list(APPEND mitk_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) endforeach() endif() # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$") set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb MITK_PLUGIN_REGEX_LIST OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") set(mitk_apps_fullpath ) foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 directory_name) list(GET target_info_list 1 option_name) if(${option_name}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${directory_name}^^${option_name}") endif() endforeach() if (mitk_plugins_fullpath) ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) endif() set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake") if(${PROJECT_NAME}_PLUGIN_LIBRARIES) ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE}) else() file(REMOVE ${MITK_PLUGIN_USE_FILE}) set(MITK_PLUGIN_USE_FILE ) endif() endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- if(DOXYGEN_FOUND) add_subdirectory(Documentation) endif() #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) # MITK_APPS is set in Applications/AppList.cmake (included somewhere above # if MITK_USE_BLUEBERRY is set to ON). if(MITK_APPS) set(activated_apps_no 0) list(LENGTH MITK_APPS app_count) # Check how many apps have been enabled # If more than one app has been activated, the we use the # default CPack configuration. Otherwise that apps configuration # will be used, if present. foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) MATH(EXPR activated_apps_no "${activated_apps_no} + 1") endif() endforeach() if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS)) # Corner case if there is only one app in total set(use_project_cpack ON) elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS) # Only one app is enabled (no "build all" flag set) set(use_project_cpack ON) else() # Less or more then one app is enabled set(use_project_cpack OFF) endif() foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) list(GET target_info_list 2 executable_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) # check whether application specific configuration files will be used if(use_project_cpack) # use files if they exist if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") endif() if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in") set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake") configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in ${CPACK_PROJECT_CONFIG_FILE} @ONLY) set(use_default_config OFF) endif() endif() # add link to the list list(APPEND CPACK_CREATE_DESKTOP_LINKS "${executable_name}") endif() endforeach() endif() # if no application specific configuration file was used, use default if(use_default_config) configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") endif() # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- # ---------------- Export targets ----------------- set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake") file(REMOVE ${MITK_EXPORTS_FILE}) set(targets_to_export) get_property(module_targets GLOBAL PROPERTY MITK_MODULE_TARGETS) if(module_targets) list(APPEND targets_to_export ${module_targets}) endif() if(MITK_USE_BLUEBERRY) if(MITK_PLUGIN_LIBRARIES) list(APPEND targets_to_export ${MITK_PLUGIN_LIBRARIES}) endif() endif() export(TARGETS ${targets_to_export} APPEND FILE ${MITK_EXPORTS_FILE}) set(MITK_EXPORTED_TARGET_PROPERTIES ) foreach(target_to_export ${targets_to_export}) get_target_property(autoload_targets ${target_to_export} MITK_AUTOLOAD_TARGETS) if(autoload_targets) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_TARGETS \"${autoload_targets}\")") endif() get_target_property(autoload_dir ${target_to_export} MITK_AUTOLOAD_DIRECTORY) if(autoload_dir) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_DIRECTORY \"${autoload_dir}\")") endif() get_target_property(deprecated_module ${target_to_export} MITK_MODULE_DEPRECATED_SINCE) if(deprecated_module) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_MODULE_DEPRECATED_SINCE \"${deprecated_module}\")") endif() endforeach() # ---------------- External projects ----------------- get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) set(MITK_CONFIG_EXTERNAL_PROJECTS ) #string(REPLACE "^^" ";" _mitk_external_projects ${MITK_EXTERNAL_PROJECTS}) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} set(MITK_USE_${ep} ${MITK_USE_${ep}}) set(MITK_${ep}_DIR \"${${ep}_DIR}\") set(MITK_${ep}_COMPONENTS ${_components}) ") endforeach() foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(_components) set(_components_arg COMPONENTS \${_components}) else() set(_components_arg) endif() if(_package) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} if(MITK_USE_${ep}) set(${ep}_DIR \${MITK_${ep}_DIR}) if(MITK_${ep}_COMPONENTS) mitkMacroFindDependency(${_package} COMPONENTS \${MITK_${ep}_COMPONENTS}) else() mitkMacroFindDependency(${_package}) endif() endif()") endif() endforeach() # ---------------- Tools ----------------- configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY) # ---------------- Configure files ----------------- configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${MITK_VERSION_STRING} COMPATIBILITY AnyNewerVersion) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) #----------------------------------------------------------------------------- # MITK Examples #----------------------------------------------------------------------------- if(MITK_BUILD_EXAMPLES) # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Examples) endif() #----------------------------------------------------------------------------- # Print configuration summary #----------------------------------------------------------------------------- message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL ) diff --git a/Modules/Classification/CLUtilities/include/mitkGIFCooccurenceMatrix2.h b/Modules/Classification/CLUtilities/include/mitkGIFCooccurenceMatrix2.h index ad019eb78d..f64972c487 100644 --- a/Modules/Classification/CLUtilities/include/mitkGIFCooccurenceMatrix2.h +++ b/Modules/Classification/CLUtilities/include/mitkGIFCooccurenceMatrix2.h @@ -1,250 +1,162 @@ #ifndef mitkGIFCooccurenceMatrix2_h #define mitkGIFCooccurenceMatrix2_h #include #include #include #include namespace mitk { - struct CoocurenceMatrixHolder - { - public: - CoocurenceMatrixHolder(double min, double max, int number); - - int IntensityToIndex(double intensity); - double IndexToMinIntensity(int index); - double IndexToMeanIntensity(int index); - double IndexToMaxIntensity(int index); - - double m_MinimumRange; - double m_MaximumRange; - double m_Stepsize; - int m_NumberOfBins; - Eigen::MatrixXd m_Matrix; - - }; - - struct CoocurenceMatrixFeatures - { - CoocurenceMatrixFeatures(): - JointMaximum(0), - JointAverage(0), - JointVariance(0), - JointEntropy(0), - RowMaximum(0), - RowAverage(0), - RowVariance(0), - RowEntropy(0), - FirstRowColumnEntropy(0), - SecondRowColumnEntropy(0), - DifferenceAverage(0), - DifferenceVariance(0), - DifferenceEntropy(0), - SumAverage(0), - SumVariance(0), - SumEntropy(0), - AngularSecondMoment(0), - Contrast(0), - Dissimilarity(0), - InverseDifference(0), - InverseDifferenceNormalised(0), - InverseDifferenceMoment(0), - InverseDifferenceMomentNormalised(0), - InverseVariance(0), - Correlation(0), - Autocorrelation(0), - ClusterTendency(0), - ClusterShade(0), - ClusterProminence(0), - FirstMeasureOfInformationCorrelation(0), - SecondMeasureOfInformationCorrelation(0) - { - } - - public: - double JointMaximum; - double JointAverage; - double JointVariance; - double JointEntropy; - double RowMaximum; - double RowAverage; - double RowVariance; - double RowEntropy; - double FirstRowColumnEntropy; - double SecondRowColumnEntropy; - double DifferenceAverage; - double DifferenceVariance; - double DifferenceEntropy; - double SumAverage; - double SumVariance; - double SumEntropy; - double AngularSecondMoment; - double Contrast; - double Dissimilarity; - double InverseDifference; - double InverseDifferenceNormalised; - double InverseDifferenceMoment; - double InverseDifferenceMomentNormalised; - double InverseVariance; - double Correlation; - double Autocorrelation; - double ClusterTendency; - double ClusterShade; - double ClusterProminence; - double FirstMeasureOfInformationCorrelation; - double SecondMeasureOfInformationCorrelation; - }; /** * \brief Calculates features based on the co-occurence matrix. * * The co-occurence matrix describes the relations between voxels in a specific direction. The elements \f$m_{i,k} \f$ of the * matrix count how often a voxel with the intensity \f$i \f$ has a neighbour in a certain direction with the intensity \f$ k \f$. * The direction for each matrix is given by a directed vector \f$ \overrightarrow{d} \f$. * * It is important to calculate the matrices for all possible directions in order to obtain a rotation invariant feature. * For the 3D case, this means that there are 26 possible directions. Using the symmetrical properties of the co-occurence * matrix, it is then possible to calculate the features in all directions looking at 13 different directions. * * The standard length of the vector is 1, e.g. looking at direct neighbours. It is possible to look at more * distance neighbours. This is achieved using the parameter range which defines the distance between * two neighbouring voxels in number of voxels. The default value for this is 1. It can be changes using the Method * SetRange() or by passing the option cooc2::range. * * There are two possible ways of combining the information obtained from the multiple directions. The first option * is to calculate a common matrix for all directions and then use this matrix to calculate the describing features. * The second method is to calculate a matrix for each direction, obtain the features and then report the mean and * standard value of these features. Both mehtods are calcuated by this filters and reported, distinguisehd by either * an "Overall" if a single matrix is used, a "Mean" for the mean Value, or an "Std.Dev." for the standard deviation. * * The connected areas are based on the binned image, the binning parameters can be set via the default * parameters as described in AbstractGlobalImageFeature. The intensity used for the calculation is * always equal to the bin number. It is also possible to determine the * dimensionality of the neighbourhood using direction-related commands as described in AbstractGlobalImageFeature. * No other options are possible beside these two options. * * This feature calculator is activated by the option -cooccurence2 or -cooc2. * * The features are calculated based on a mask. It is assumed that the mask is * of the type of an unsigned short image. All voxels with the value 1 are treated as masked. * * The following features are defined. We always give the notation for the overall matrix feature * although those for the mean and std.dev. are basically equal. In the name, is replace * by the distance of the neighbours. For the definitions of the feature, the probability of each * intensity pair (i,k) \f$ p_{i,k} = \frac{m_{i,k}}{\sum_i \sum_k m_{i,k}} \f$. * * In addition, the marginal sum \f$ p_{i,\cdot} = p_{\cdot,k=i} = \sum_k p_{i,k} \f$, which is * identical for both axis due to the symetrical nature of the matrix. Furthermore, the diagonal and * cross diagnoal features are used: * \f[ p_{i-k}(l) = \sum_i \sum_k p_{i,k} \delta(l - \| i -k \| ) \enspace \enspace l = 0, \dots, N_g -1 \f] * \f[ p_{i+k}(l) = \sum_i \sum_k p_{i,k} \delta(l - ( i + k ) ) \enspace \enspace l = 2, \dots, 2 N_g \f] * Here, \f$ \delta(x) \f$ is the dirac function, which is one for \f$x=0 \f$ and zero otherwise. * - Co-occurenced Based Features ()::Overall Joint Maximum: * \f[ \textup{Joint Maximum}= \textup{max}(p_{i,k}) \f] * - Co-occurenced Based Features ()::Overall Joint Average: * \f[ \textup{Joint Average} = \mu_{ja} = \sum_i \sum_k i p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Joint Variance: * \f[ \textup{Joint Variance} = \sum_i \sum_k (i - \mu_{ja})^2 p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Joint Entropy: * \f[ \textup{Joint Entropy} = e_j = - \sum_i \sum_k p_{i,k} \textup{log}_2 p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Row Maximum: * \f[ \textup{Row Maximum}= \textup{max}(p_{i,\cdot}) \f] * - Co-occurenced Based Features ()::Overall Row Average: * \f[ \textup{Row Average} = \mu_{ra} = \sum_i i p_{i,\cdot} \f] * - Co-occurenced Based Features ()::Overall Row Variance: * \f[ \textup{Row Variance} = \sigma^2_{i, \cdot} = \sum_i (i - \mu_{ra})^2 p_{i,\cdot} \f] * - Co-occurenced Based Features ()::Overall Row Entropy: * \f[ \textup{Row Entropy} = e_r = - \sum_i p_{i,\cdot} \textup{log}_2 p_{i,\cdot} \f] * - Co-occurenced Based Features ()::Overall First Row-Column Entropy: * \f[ \textup{First Row-Column Entropy} = e_1 = - \sum_i \sum_k p_{i,k} \textup{log}_2 ( p_{i,\cdot} p_{\cdot,k}) \f] * - Co-occurenced Based Features ()::Overall Second Row-Column Entropy: * \f[ \textup{Second Row-Column Entropy} = e_2 = - \sum_i \sum_k p_{i,\cdot} p_{\cdot,k} \textup{log}_2 ( p_{i,\cdot} p_{\cdot,k}) \f] * - Co-occurenced Based Features ()::Overall Difference Average: * \f[ \textup{Difference Average} = \mu_{da} = \sum_l l p_{i-k}(l) \f] * - Co-occurenced Based Features ()::Overall Difference Variance: * \f[ \textup{Difference Variance} = \sum_l (i - \mu_{da})^2 p_{i-k}(l) \f] * - Co-occurenced Based Features ()::Overall Difference Entropy: * \f[ \textup{Difference Entropy} = - \sum_l p_{i-k}(l) \textup{log}_2 p_{i-k}(l) \f] * - Co-occurenced Based Features ()::Overall Sum Average: * \f[ \textup{Sum Average} = \mu_{sa} = \sum_l l p_{i+k}(l) \f] * - Co-occurenced Based Features ()::Overall Sum Variance: * \f[ \textup{Sum Variance} = \sum_l (i - \mu_{sa})^2 p_{i+k}(l) \f] * - Co-occurenced Based Features ()::Overall Sum Entropy: * \f[ \textup{Sum Entropy} = - \sum_l p_{i+k}(l) \textup{log}_2 p_{i+k}(l) \f] * - Co-occurenced Based Features ()::Overall Angular Second Moment: * \f[ \textup{Angular Second Moment} = \sum_i \sum_k p^2_{i,k} \f] * - Co-occurenced Based Features ()::Overall Contrast: * \f[ \textup{Contrast} = \sum_i \sum_k (i-k)^2 p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Dissimilarity: * \f[ \textup{Dissimilarity} = \sum_i \sum_k \| i-k\| p^2_{i,k} \f] * - Co-occurenced Based Features ()::Overall Inverse Difference: * \f[ \textup{Inverse Difference} = \sum_i \sum_k \frac{p_{i,k}}{1+\| i-k\|} \f] * - Co-occurenced Based Features ()::Overall Inverse Difference Normalized: * \f[ \textup{Inverse Difference Normalized} = \sum_i \sum_k \frac{p_{i,k}}{1+\frac{\| i-k\|}{N_g}} \f] * - Co-occurenced Based Features ()::Overall Inverse Difference Moment: * \f[ \textup{Inverse Difference Moment} = \sum_i \sum_k \frac{p_{i,k}}{1+ ( i-k )^2} \f] * - Co-occurenced Based Features ()::Overall Inverse Difference Moment Normalized: * \f[ \textup{Inverse Difference Moment Normalized} = \sum_i \sum_k \frac{p_{i,k}}{1+\frac{( i-k ) ^2}{N_g}} \f] * - Co-occurenced Based Features ()::Overall Inverse Variance: * \f[ \textup{Inverse Difference Moment Normalized} = \sum_i \sum_k \frac{p_{i,k}}{(i-k)^2} \f] * - Co-occurenced Based Features ()::Overall Correlation: * \f[ \textup{Correlation} = \frac{1}{\sigma^2_{i,\cdot}} \sum_i \sum_k (i - \mu_{ra})(k - \mu_{ra}) p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Autocorrelation: * \f[ \textup{Autocorrelation} = \sum_i \sum_k i k p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Cluster Tendency: * \f[ \textup{Cluster Tendency} = \sum_i \sum_k (i + k - 2\mu_{ra})^2 p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Cluster Shade: * \f[ \textup{Cluster Shade} = \sum_i \sum_k (i + k - 2\mu_{ra})^3 p_{i,k} \f] * - Co-occurenced Based Features ()::Overall Cluster Prominence: * \f[ \textup{Cluster Prominence} = \sum_i \sum_k (i + k - 2\mu_{ra})^4 p_{i,k} \f] * - Co-occurenced Based Features ()::Overall First Measure of Information Correlation: * \f[ \textup{First Measure of Information Correlation} = \frac{ e_j- e_1}{e_r} \f] * - Co-occurenced Based Features ()::Overall Second Measure of Information Correlation: * \f[ \textup{Second Measure of Information Correlation} = \sqrt{1- \exp(-2 (e_2 - e_j)} \f] */ class MITKCLUTILITIES_EXPORT GIFCooccurenceMatrix2 : public AbstractGlobalImageFeature { public: mitkClassMacro(GIFCooccurenceMatrix2, AbstractGlobalImageFeature); itkFactorylessNewMacro(Self) itkCloneMacro(Self) GIFCooccurenceMatrix2(); /** * \brief Calculates the Cooccurence-Matrix based features for this class. */ virtual FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &feature) override; /** * \brief Returns a list of the names of all features that are calculated from this class */ virtual FeatureNameListType GetFeatureNames() override; virtual void CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList); virtual void AddArguments(mitkCommandLineParser &parser); virtual std::string GetCurrentFeatureEncoding() override; itkGetConstMacro(Range,double); itkSetMacro(Range, double); struct GIFCooccurenceMatrix2Configuration { double range; unsigned int direction; double MinimumIntensity; double MaximumIntensity; int Bins; std::string prefix; }; private: double m_Range; }; } #endif //mitkGIFCooccurenceMatrix2_h diff --git a/Modules/Classification/CLUtilities/include/mitkGIFGreyLevelSizeZone.h b/Modules/Classification/CLUtilities/include/mitkGIFGreyLevelSizeZone.h index 1072abe0ac..d42a9aa35a 100644 --- a/Modules/Classification/CLUtilities/include/mitkGIFGreyLevelSizeZone.h +++ b/Modules/Classification/CLUtilities/include/mitkGIFGreyLevelSizeZone.h @@ -1,180 +1,115 @@ #ifndef mitkGIFGreyLevelSizeZone_h #define mitkGIFGreyLevelSizeZone_h #include #include #include #include namespace mitk { - struct GreyLevelSizeZoneMatrixHolder - { - public: - GreyLevelSizeZoneMatrixHolder(double min, double max, int number, int maxSize); - - int IntensityToIndex(double intensity); - double IndexToMinIntensity(int index); - double IndexToMeanIntensity(int index); - double IndexToMaxIntensity(int index); - - double m_MinimumRange; - double m_MaximumRange; - double m_Stepsize; - int m_NumberOfBins; - int m_MaximumSize; - Eigen::MatrixXd m_Matrix; - - }; - - struct GreyLevelSizeZoneFeatures - { - GreyLevelSizeZoneFeatures() : - SmallZoneEmphasis(0), - LargeZoneEmphasis(0), - LowGreyLevelEmphasis(0), - HighGreyLevelEmphasis(0), - SmallZoneLowGreyLevelEmphasis(0), - SmallZoneHighGreyLevelEmphasis(0), - LargeZoneLowGreyLevelEmphasis(0), - LargeZoneHighGreyLevelEmphasis(0), - GreyLevelNonUniformity(0), - GreyLevelNonUniformityNormalized(0), - ZoneSizeNonUniformity(0), - ZoneSizeNoneUniformityNormalized(0), - ZonePercentage(0), - GreyLevelMean(0), - GreyLevelVariance(0), - ZoneSizeMean(0), - ZoneSizeVariance(0), - ZoneSizeEntropy(0) - { - } - - public: - double SmallZoneEmphasis; - double LargeZoneEmphasis; - double LowGreyLevelEmphasis; - double HighGreyLevelEmphasis; - double SmallZoneLowGreyLevelEmphasis; - double SmallZoneHighGreyLevelEmphasis; - double LargeZoneLowGreyLevelEmphasis; - double LargeZoneHighGreyLevelEmphasis; - double GreyLevelNonUniformity; - double GreyLevelNonUniformityNormalized; - double ZoneSizeNonUniformity; - double ZoneSizeNoneUniformityNormalized; - double ZonePercentage; - double GreyLevelMean; - double GreyLevelVariance; - double ZoneSizeMean; - double ZoneSizeVariance; - double ZoneSizeEntropy; - }; - - class MITKCLUTILITIES_EXPORT GIFGreyLevelSizeZone : public AbstractGlobalImageFeature { /** * \brief Calculates the Grey level size zone based features. * * Grey level size zone based features are similar to Grey Level Cooccurence features. But instead * of measuring the similarity within a given neighbourhood, the size of areas with the same intensity * is assessed. For this, a matrix is created that gives the number of areas \f$ m_{x,s} \f$ with the intensity \f$ x \f$ and * the size of \f$ s \f$. Each area is specified as connected voxels with the given intensity. * * The image is quantified prior to the calculation of the features. This reduces the number of * available intensity values. Instead of using the pure intensity value, the features are * calculated using the number of the bins as intensity value \f$ x_i \f$. The parameter of the * quantification of the image can be controlled using the general binning parameters as defined * in AbstractGlobalImageFeature. * * By default, the calculation is based on a 26 neighourhood for 3D and a 8 neighbourhood in 2D. It is further * possible to exclude directions from the calculation, e.g. calculating the feature in 2D, even if a * 3D image is passed. This is controlled by determine the * dimensionality of the neighbourhood using direction-related commands as described in AbstractGlobalImageFeature. * No other options are possible beside these two options. * * This feature calculator is activated by the option -grey-level-sizezone or -glsz. * * The features are calculated based on a mask. It is assumed that the mask is * of the type of an unsigned short image. All voxels with the value 1 are treated as masked. * * Several values are definied for the definition of the features. \f$ N_v \f$ is the number of masked voxels, * \f$N_s \f$ is the number of different zones, \f$ m_{x,\cdot} = \sum_s m{x,s} \f$ is the number of all areas * with a given intensity value, and likewise \f$ m_{\cdot, s} = \sum_x m{x,s} \f$ is the number of all areas * with a given size. The features are then defined as: * - Grey Level Size Zone::Small Zone Emphasis: * \f[ \textup{Small Zone Emphasis}= \frac{1}{N_s} \sum_s { \frac{m_{\cdot, s}}{s^2} } \f] * - Grey Level Size Zone::Large Zone Emphasis: * \f[ \textup{Large Zone Emphasis}= \frac{1}{N_s} \sum_s { m_{\cdot, s} s^2} \f] * - Grey Level Size Zone::Low Grey Level Zone Emphasis: * \f[ \textup{Low Grey Level Zone Emphasis}= \frac{1}{N_s} \sum_x { \frac{m_{x,\cdot}}{x^2} } \f] * - Grey Level Size Zone::High Grey Level Zone Emphasis: * \f[ \textup{High Grey Level Zone Emphasis}= \frac{1}{N_s} \sum_x { m_{x,\cdot} x^2} \f] * - Grey Level Size Zone::Small Zone Low Grey Level Emphasis: * \f[ \textup{Small Zone Low Grey Level Emphasis}= \frac{1}{N_s} \sum_x \sum_s { \frac{m_{x,s}}{x^2 s^2} } \f] * - Grey Level Size Zone::Small Zone High Grey Level Emphasis: * \f[ \textup{Small Zone High Grey Level Emphasis}= \frac{1}{N_s} \sum_x \sum_s { \frac{x^2 m_{x,s}}{s^2} } \f] * - Grey Level Size Zone::Large Zone Low Grey Level Emphasis: * \f[ \textup{Large Zone Low Grey Level Emphasis}= \frac{1}{N_s} \sum_x \sum_s { \frac{s^2 m_{x,s}}{x^2} } \f] * - Grey Level Size Zone::Large Zone High Grey Level Emphasis: * \f[ \textup{Large Zone High Grey Level Emphasis}= \frac{1}{N_s} \sum_x \sum_s { x^2 s^2 m_{x,s} } \f] * - Grey Level Size Zone::Grey Level Non-Uniformity: * \f[ \textup{Grey Level Non-Uniformity}= \frac{1}{N_s} \sum_x m_{x,\cdot}^2 \f] * - Grey Level Size Zone::Grey Level Non-Uniformity Normalized: * \f[ \textup{Grey Level Non-Uniformity Normalized}= \frac{1}{N_s^2} \sum_x m_{x,\cdot}^2 \f] * - Grey Level Size Zone::Zone Size Non-Uniformity: * \f[ \textup{Zone Size Non-Uniformity}= \frac{1}{N_s} \sum_s m_{\cdot, s}^2 \f] * - Grey Level Size Zone::Zone Size Non-Uniformity Normalized: * \f[ \textup{Zone Size Non-Uniformity Normalized}= \frac{1}{N_s^2} \sum_s m_{\cdot, s}^2 \f] * - Grey Level Size Zone::Zone Percentage: The ratio of realized areas to the theoretical limit of zones: * \f[ \textup{Zone Percentage}= \frac{N_s}{N_v} \f] * - Grey Level Size Zone::Grey Level Mean: * \f[ \textup{Grey Level Mean} = \mu_x = \frac{1}{N_s} \sum_x x m_{x, \cdot} \f] * - Grey Level Size Zone::Grey Level Variance: * \f[ \textup{Grey Level Variance} = \frac{1}{N_s} \sum_x (x -mu_x)^2 m_{x, \cdot} \f] * - Grey Level Size Zone::Zone Size Mean: * \f[ \textup{Zone Size Mean} = \mu_s = \frac{1}{N_s} \sum_s s m_{\cdot, s} \f] * - Grey Level Size Zone::Grey Level Variance: * \f[ \textup{Grey Level Variance} = \frac{1}{N_s} \sum_s (s -mu_s)^2 m_{\cdot, s} \f] * - Grey Level Size Zone::Zone Size Entropy: This feature would be equivalent with * the Grey Level Entropy, which is therefore not included. It is based on the likelihood * for a given intensity- size combination \f$ p_{x,s} = \frac{m_{x,s}}{N_s} \f$. : * \f[ \textup{Zone Size Entropy} = \sum_x \sum_s p_{x,s} \textup{log}_2 \left( p{_x,s} \right) \f] */ public: mitkClassMacro(GIFGreyLevelSizeZone, AbstractGlobalImageFeature); itkFactorylessNewMacro(Self) itkCloneMacro(Self) GIFGreyLevelSizeZone(); /** * \brief Calculates the Cooccurence-Matrix based features for this class. */ virtual FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &feature) override; /** * \brief Returns a list of the names of all features that are calculated from this class */ virtual FeatureNameListType GetFeatureNames() override; virtual void CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList); virtual void AddArguments(mitkCommandLineParser &parser); virtual std::string GetCurrentFeatureEncoding() override; struct GIFGreyLevelSizeZoneConfiguration { unsigned int direction; double MinimumIntensity; double MaximumIntensity; int Bins; std::string prefix; }; }; } #endif //mitkGIFGreyLevelSizeZone_h diff --git a/Modules/Classification/CLUtilities/include/mitkGIFNeighbourhoodGreyLevelDifference.h b/Modules/Classification/CLUtilities/include/mitkGIFNeighbourhoodGreyLevelDifference.h index 66cbc509a0..8913832535 100644 --- a/Modules/Classification/CLUtilities/include/mitkGIFNeighbourhoodGreyLevelDifference.h +++ b/Modules/Classification/CLUtilities/include/mitkGIFNeighbourhoodGreyLevelDifference.h @@ -1,51 +1,51 @@ #ifndef mitkGIFNeighbourhoodGreyLevelDifference_h #define mitkGIFNeighbourhoodGreyLevelDifference_h #include #include #include namespace mitk { class MITKCLUTILITIES_EXPORT GIFNeighbourhoodGreyLevelDifference : public AbstractGlobalImageFeature { public: mitkClassMacro(GIFNeighbourhoodGreyLevelDifference,AbstractGlobalImageFeature) itkFactorylessNewMacro(Self) itkCloneMacro(Self) GIFNeighbourhoodGreyLevelDifference(); /** * \brief Calculates the Cooccurence-Matrix based features for this class. */ FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &feature) override; /** * \brief Returns a list of the names of all features that are calculated from this class */ FeatureNameListType GetFeatureNames() override; itkGetConstMacro(Range,double); itkSetMacro(Range, double); itkGetConstMacro(UseCtRange, bool); itkSetMacro(UseCtRange, bool); - + virtual void CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList); virtual void AddArguments(mitkCommandLineParser &parser); struct ParameterStruct { bool m_UseCtRange; double m_Range; unsigned int m_Direction; }; private: double m_Range; bool m_UseCtRange; }; } #endif //mitkGIFNeighbourhoodGreyLevelDifference_h diff --git a/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h b/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h index d915514c8f..881d1677eb 100644 --- a/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h +++ b/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h @@ -1,237 +1,152 @@ #ifndef mitkGIFNeighbouringGreyLevelDependenceFeatures_h #define mitkGIFNeighbouringGreyLevelDependenceFeatures_h #include #include #include #include namespace mitk { - struct NGLDMMatrixHolder - { - public: - NGLDMMatrixHolder(double min, double max, int number, int depenence); - - int IntensityToIndex(double intensity); - double IndexToMinIntensity(int index); - double IndexToMeanIntensity(int index); - double IndexToMaxIntensity(int index); - - double m_MinimumRange; - double m_MaximumRange; - double m_Stepsize; - int m_NumberOfDependences; - int m_NumberOfBins; - Eigen::MatrixXd m_Matrix; - - int m_NeighbourhoodSize; - unsigned long m_NumberOfNeighbourVoxels; - unsigned long m_NumberOfDependenceNeighbourVoxels; - unsigned long m_NumberOfNeighbourhoods; - unsigned long m_NumberOfCompleteNeighbourhoods; - }; - - struct NGLDMMatrixFeatures - { - NGLDMMatrixFeatures() : - LowDependenceEmphasis(0), - HighDependenceEmphasis(0), - LowGreyLevelCountEmphasis(0), - HighGreyLevelCountEmphasis(0), - LowDependenceLowGreyLevelEmphasis(0), - LowDependenceHighGreyLevelEmphasis(0), - HighDependenceLowGreyLevelEmphasis(0), - HighDependenceHighGreyLevelEmphasis(0), - GreyLevelNonUniformity(0), - GreyLevelNonUniformityNormalised(0), - DependenceCountNonUniformity(0), - DependenceCountNonUniformityNormalised(0), - DependenceCountPercentage(0), - GreyLevelVariance(0), - DependenceCountVariance(0), - DependenceCountEntropy(0), - DependenceCountEnergy(0), - MeanGreyLevelCount(0), - MeanDependenceCount(0), - ExpectedNeighbourhoodSize(0), - AverageNeighbourhoodSize(0), - AverageIncompleteNeighbourhoodSize(0), - PercentageOfCompleteNeighbourhoods(0), - PercentageOfDependenceNeighbours(0) - { - } - - public: - double LowDependenceEmphasis; - double HighDependenceEmphasis; - double LowGreyLevelCountEmphasis; - double HighGreyLevelCountEmphasis; - double LowDependenceLowGreyLevelEmphasis; - double LowDependenceHighGreyLevelEmphasis; - double HighDependenceLowGreyLevelEmphasis; - double HighDependenceHighGreyLevelEmphasis; - - double GreyLevelNonUniformity; - double GreyLevelNonUniformityNormalised; - double DependenceCountNonUniformity; - double DependenceCountNonUniformityNormalised; - - double DependenceCountPercentage; - double GreyLevelVariance; - double DependenceCountVariance; - double DependenceCountEntropy; - double DependenceCountEnergy; - double MeanGreyLevelCount; - double MeanDependenceCount; - - double ExpectedNeighbourhoodSize; - double AverageNeighbourhoodSize; - double AverageIncompleteNeighbourhoodSize; - double PercentageOfCompleteNeighbourhoods; - double PercentageOfDependenceNeighbours; - - }; - /** * \brief Calculates the Neighbouring Grey Level Dependence Features * * The Neighbouring Grey Level Dependence Features were proposed by Sun and Wee (1983) and * capture the coarsness of the image texture. They are rotational invariant. * * The features are calculated on a matrix \f$ m \f$. To obtain the matrix, a neighbourhood * around each feature is calculated and the number of voxels within the neighbourhood that * are greater than the center voxel plus \f$ \alpha \f$ is counted. This is called the * number of dependence voxels. The matrix gives the * number of voxels with an intesity \f$ x \f$ and $\f d \f$ dependence neighbourhood voxels. * * The image is quantified prior to the calculation of the features. This reduces the number of * available intensity values. Instead of using the pure intensity value, the features are * calculated using the number of the bins as intensity value \f$ x_i \f$. The parameter of the * quantification of the image can be controlled using the general binning parameters as defined * in AbstractGlobalImageFeature. * * By default, the calculation is based on a 26 neighourhood for 3D and a 8 neighbourhood in 2D. It is further * possible to exclude directions from the calculation, e.g. calculating the feature in 2D, even if a * 3D image is passed. This is controlled by determine the * dimensionality of the neighbourhood using direction-related commands as described in AbstractGlobalImageFeature. * * In addition to this, the size of the neighbourhood can be controlled by setting the parameter * ngld::range. By default it is one. To pass more than one range, separate the ranges with * a semicolon. E.g. 1;2;3 would calculate the features for the ranges 1, 2, and 3. * * This feature calculator is activated by the option -neighbouring-grey-level-dependence * or -ngld. * * The features are calculated based on a mask. It is assumed that the mask is * a unsigned short image. All voxels with a value greater 0 are treated as masked. * * Several values are definied for the definition of the features. \f$ N_v \f$ is the number of masked voxels, * \f$N_s \f$ is the number of neighbourhoods, \f$ m_{x,\cdot} = \sum_d m{x,d} \f$ is the number of neighbourhoods * with a given intensity value, and likewise \f$ m_{\cdot, d} = \sum_x m{x,d} \f$ is the number of neighbourhoods * with a given number of dependence features: * - Neighbouring Grey Level Dependence::Low Dependence Emphasis: * \f[ \textup{Low dependence emphasis}= \frac{1}{N_s} \sum_d { \frac{m_{\cdot, d}}{d^2} } \f] * - Neighbouring Grey Level Dependence::High Dependence Emphasis: * \f[ \textup{High dependence emphasis}= \frac{1}{N_s} \sum_d { m_{\cdot, d} d^2} \f] * - Neighbouring Grey Level Dependence::Low Grey Level Count Emphasis: * \f[ \textup{Low grey level count emphasis}= \frac{1}{N_s} \sum_x { \frac{m_{x,\cdot}}{x^2} } \f] * - Neighbouring Grey Level Dependence::High Grey Level Count Emphasis: * \f[ \textup{High grey level count emphasis}= \frac{1}{N_s} \sum_x { m_{x,\cdot} x^2} \f] * - Neighbouring Grey Level Dependence::Low Dependence Low Grey Level Emphasis: * \f[ \textup{Low Dependence Low Grey Level Emphasis}= \frac{1}{N_s} \sum_x \sum_d { \frac{m_{x,d}}{x^2 d^2} } \f] * - Neighbouring Grey Level Dependence::Low Dependence High Grey Level Emphasis: * \f[ \textup{Low dependence high grey level emphasis}= \frac{1}{N_s} \sum_x \sum_d { \frac{x^2 m_{x,d}}{d^2} } \f] * - Neighbouring Grey Level Dependence::High Dependence Low Grey Level Emphasis: * \f[ \textup{High Dependence Low Grey Level Emphasis}= \frac{1}{N_s} \sum_x \sum_d { \frac{d^2 m_{x,d}}{x^2} } \f] * - Neighbouring Grey Level Dependence::High Dependence High Grey Level Emphasis: * \f[ \textup{High dependence high grey level emphasis}= \frac{1}{N_s} \sum_x \sum_d { x^2 d^2 m_{x,d} } \f] * - Neighbouring Grey Level Dependence::Grey level nonuniformity: * \f[ \textup{Grey level nonuniformity}= \frac{1}{N_s} \sum_x m_{x,\cdot}^2 \f] * - Neighbouring Grey Level Dependence::Grey level nonuniformity normalized: * \f[ \textup{Grey level nonuniformity normalized}= \frac{1}{N_s^2} \sum_x m_{x,\cdot}^2 \f] * - Neighbouring Grey Level Dependence::Dependence Count Nonuniformity: * \f[ \textup{Dependence count nonuniformity}= \frac{1}{N_s} \sum_d m_{\cdot, d}^2 \f] * - Neighbouring Grey Level Dependence::Dependence Count Nonuniformity Normalized: * \f[ \textup{Dependence count nonuniformity normalized}= \frac{1}{N_s^2} \sum_d m_{\cdot, d}^2 \f] * - Neighbouring Grey Level Dependence::DEpendence Count Percentage THe number of realized * neighbourhoods relativ to the theoretical maximum of realized neighbourhoods. This feature is always * one for this implementation as partial neighbourhoods are still considered. * - Neighbouring Grey Level Dependence::Grey Level Mean: The mean value of all grey level. * \f[ \textup{Grey Level Mean} = \mu_x = \frac{1}{N_s} \sum_x x m_{x,\cdot} \f] * - Neighbouring Grey Level Dependence::Grey Level Variance: * \f[ \textup{Grey level variance} = \frac{1}{N_s} \sum_x (x -mu_x)^2 m_{x, \cdot} \f] * - Neighbouring Grey Level Dependence::Dependence Count Mean: The mean value of all dependence counts. * \f[ \textup{Dependence count mean} = \mu_d = \frac{1}{N_s} \sum_d d m_{\cdot,d} \f] * - Neighbouring Grey Level Dependence::Dependence Count Variance: * \f[ \textup{Dependence count variance} = \frac{1}{N_s} \sum_d (d -mu_d)^2 m_{\cdot, d} \f] * - Neighbouring Grey Level Dependence::Dependence Count Entropy: This feature would be equivalent with * the Grey Level Entropy, which is therefore not included. It is based on the likelihood * for a given intensity- size combination \f$ p_{x,d} = \frac{m_{x,d}}{N_s} \f$. : * \f[ \textup{Dependence count entropy} = \sum_x \sum_d p_{x,d} \textup{log}_2 \left( p_{x,d} \right) \f] * - Neighbouring Grey Level Dependence::Dependence Count Energy: This feature would be equivalent with * the Grey Level Energy, which is therefore not included. It is based on the likelihood * for a given intensity- size combination \f$ p_{x,d} = \frac{m_{x,d}}{N_s} \f$. : * \f[ \textup{Dependence count energy} = \sum_x \sum_d p_{x,d}^2 \f] * - Neighbouring Grey Level Dependence::Expected Neighbourhood Size: The expected size of a * full neighbourhood. It depends on the dimension of the area that is looked at. * - Neighbouring Grey Level Dependence::Average Neighbourhood Size: The feature calculation * allows to consider partially masked neighbourhoods. Due to that, some neighbourhoods might be smaller. * This feature gives not the theoretical neighbourhood size but the average realized neighbourhood sizes. * - Neighbouring Grey Level Dependence::Average Incomplete Neighbourhood Size: Gives the average * size of all neighbourhoods that are not complete. * - Neighbouring Grey Level Dependence::Percentage of complete Neighbourhoods: Gives the percentage * of all complete neighbourhoods from all realized neighbourhoods. * - Neighbouring Grey Level Dependence::Percentage of Dependence Neighbour Voxels: Gives the * percentage of voxels in all neighbourhoods compared to the expected number of voxels. */ class MITKCLUTILITIES_EXPORT GIFNeighbouringGreyLevelDependenceFeature : public AbstractGlobalImageFeature { public: mitkClassMacro(GIFNeighbouringGreyLevelDependenceFeature, AbstractGlobalImageFeature) itkFactorylessNewMacro(Self) itkCloneMacro(Self) GIFNeighbouringGreyLevelDependenceFeature(); /** * \brief Calculates the Cooccurence-Matrix based features for this class. */ virtual FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &feature) override; /** * \brief Returns a list of the names of all features that are calculated from this class */ virtual FeatureNameListType GetFeatureNames() override; virtual std::string GetCurrentFeatureEncoding() override; itkGetConstMacro(Range,double); itkSetMacro(Range, double); itkGetConstMacro(Alpha, int); itkSetMacro(Alpha, int); virtual void CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList); virtual void AddArguments(mitkCommandLineParser &parser); struct GIFNeighbouringGreyLevelDependenceFeatureConfiguration { double range; unsigned int direction; int alpha; double MinimumIntensity; double MaximumIntensity; int Bins; std::string FeatureEncoding; }; private: double m_Range; int m_Alpha; }; } #endif //mitkGIFNeighbouringGreyLevelDependenceFeature_h diff --git a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFCooccurenceMatrix2.cpp b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFCooccurenceMatrix2.cpp index be973e20be..a50b98f65a 100644 --- a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFCooccurenceMatrix2.cpp +++ b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFCooccurenceMatrix2.cpp @@ -1,600 +1,693 @@ #include // MITK #include #include #include // ITK #include #include #include // STL #include #include +namespace mitk +{ + struct CoocurenceMatrixHolder + { + public: + CoocurenceMatrixHolder(double min, double max, int number); + + int IntensityToIndex(double intensity); + double IndexToMinIntensity(int index); + double IndexToMeanIntensity(int index); + double IndexToMaxIntensity(int index); + + double m_MinimumRange; + double m_MaximumRange; + double m_Stepsize; + int m_NumberOfBins; + Eigen::MatrixXd m_Matrix; + + }; + + struct CoocurenceMatrixFeatures + { + CoocurenceMatrixFeatures() : + JointMaximum(0), + JointAverage(0), + JointVariance(0), + JointEntropy(0), + RowMaximum(0), + RowAverage(0), + RowVariance(0), + RowEntropy(0), + FirstRowColumnEntropy(0), + SecondRowColumnEntropy(0), + DifferenceAverage(0), + DifferenceVariance(0), + DifferenceEntropy(0), + SumAverage(0), + SumVariance(0), + SumEntropy(0), + AngularSecondMoment(0), + Contrast(0), + Dissimilarity(0), + InverseDifference(0), + InverseDifferenceNormalised(0), + InverseDifferenceMoment(0), + InverseDifferenceMomentNormalised(0), + InverseVariance(0), + Correlation(0), + Autocorrelation(0), + ClusterTendency(0), + ClusterShade(0), + ClusterProminence(0), + FirstMeasureOfInformationCorrelation(0), + SecondMeasureOfInformationCorrelation(0) + { + } + + public: + double JointMaximum; + double JointAverage; + double JointVariance; + double JointEntropy; + double RowMaximum; + double RowAverage; + double RowVariance; + double RowEntropy; + double FirstRowColumnEntropy; + double SecondRowColumnEntropy; + double DifferenceAverage; + double DifferenceVariance; + double DifferenceEntropy; + double SumAverage; + double SumVariance; + double SumEntropy; + double AngularSecondMoment; + double Contrast; + double Dissimilarity; + double InverseDifference; + double InverseDifferenceNormalised; + double InverseDifferenceMoment; + double InverseDifferenceMomentNormalised; + double InverseVariance; + double Correlation; + double Autocorrelation; + double ClusterTendency; + double ClusterShade; + double ClusterProminence; + double FirstMeasureOfInformationCorrelation; + double SecondMeasureOfInformationCorrelation; + }; + +} + static void MatrixFeaturesTo(mitk::CoocurenceMatrixFeatures features, std::string prefix, mitk::GIFCooccurenceMatrix2::FeatureListType &featureList); static void CalculateMeanAndStdDevFeatures(std::vector featureList, mitk::CoocurenceMatrixFeatures &meanFeature, mitk::CoocurenceMatrixFeatures &stdFeature); static void NormalizeMatrixFeature(mitk::CoocurenceMatrixFeatures &features, std::size_t number); mitk::CoocurenceMatrixHolder::CoocurenceMatrixHolder(double min, double max, int number) : m_MinimumRange(min), m_MaximumRange(max), m_NumberOfBins(number) { m_Matrix.resize(number, number); m_Matrix.fill(0); m_Stepsize = (max - min) / (number); } int mitk::CoocurenceMatrixHolder::IntensityToIndex(double intensity) { int index = std::floor((intensity - m_MinimumRange) / m_Stepsize); return std::max(0, std::min(index, m_NumberOfBins - 1)); } double mitk::CoocurenceMatrixHolder::IndexToMinIntensity(int index) { return m_MinimumRange + index * m_Stepsize; } double mitk::CoocurenceMatrixHolder::IndexToMeanIntensity(int index) { return m_MinimumRange + (index+0.5) * m_Stepsize; } double mitk::CoocurenceMatrixHolder::IndexToMaxIntensity(int index) { return m_MinimumRange + (index + 1) * m_Stepsize; } template void CalculateCoOcMatrix(itk::Image* itkImage, itk::Image* mask, itk::Offset offset, int range, mitk::CoocurenceMatrixHolder &holder) { typedef itk::Image ImageType; typedef itk::Image MaskImageType; typedef itk::ShapedNeighborhoodIterator ShapeIterType; typedef itk::ShapedNeighborhoodIterator ShapeMaskIterType; typedef itk::ImageRegionConstIterator ConstIterType; typedef itk::ImageRegionConstIterator ConstMaskIterType; itk::Size radius; radius.Fill(range+1); ShapeIterType imageOffsetIter(radius, itkImage, itkImage->GetLargestPossibleRegion()); ShapeMaskIterType maskOffsetIter(radius, mask, mask->GetLargestPossibleRegion()); imageOffsetIter.ActivateOffset(offset); maskOffsetIter.ActivateOffset(offset); ConstIterType imageIter(itkImage, itkImage->GetLargestPossibleRegion()); ConstMaskIterType maskIter(mask, mask->GetLargestPossibleRegion()); // iterator.GetIndex() + ci.GetNeighborhoodOffset() auto region = mask->GetLargestPossibleRegion(); while (!maskIter.IsAtEnd()) { auto ciMask = maskOffsetIter.Begin(); auto ciValue = imageOffsetIter.Begin(); if (maskIter.Value() > 0 && ciMask.Get() > 0 && imageIter.Get() == imageIter.Get() && ciValue.Get() == ciValue.Get() && region.IsInside(maskOffsetIter.GetIndex() + ciMask.GetNeighborhoodOffset())) { int i = holder.IntensityToIndex(imageIter.Get()); int j = holder.IntensityToIndex(ciValue.Get()); holder.m_Matrix(i, j) += 1; holder.m_Matrix(j, i) += 1; } ++imageOffsetIter; ++maskOffsetIter; ++imageIter; ++maskIter; } } void CalculateFeatures( mitk::CoocurenceMatrixHolder &holder, mitk::CoocurenceMatrixFeatures & results ) { auto pijMatrix = holder.m_Matrix; auto piMatrix = holder.m_Matrix; auto pjMatrix = holder.m_Matrix; double Ng = holder.m_NumberOfBins; int NgSize = holder.m_NumberOfBins; pijMatrix /= pijMatrix.sum(); piMatrix.rowwise().normalize(); pjMatrix.colwise().normalize(); for (int i = 0; i < holder.m_NumberOfBins; ++i) for (int j = 0; j < holder.m_NumberOfBins; ++j) { if (pijMatrix(i, j) != pijMatrix(i, j)) pijMatrix(i, j) = 0; if (piMatrix(i, j) != piMatrix(i, j)) piMatrix(i, j) = 0; if (pjMatrix(i, j) != pjMatrix(i, j)) pjMatrix(i, j) = 0; } Eigen::VectorXd piVector = pijMatrix.colwise().sum(); Eigen::VectorXd pjVector = pijMatrix.rowwise().sum(); double sigmai = 0;; for (int i = 0; i < holder.m_NumberOfBins; ++i) { double iInt = i + 1;// holder.IndexToMeanIntensity(i); results.RowAverage += iInt * piVector(i); if (piVector(i) > 0) { results.RowEntropy -= piVector(i) * std::log(piVector(i)) / std::log(2); } } for (int i = 0; i < holder.m_NumberOfBins; ++i) { double iInt = i + 1; // holder.IndexToMeanIntensity(i); results.RowVariance += (iInt - results.RowAverage)*(iInt - results.RowAverage) * piVector(i); } results.RowMaximum = piVector.maxCoeff(); sigmai = std::sqrt(results.RowVariance); Eigen::VectorXd pimj(NgSize); pimj.fill(0); Eigen::VectorXd pipj(2*NgSize); pipj.fill(0); results.JointMaximum += pijMatrix.maxCoeff(); for (int i = 0; i < holder.m_NumberOfBins; ++i) { for (int j = 0; j < holder.m_NumberOfBins; ++j) { //double iInt = holder.IndexToMeanIntensity(i); //double jInt = holder.IndexToMeanIntensity(j); double iInt = i + 1;// holder.IndexToMeanIntensity(i); double jInt = j + 1;// holder.IndexToMeanIntensity(j); double pij = pijMatrix(i, j); int deltaK = (i - j)>0?(i-j) : (j-i); pimj(deltaK) += pij; pipj(i + j) += pij; results.JointAverage += iInt * pij; if (pij > 0) { results.JointEntropy -= pij * std::log(pij) / std::log(2); results.FirstRowColumnEntropy -= pij * std::log(piVector(i)*pjVector(j)) / std::log(2); } if (piVector(i) > 0 && pjVector(j) > 0 ) { results.SecondRowColumnEntropy -= piVector(i)*pjVector(j) * std::log(piVector(i)*pjVector(j)) / std::log(2); } results.AngularSecondMoment += pij*pij; results.Contrast += (iInt - jInt)* (iInt - jInt) * pij; results.Dissimilarity += std::abs(iInt - jInt) * pij; results.InverseDifference += pij / (1 + (std::abs(iInt - jInt))); results.InverseDifferenceNormalised += pij / (1 + (std::abs(iInt - jInt) / Ng)); results.InverseDifferenceMoment += pij / (1 + (iInt - jInt)*(iInt - jInt)); results.InverseDifferenceMomentNormalised += pij / (1 + (iInt - jInt)*(iInt - jInt)/Ng/Ng); results.Autocorrelation += iInt*jInt * pij; double cluster = (iInt + jInt - 2 * results.RowAverage); results.ClusterTendency += cluster*cluster * pij; results.ClusterShade += cluster*cluster*cluster * pij; results.ClusterProminence += cluster*cluster*cluster*cluster * pij; if (iInt != jInt) { results.InverseVariance += pij / (iInt - jInt) / (iInt - jInt); } } } results.Correlation = 1 / sigmai / sigmai * (-results.RowAverage*results.RowAverage+ results.Autocorrelation); results.FirstMeasureOfInformationCorrelation = (results.JointEntropy - results.FirstRowColumnEntropy) / results.RowEntropy; if (results.JointEntropy < results.SecondRowColumnEntropy) { results.SecondMeasureOfInformationCorrelation = sqrt(1 - exp(-2 * (results.SecondRowColumnEntropy - results.JointEntropy))); } else { results.SecondMeasureOfInformationCorrelation = 0; } for (int i = 0; i < holder.m_NumberOfBins; ++i) { for (int j = 0; j < holder.m_NumberOfBins; ++j) { //double iInt = holder.IndexToMeanIntensity(i); //double jInt = holder.IndexToMeanIntensity(j); double iInt = i + 1; double pij = pijMatrix(i, j); results.JointVariance += (iInt - results.JointAverage)* (iInt - results.JointAverage)*pij; } } for (int k = 0; k < NgSize; ++k) { results.DifferenceAverage += k* pimj(k); if (pimj(k) > 0) { results.DifferenceEntropy -= pimj(k) * log(pimj(k)) / std::log(2); } } for (int k = 0; k < NgSize; ++k) { results.DifferenceVariance += (results.DifferenceAverage-k)* (results.DifferenceAverage-k)*pimj(k); } for (int k = 0; k <2* NgSize ; ++k) { results.SumAverage += (2+k)* pipj(k); if (pipj(k) > 0) { results.SumEntropy -= pipj(k) * log(pipj(k)) / std::log(2); } } for (int k = 0; k < 2*NgSize; ++k) { results.SumVariance += (2+k - results.SumAverage)* (2+k - results.SumAverage)*pipj(k); } //MITK_INFO << std::endl << holder.m_Matrix; //MITK_INFO << std::endl << pijMatrix; //MITK_INFO << std::endl << piMatrix; //MITK_INFO << std::endl << pjMatrix; //for (int i = 0; i < holder.m_NumberOfBins; ++i) //{ // MITK_INFO << "Bin " << i << " Min: " << holder.IndexToMinIntensity(i) << " Max: " << holder.IndexToMaxIntensity(i); //} //MITK_INFO << pimj; //MITK_INFO << pipj; } template void CalculateCoocurenceFeatures(itk::Image* itkImage, mitk::Image::Pointer mask, mitk::GIFCooccurenceMatrix2::FeatureListType & featureList, mitk::GIFCooccurenceMatrix2::GIFCooccurenceMatrix2Configuration config) { typedef itk::Image MaskType; typedef itk::Neighborhood NeighborhoodType; typedef itk::Offset OffsetType; /////////////////////////////////////////////////////////////////////////////////////////////// double rangeMin = config.MinimumIntensity; double rangeMax = config.MaximumIntensity; int numberOfBins = config.Bins; typename MaskType::Pointer maskImage = MaskType::New(); mitk::CastToItkImage(mask, maskImage); //Find possible directions std::vector < itk::Offset > offsetVector; NeighborhoodType hood; hood.SetRadius(1); unsigned int centerIndex = hood.GetCenterNeighborhoodIndex(); OffsetType offset; for (unsigned int d = 0; d < centerIndex; d++) { offset = hood.GetOffset(d); bool useOffset = true; for (unsigned int i = 0; i < VImageDimension; ++i) { offset[i] *= config.range; if (config.direction == i + 2 && offset[i] != 0) { useOffset = false; } } if (useOffset) { offsetVector.push_back(offset); } } if (config.direction == 1) { offsetVector.clear(); offset[0] = 0; offset[1] = 0; offset[2] = 1; } std::vector resultVector; mitk::CoocurenceMatrixHolder holderOverall(rangeMin, rangeMax, numberOfBins); mitk::CoocurenceMatrixFeatures overallFeature; for (std::size_t i = 0; i < offsetVector.size(); ++i) { if (config.direction > 1) { if (offsetVector[i][config.direction - 2] != 0) { continue; } } offset = offsetVector[i]; mitk::CoocurenceMatrixHolder holder(rangeMin, rangeMax, numberOfBins); mitk::CoocurenceMatrixFeatures coocResults; CalculateCoOcMatrix(itkImage, maskImage, offset, config.range, holder); holderOverall.m_Matrix += holder.m_Matrix; CalculateFeatures(holder, coocResults); resultVector.push_back(coocResults); } CalculateFeatures(holderOverall, overallFeature); //NormalizeMatrixFeature(overallFeature, offsetVector.size()); mitk::CoocurenceMatrixFeatures featureMean; mitk::CoocurenceMatrixFeatures featureStd; CalculateMeanAndStdDevFeatures(resultVector, featureMean, featureStd); std::ostringstream ss; ss << config.range; std::string strRange = ss.str(); MatrixFeaturesTo(overallFeature, config.prefix + " Overall", featureList); MatrixFeaturesTo(featureMean, config.prefix + " Mean", featureList); MatrixFeaturesTo(featureStd, config.prefix + " Std.Dev.", featureList); } static void MatrixFeaturesTo(mitk::CoocurenceMatrixFeatures features, std::string prefix, mitk::GIFCooccurenceMatrix2::FeatureListType &featureList) { featureList.push_back(std::make_pair(prefix + "Joint Maximum", features.JointMaximum)); featureList.push_back(std::make_pair(prefix + "Joint Average", features.JointAverage)); featureList.push_back(std::make_pair(prefix + "Joint Variance", features.JointVariance)); featureList.push_back(std::make_pair(prefix + "Joint Entropy", features.JointEntropy)); featureList.push_back(std::make_pair(prefix + "Row Maximum", features.RowMaximum)); featureList.push_back(std::make_pair(prefix + "Row Average", features.RowAverage)); featureList.push_back(std::make_pair(prefix + "Row Variance", features.RowVariance)); featureList.push_back(std::make_pair(prefix + "Row Entropy", features.RowEntropy)); featureList.push_back(std::make_pair(prefix + "First Row-Column Entropy", features.FirstRowColumnEntropy)); featureList.push_back(std::make_pair(prefix + "Second Row-Column Entropy", features.SecondRowColumnEntropy)); featureList.push_back(std::make_pair(prefix + "Difference Average", features.DifferenceAverage)); featureList.push_back(std::make_pair(prefix + "Difference Variance", features.DifferenceVariance)); featureList.push_back(std::make_pair(prefix + "Difference Entropy", features.DifferenceEntropy)); featureList.push_back(std::make_pair(prefix + "Sum Average", features.SumAverage)); featureList.push_back(std::make_pair(prefix + "Sum Variance", features.SumVariance)); featureList.push_back(std::make_pair(prefix + "Sum Entropy", features.SumEntropy)); featureList.push_back(std::make_pair(prefix + "Angular Second Moment", features.AngularSecondMoment)); featureList.push_back(std::make_pair(prefix + "Contrast", features.Contrast)); featureList.push_back(std::make_pair(prefix + "Dissimilarity", features.Dissimilarity)); featureList.push_back(std::make_pair(prefix + "Inverse Difference", features.InverseDifference)); featureList.push_back(std::make_pair(prefix + "Inverse Difference Normalized", features.InverseDifferenceNormalised)); featureList.push_back(std::make_pair(prefix + "Inverse Difference Moment", features.InverseDifferenceMoment)); featureList.push_back(std::make_pair(prefix + "Inverse Difference Moment Normalized", features.InverseDifferenceMomentNormalised)); featureList.push_back(std::make_pair(prefix + " Inverse Variance", features.InverseVariance)); featureList.push_back(std::make_pair(prefix + "Correlation", features.Correlation)); featureList.push_back(std::make_pair(prefix + "Autocorrleation", features.Autocorrelation)); featureList.push_back(std::make_pair(prefix + "Cluster Tendency", features.ClusterTendency)); featureList.push_back(std::make_pair(prefix + "Cluster Shade", features.ClusterShade)); featureList.push_back(std::make_pair(prefix + "Cluster Prominence", features.ClusterProminence)); featureList.push_back(std::make_pair(prefix + "First Measure of Information Correlation", features.FirstMeasureOfInformationCorrelation)); featureList.push_back(std::make_pair(prefix + "Second Measure of Information Correlation", features.SecondMeasureOfInformationCorrelation)); } static void CalculateMeanAndStdDevFeatures(std::vector featureList, mitk::CoocurenceMatrixFeatures &meanFeature, mitk::CoocurenceMatrixFeatures &stdFeature) { #define ADDFEATURE(a) meanFeature.a += featureList[i].a;stdFeature.a += featureList[i].a*featureList[i].a #define CALCVARIANCE(a) stdFeature.a =sqrt(stdFeature.a - meanFeature.a*meanFeature.a) for (std::size_t i = 0; i < featureList.size(); ++i) { ADDFEATURE(JointMaximum); ADDFEATURE(JointAverage); ADDFEATURE(JointVariance); ADDFEATURE(JointEntropy); ADDFEATURE(RowMaximum); ADDFEATURE(RowAverage); ADDFEATURE(RowVariance); ADDFEATURE(RowEntropy); ADDFEATURE(FirstRowColumnEntropy); ADDFEATURE(SecondRowColumnEntropy); ADDFEATURE(DifferenceAverage); ADDFEATURE(DifferenceVariance); ADDFEATURE(DifferenceEntropy); ADDFEATURE(SumAverage); ADDFEATURE(SumVariance); ADDFEATURE(SumEntropy); ADDFEATURE(AngularSecondMoment); ADDFEATURE(Contrast); ADDFEATURE(Dissimilarity); ADDFEATURE(InverseDifference); ADDFEATURE(InverseDifferenceNormalised); ADDFEATURE(InverseDifferenceMoment); ADDFEATURE(InverseDifferenceMomentNormalised); ADDFEATURE(InverseVariance); ADDFEATURE(Correlation); ADDFEATURE(Autocorrelation); ADDFEATURE(ClusterShade); ADDFEATURE(ClusterTendency); ADDFEATURE(ClusterProminence); ADDFEATURE(FirstMeasureOfInformationCorrelation); ADDFEATURE(SecondMeasureOfInformationCorrelation); } NormalizeMatrixFeature(meanFeature, featureList.size()); NormalizeMatrixFeature(stdFeature, featureList.size()); CALCVARIANCE(JointMaximum); CALCVARIANCE(JointAverage); CALCVARIANCE(JointVariance); CALCVARIANCE(JointEntropy); CALCVARIANCE(RowMaximum); CALCVARIANCE(RowAverage); CALCVARIANCE(RowVariance); CALCVARIANCE(RowEntropy); CALCVARIANCE(FirstRowColumnEntropy); CALCVARIANCE(SecondRowColumnEntropy); CALCVARIANCE(DifferenceAverage); CALCVARIANCE(DifferenceVariance); CALCVARIANCE(DifferenceEntropy); CALCVARIANCE(SumAverage); CALCVARIANCE(SumVariance); CALCVARIANCE(SumEntropy); CALCVARIANCE(AngularSecondMoment); CALCVARIANCE(Contrast); CALCVARIANCE(Dissimilarity); CALCVARIANCE(InverseDifference); CALCVARIANCE(InverseDifferenceNormalised); CALCVARIANCE(InverseDifferenceMoment); CALCVARIANCE(InverseDifferenceMomentNormalised); CALCVARIANCE(InverseVariance); CALCVARIANCE(Correlation); CALCVARIANCE(Autocorrelation); CALCVARIANCE(ClusterShade); CALCVARIANCE(ClusterTendency); CALCVARIANCE(ClusterProminence); CALCVARIANCE(FirstMeasureOfInformationCorrelation); CALCVARIANCE(SecondMeasureOfInformationCorrelation); #undef ADDFEATURE #undef CALCVARIANCE } static void NormalizeMatrixFeature(mitk::CoocurenceMatrixFeatures &features, std::size_t number) { features.JointMaximum = features.JointMaximum / number; features.JointAverage = features.JointAverage / number; features.JointVariance = features.JointVariance / number; features.JointEntropy = features.JointEntropy / number; features.RowMaximum = features.RowMaximum / number; features.RowAverage = features.RowAverage / number; features.RowVariance = features.RowVariance / number; features.RowEntropy = features.RowEntropy / number; features.FirstRowColumnEntropy = features.FirstRowColumnEntropy / number; features.SecondRowColumnEntropy = features.SecondRowColumnEntropy / number; features.DifferenceAverage = features.DifferenceAverage / number; features.DifferenceVariance = features.DifferenceVariance / number; features.DifferenceEntropy = features.DifferenceEntropy / number; features.SumAverage = features.SumAverage / number; features.SumVariance = features.SumVariance / number; features.SumEntropy = features.SumEntropy / number; features.AngularSecondMoment = features.AngularSecondMoment / number; features.Contrast = features.Contrast / number; features.Dissimilarity = features.Dissimilarity / number; features.InverseDifference = features.InverseDifference / number; features.InverseDifferenceNormalised = features.InverseDifferenceNormalised / number; features.InverseDifferenceMoment = features.InverseDifferenceMoment / number; features.InverseDifferenceMomentNormalised = features.InverseDifferenceMomentNormalised / number; features.InverseVariance = features.InverseVariance / number; features.Correlation = features.Correlation / number; features.Autocorrelation = features.Autocorrelation / number; features.ClusterShade = features.ClusterShade / number; features.ClusterTendency = features.ClusterTendency / number; features.ClusterProminence = features.ClusterProminence / number; features.FirstMeasureOfInformationCorrelation = features.FirstMeasureOfInformationCorrelation / number; features.SecondMeasureOfInformationCorrelation = features.SecondMeasureOfInformationCorrelation / number; } mitk::GIFCooccurenceMatrix2::GIFCooccurenceMatrix2(): m_Range(1.0) { SetShortName("cooc2"); SetLongName("cooccurence2"); SetFeatureClassName("Co-occurenced Based Features"); } mitk::GIFCooccurenceMatrix2::FeatureListType mitk::GIFCooccurenceMatrix2::CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) { InitializeQuantifier(image, mask); FeatureListType featureList; GIFCooccurenceMatrix2Configuration config; config.direction = GetDirection(); config.range = m_Range; config.MinimumIntensity = GetQuantifier()->GetMinimum(); config.MaximumIntensity = GetQuantifier()->GetMaximum(); config.Bins = GetQuantifier()->GetBins(); config.prefix = FeatureDescriptionPrefix(); AccessByItk_3(image, CalculateCoocurenceFeatures, mask, featureList,config); return featureList; } mitk::GIFCooccurenceMatrix2::FeatureNameListType mitk::GIFCooccurenceMatrix2::GetFeatureNames() { FeatureNameListType featureList; return featureList; } void mitk::GIFCooccurenceMatrix2::AddArguments(mitkCommandLineParser &parser) { std::string name = GetOptionPrefix(); parser.addArgument(GetLongName(), name, mitkCommandLineParser::Bool, "Use Co-occurence matrix", "calculates Co-occurence based features (new implementation)", us::Any()); parser.addArgument(name+"::range", name+"::range", mitkCommandLineParser::String, "Cooc 2 Range", "Define the range that is used (Semicolon-separated)", us::Any()); AddQuantifierArguments(parser); } void mitk::GIFCooccurenceMatrix2::CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &, const Image::Pointer &maskNoNAN, FeatureListType &featureList) { auto parsedArgs = GetParameter(); std::string name = GetOptionPrefix(); if (parsedArgs.count(GetLongName())) { InitializeQuantifierFromParameters(feature, maskNoNAN); std::vector ranges; if (parsedArgs.count(name + "::range")) { ranges = SplitDouble(parsedArgs[name + "::range"].ToString(), ';'); } else { ranges.push_back(1); } for (std::size_t i = 0; i < ranges.size(); ++i) { MITK_INFO << "Start calculating coocurence with range " << ranges[i] << "...."; this->SetRange(ranges[i]); auto localResults = this->CalculateFeatures(feature, maskNoNAN); featureList.insert(featureList.end(), localResults.begin(), localResults.end()); MITK_INFO << "Finished calculating coocurence with range " << ranges[i] << "...."; } } } std::string mitk::GIFCooccurenceMatrix2::GetCurrentFeatureEncoding() { std::ostringstream ss; ss << m_Range; std::string strRange = ss.str(); return QuantifierParameterString() + "_Range-" + ss.str(); } diff --git a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp index 2453c82166..0229979792 100644 --- a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp +++ b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp @@ -1,371 +1,438 @@ #include // MITK #include #include #include // ITK #include // STL +namespace mitk +{ + struct GreyLevelSizeZoneMatrixHolder + { + public: + GreyLevelSizeZoneMatrixHolder(double min, double max, int number, int maxSize); + + int IntensityToIndex(double intensity); + double IndexToMinIntensity(int index); + double IndexToMeanIntensity(int index); + double IndexToMaxIntensity(int index); + + double m_MinimumRange; + double m_MaximumRange; + double m_Stepsize; + int m_NumberOfBins; + int m_MaximumSize; + Eigen::MatrixXd m_Matrix; + + }; + + struct GreyLevelSizeZoneFeatures + { + GreyLevelSizeZoneFeatures() : + SmallZoneEmphasis(0), + LargeZoneEmphasis(0), + LowGreyLevelEmphasis(0), + HighGreyLevelEmphasis(0), + SmallZoneLowGreyLevelEmphasis(0), + SmallZoneHighGreyLevelEmphasis(0), + LargeZoneLowGreyLevelEmphasis(0), + LargeZoneHighGreyLevelEmphasis(0), + GreyLevelNonUniformity(0), + GreyLevelNonUniformityNormalized(0), + ZoneSizeNonUniformity(0), + ZoneSizeNoneUniformityNormalized(0), + ZonePercentage(0), + GreyLevelMean(0), + GreyLevelVariance(0), + ZoneSizeMean(0), + ZoneSizeVariance(0), + ZoneSizeEntropy(0) + { + } + + public: + double SmallZoneEmphasis; + double LargeZoneEmphasis; + double LowGreyLevelEmphasis; + double HighGreyLevelEmphasis; + double SmallZoneLowGreyLevelEmphasis; + double SmallZoneHighGreyLevelEmphasis; + double LargeZoneLowGreyLevelEmphasis; + double LargeZoneHighGreyLevelEmphasis; + double GreyLevelNonUniformity; + double GreyLevelNonUniformityNormalized; + double ZoneSizeNonUniformity; + double ZoneSizeNoneUniformityNormalized; + double ZonePercentage; + double GreyLevelMean; + double GreyLevelVariance; + double ZoneSizeMean; + double ZoneSizeVariance; + double ZoneSizeEntropy; + }; +} + static void MatrixFeaturesTo(mitk::GreyLevelSizeZoneFeatures features, std::string prefix, mitk::GIFGreyLevelSizeZone::FeatureListType &featureList); mitk::GreyLevelSizeZoneMatrixHolder::GreyLevelSizeZoneMatrixHolder(double min, double max, int number, int maxSize) : m_MinimumRange(min), m_MaximumRange(max), m_NumberOfBins(number), m_MaximumSize(maxSize) { m_Matrix.resize(number, maxSize); m_Matrix.fill(0); m_Stepsize = (max - min) / (number); } int mitk::GreyLevelSizeZoneMatrixHolder::IntensityToIndex(double intensity) { return std::floor((intensity - m_MinimumRange) / m_Stepsize); } double mitk::GreyLevelSizeZoneMatrixHolder::IndexToMinIntensity(int index) { return m_MinimumRange + index * m_Stepsize; } double mitk::GreyLevelSizeZoneMatrixHolder::IndexToMeanIntensity(int index) { return m_MinimumRange + (index+0.5) * m_Stepsize; } double mitk::GreyLevelSizeZoneMatrixHolder::IndexToMaxIntensity(int index) { return m_MinimumRange + (index + 1) * m_Stepsize; } template static int CalculateGlSZMatrix(itk::Image* itkImage, itk::Image* mask, std::vector > offsets, bool estimateLargestRegion, mitk::GreyLevelSizeZoneMatrixHolder &holder) { typedef itk::Image ImageType; typedef itk::Image MaskImageType; typedef typename ImageType::IndexType IndexType; typedef itk::ImageRegionIteratorWithIndex ConstIterType; typedef itk::ImageRegionIteratorWithIndex ConstMaskIterType; auto region = mask->GetLargestPossibleRegion(); typename MaskImageType::RegionType newRegion; newRegion.SetSize(region.GetSize()); newRegion.SetIndex(region.GetIndex()); ConstIterType imageIter(itkImage, itkImage->GetLargestPossibleRegion()); ConstMaskIterType maskIter(mask, mask->GetLargestPossibleRegion()); typename MaskImageType::Pointer visitedImage = MaskImageType::New(); visitedImage->SetRegions(newRegion); visitedImage->Allocate(); visitedImage->FillBuffer(0); int largestRegion = 0; while (!maskIter.IsAtEnd()) { if (maskIter.Value() > 0 ) { auto startIntensityIndex = holder.IntensityToIndex(imageIter.Value()); std::vector indices; indices.push_back(maskIter.GetIndex()); unsigned int steps = 0; while (indices.size() > 0) { auto currentIndex = indices.back(); indices.pop_back(); if (!region.IsInside(currentIndex)) { continue; } auto wasVisited = visitedImage->GetPixel(currentIndex); auto newIntensityIndex = holder.IntensityToIndex(itkImage->GetPixel(currentIndex)); auto isInMask = mask->GetPixel(currentIndex); if ((isInMask > 0) && (newIntensityIndex == startIntensityIndex) && (wasVisited < 1)) { ++steps; visitedImage->SetPixel(currentIndex, 1); for (auto offset : offsets) { auto newIndex = currentIndex + offset; indices.push_back(newIndex); newIndex = currentIndex - offset; indices.push_back(newIndex); } } } if (steps > 0) { largestRegion = std::max(steps, largestRegion); steps = std::min(steps, holder.m_MaximumSize); if (!estimateLargestRegion) { holder.m_Matrix(startIntensityIndex, steps - 1) += 1; } } } ++imageIter; ++maskIter; } return largestRegion; } static void CalculateFeatures( mitk::GreyLevelSizeZoneMatrixHolder &holder, mitk::GreyLevelSizeZoneFeatures & results ) { auto SgzMatrix = holder.m_Matrix; auto pgzMatrix = holder.m_Matrix; auto pgMatrix = holder.m_Matrix; auto pzMatrix = holder.m_Matrix; double Ns = pgzMatrix.sum(); pgzMatrix /= Ns; pgMatrix.rowwise().normalize(); pzMatrix.colwise().normalize(); for (int i = 0; i < holder.m_NumberOfBins; ++i) for (int j = 0; j < holder.m_NumberOfBins; ++j) { if (pgzMatrix(i, j) != pgzMatrix(i, j)) pgzMatrix(i, j) = 0; if (pgMatrix(i, j) != pgMatrix(i, j)) pgMatrix(i, j) = 0; if (pzMatrix(i, j) != pzMatrix(i, j)) pzMatrix(i, j) = 0; } Eigen::VectorXd SgVector = SgzMatrix.rowwise().sum(); Eigen::VectorXd SzVector = SgzMatrix.colwise().sum(); for (int j = 0; j < SzVector.size(); ++j) { results.SmallZoneEmphasis += SzVector(j) / (j + 1) / (j + 1); results.LargeZoneEmphasis += SzVector(j) * (j + 1.0) * (j + 1.0); results.ZoneSizeNonUniformity += SzVector(j) * SzVector(j); results.ZoneSizeNoneUniformityNormalized += SzVector(j) * SzVector(j); } for (int i = 0; i < SgVector.size(); ++i) { results.LowGreyLevelEmphasis += SgVector(i) / (i + 1) / (i + 1); results.HighGreyLevelEmphasis += SgVector(i) * (i + 1) * (i + 1); results.GreyLevelNonUniformity += SgVector(i)*SgVector(i); results.GreyLevelNonUniformityNormalized += SgVector(i)*SgVector(i); } for (int i = 0; i < SgzMatrix.rows(); ++i) { for (int j = 0; j < SgzMatrix.cols(); ++j) { results.SmallZoneLowGreyLevelEmphasis += SgzMatrix(i, j) / (i + 1) / (i + 1) / (j + 1) / (j + 1); results.SmallZoneHighGreyLevelEmphasis += SgzMatrix(i, j) * (i + 1) * (i + 1) / (j + 1) / (j + 1); results.LargeZoneLowGreyLevelEmphasis += SgzMatrix(i, j) / (i + 1) / (i + 1) * (j + 1.0) * (j + 1.0); results.LargeZoneHighGreyLevelEmphasis += SgzMatrix(i, j) * (i + 1) * (i + 1) * (j + 1.0) * (j + 1.0); results.ZonePercentage += SgzMatrix(i, j)*(j + 1); results.GreyLevelMean += (i + 1)*pgzMatrix(i, j); results.ZoneSizeMean += (j + 1)*pgzMatrix(i, j); if (pgzMatrix(i, j) > 0) results.ZoneSizeEntropy -= pgzMatrix(i, j) * std::log(pgzMatrix(i, j)) / std::log(2); } } for (int i = 0; i < SgzMatrix.rows(); ++i) { for (int j = 0; j < SgzMatrix.cols(); ++j) { results.GreyLevelVariance += (i + 1 - results.GreyLevelMean)*(i + 1 - results.GreyLevelMean)*pgzMatrix(i, j); results.ZoneSizeVariance += (j + 1 - results.ZoneSizeMean)*(j + 1 - results.ZoneSizeMean)*pgzMatrix(i, j); } } results.SmallZoneEmphasis /= Ns; results.LargeZoneEmphasis /= Ns; results.LowGreyLevelEmphasis /= Ns; results.HighGreyLevelEmphasis /= Ns; results.SmallZoneLowGreyLevelEmphasis /= Ns; results.SmallZoneHighGreyLevelEmphasis /= Ns; results.LargeZoneLowGreyLevelEmphasis /= Ns; results.LargeZoneHighGreyLevelEmphasis /= Ns; results.GreyLevelNonUniformity /= Ns; results.GreyLevelNonUniformityNormalized /= Ns*Ns; results.ZoneSizeNonUniformity /= Ns; results.ZoneSizeNoneUniformityNormalized /= Ns*Ns; results.ZonePercentage = Ns / results.ZonePercentage; } template static void CalculateGreyLevelSizeZoneFeatures(itk::Image* itkImage, mitk::Image::Pointer mask, mitk::GIFGreyLevelSizeZone::FeatureListType & featureList, mitk::GIFGreyLevelSizeZone::GIFGreyLevelSizeZoneConfiguration config) { typedef itk::Image MaskType; typedef itk::Neighborhood NeighborhoodType; typedef itk::Offset OffsetType; /////////////////////////////////////////////////////////////////////////////////////////////// double rangeMin = config.MinimumIntensity; double rangeMax = config.MaximumIntensity; int numberOfBins = config.Bins; typename MaskType::Pointer maskImage = MaskType::New(); mitk::CastToItkImage(mask, maskImage); //Find possible directions std::vector < itk::Offset > offsetVector; NeighborhoodType hood; hood.SetRadius(1); unsigned int centerIndex = hood.GetCenterNeighborhoodIndex(); OffsetType offset; for (unsigned int d = 0; d < centerIndex; d++) { offset = hood.GetOffset(d); bool useOffset = true; for (unsigned int i = 0; i < VImageDimension; ++i) { if ((config.direction == i + 2) && offset[i] != 0) { useOffset = false; } } if (useOffset) { offsetVector.push_back(offset); MITK_INFO << offset; } } if (config.direction == 1) { offsetVector.clear(); offset[0] = 0; offset[1] = 0; offset[2] = 1; offsetVector.push_back(offset); } std::vector resultVector; mitk::GreyLevelSizeZoneMatrixHolder tmpHolder(rangeMin, rangeMax, numberOfBins, 3); int largestRegion = CalculateGlSZMatrix(itkImage, maskImage, offsetVector, true, tmpHolder); mitk::GreyLevelSizeZoneMatrixHolder holderOverall(rangeMin, rangeMax, numberOfBins,largestRegion); mitk::GreyLevelSizeZoneFeatures overallFeature; CalculateGlSZMatrix(itkImage, maskImage, offsetVector, false, holderOverall); CalculateFeatures(holderOverall, overallFeature); MatrixFeaturesTo(overallFeature, config.prefix, featureList); } static void MatrixFeaturesTo(mitk::GreyLevelSizeZoneFeatures features, std::string prefix, mitk::GIFGreyLevelSizeZone::FeatureListType &featureList) { featureList.push_back(std::make_pair(prefix + "Small Zone Emphasis", features.SmallZoneEmphasis)); featureList.push_back(std::make_pair(prefix + "Large Zone Emphasis", features.LargeZoneEmphasis)); featureList.push_back(std::make_pair(prefix + "Low Grey Level Emphasis", features.LowGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "High Grey Level Emphasis", features.HighGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "Small Zone Low Grey Level Emphasis", features.SmallZoneLowGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "Small Zone High Grey Level Emphasis", features.SmallZoneHighGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "Large Zone Low Grey Level Emphasis", features.LargeZoneLowGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "Large Zone High Grey Level Emphasis", features.LargeZoneHighGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "Grey Level Non-Uniformity", features.GreyLevelNonUniformity)); featureList.push_back(std::make_pair(prefix + "Grey Level Non-Uniformity Normalized", features.GreyLevelNonUniformityNormalized)); featureList.push_back(std::make_pair(prefix + "Zone Size Non-Uniformity", features.ZoneSizeNonUniformity)); featureList.push_back(std::make_pair(prefix + "Zone Size Non-Uniformity Normalized", features.ZoneSizeNoneUniformityNormalized)); featureList.push_back(std::make_pair(prefix + "Zone Percentage", features.ZonePercentage)); featureList.push_back(std::make_pair(prefix + "Grey Level Mean", features.GreyLevelMean)); featureList.push_back(std::make_pair(prefix + "Grey Level Variance", features.GreyLevelVariance)); featureList.push_back(std::make_pair(prefix + "Zone Size Mean", features.ZoneSizeMean)); featureList.push_back(std::make_pair(prefix + "Zone Size Variance", features.ZoneSizeVariance)); featureList.push_back(std::make_pair(prefix + "Zone Size Entropy", features.ZoneSizeEntropy)); } mitk::GIFGreyLevelSizeZone::GIFGreyLevelSizeZone() { SetShortName("glsz"); SetLongName("grey-level-sizezone"); SetFeatureClassName("Grey Level Size Zone"); } mitk::GIFGreyLevelSizeZone::FeatureListType mitk::GIFGreyLevelSizeZone::CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) { InitializeQuantifier(image, mask); FeatureListType featureList; GIFGreyLevelSizeZoneConfiguration config; config.direction = GetDirection(); config.MinimumIntensity = GetQuantifier()->GetMinimum(); config.MaximumIntensity = GetQuantifier()->GetMaximum(); config.Bins = GetQuantifier()->GetBins(); config.prefix = FeatureDescriptionPrefix(); AccessByItk_3(image, CalculateGreyLevelSizeZoneFeatures, mask, featureList, config); return featureList; } mitk::GIFGreyLevelSizeZone::FeatureNameListType mitk::GIFGreyLevelSizeZone::GetFeatureNames() { FeatureNameListType featureList; return featureList; } void mitk::GIFGreyLevelSizeZone::AddArguments(mitkCommandLineParser &parser) { std::string name = GetOptionPrefix(); parser.addArgument(GetLongName(), name, mitkCommandLineParser::Bool, "Use Grey Level Size Zone", "Calculates the size zone based features.", us::Any()); AddQuantifierArguments(parser); } void mitk::GIFGreyLevelSizeZone::CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &, const Image::Pointer &maskNoNAN, FeatureListType &featureList) { auto parsedArgs = GetParameter(); std::string name = GetOptionPrefix(); if (parsedArgs.count(GetLongName())) { InitializeQuantifierFromParameters(feature, maskNoNAN); MITK_INFO << "Start calculating Grey leve size zone ..."; auto localResults = this->CalculateFeatures(feature, maskNoNAN); featureList.insert(featureList.end(), localResults.begin(), localResults.end()); MITK_INFO << "Finished calculating Grey level size zone ..."; } } std::string mitk::GIFGreyLevelSizeZone::GetCurrentFeatureEncoding() { return QuantifierParameterString(); } diff --git a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp index 3bce70d519..a606c15c04 100644 --- a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp +++ b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp @@ -1,398 +1,486 @@ #include // MITK #include #include #include // ITK #include #include #include #include // STL #include +namespace mitk +{ + struct NGLDMMatrixHolder + { + public: + NGLDMMatrixHolder(double min, double max, int number, int depenence); + + int IntensityToIndex(double intensity); + double IndexToMinIntensity(int index); + double IndexToMeanIntensity(int index); + double IndexToMaxIntensity(int index); + + double m_MinimumRange; + double m_MaximumRange; + double m_Stepsize; + int m_NumberOfDependences; + int m_NumberOfBins; + Eigen::MatrixXd m_Matrix; + + int m_NeighbourhoodSize; + unsigned long m_NumberOfNeighbourVoxels; + unsigned long m_NumberOfDependenceNeighbourVoxels; + unsigned long m_NumberOfNeighbourhoods; + unsigned long m_NumberOfCompleteNeighbourhoods; + }; + + struct NGLDMMatrixFeatures + { + NGLDMMatrixFeatures() : + LowDependenceEmphasis(0), + HighDependenceEmphasis(0), + LowGreyLevelCountEmphasis(0), + HighGreyLevelCountEmphasis(0), + LowDependenceLowGreyLevelEmphasis(0), + LowDependenceHighGreyLevelEmphasis(0), + HighDependenceLowGreyLevelEmphasis(0), + HighDependenceHighGreyLevelEmphasis(0), + GreyLevelNonUniformity(0), + GreyLevelNonUniformityNormalised(0), + DependenceCountNonUniformity(0), + DependenceCountNonUniformityNormalised(0), + DependenceCountPercentage(0), + GreyLevelVariance(0), + DependenceCountVariance(0), + DependenceCountEntropy(0), + DependenceCountEnergy(0), + MeanGreyLevelCount(0), + MeanDependenceCount(0), + ExpectedNeighbourhoodSize(0), + AverageNeighbourhoodSize(0), + AverageIncompleteNeighbourhoodSize(0), + PercentageOfCompleteNeighbourhoods(0), + PercentageOfDependenceNeighbours(0) + { + } + + public: + double LowDependenceEmphasis; + double HighDependenceEmphasis; + double LowGreyLevelCountEmphasis; + double HighGreyLevelCountEmphasis; + double LowDependenceLowGreyLevelEmphasis; + double LowDependenceHighGreyLevelEmphasis; + double HighDependenceLowGreyLevelEmphasis; + double HighDependenceHighGreyLevelEmphasis; + + double GreyLevelNonUniformity; + double GreyLevelNonUniformityNormalised; + double DependenceCountNonUniformity; + double DependenceCountNonUniformityNormalised; + + double DependenceCountPercentage; + double GreyLevelVariance; + double DependenceCountVariance; + double DependenceCountEntropy; + double DependenceCountEnergy; + double MeanGreyLevelCount; + double MeanDependenceCount; + + double ExpectedNeighbourhoodSize; + double AverageNeighbourhoodSize; + double AverageIncompleteNeighbourhoodSize; + double PercentageOfCompleteNeighbourhoods; + double PercentageOfDependenceNeighbours; + + }; +} + static void MatrixFeaturesTo(mitk::NGLDMMatrixFeatures features, std::string prefix, mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType &featureList); mitk::NGLDMMatrixHolder::NGLDMMatrixHolder(double min, double max, int number, int depenence) : m_MinimumRange(min), m_MaximumRange(max), m_Stepsize(0), m_NumberOfDependences(depenence), m_NumberOfBins(number), m_NeighbourhoodSize(1), m_NumberOfNeighbourVoxels(0), m_NumberOfDependenceNeighbourVoxels(0), m_NumberOfNeighbourhoods(0), m_NumberOfCompleteNeighbourhoods(0) { m_Matrix.resize(number, depenence); m_Matrix.fill(0); m_Stepsize = (max - min) / (number); } int mitk::NGLDMMatrixHolder::IntensityToIndex(double intensity) { return std::floor((intensity - m_MinimumRange) / m_Stepsize); } double mitk::NGLDMMatrixHolder::IndexToMinIntensity(int index) { return m_MinimumRange + index * m_Stepsize; } double mitk::NGLDMMatrixHolder::IndexToMeanIntensity(int index) { return m_MinimumRange + (index+0.5) * m_Stepsize; } double mitk::NGLDMMatrixHolder::IndexToMaxIntensity(int index) { return m_MinimumRange + (index + 1) * m_Stepsize; } template void CalculateNGLDMMatrix(itk::Image* itkImage, itk::Image* mask, int alpha, int range, unsigned int direction, mitk::NGLDMMatrixHolder &holder) { typedef itk::Image ImageType; typedef itk::Image MaskImageType; typedef itk::NeighborhoodIterator ShapeIterType; typedef itk::NeighborhoodIterator ShapeMaskIterType; holder.m_NumberOfCompleteNeighbourhoods = 0; holder.m_NumberOfNeighbourhoods = 0; holder.m_NumberOfNeighbourVoxels = 0; holder.m_NumberOfDependenceNeighbourVoxels = 0; itk::Size radius; radius.Fill(range); if ((direction > 1) && (direction - 2 GetLargestPossibleRegion()); ShapeMaskIterType maskIter(radius, mask, mask->GetLargestPossibleRegion()); auto region = mask->GetLargestPossibleRegion(); auto center = imageIter.Size() / 2; auto iterSize = imageIter.Size(); holder.m_NeighbourhoodSize = iterSize-1; while (!maskIter.IsAtEnd()) { int sameValues = 0; bool completeNeighbourhood = true; int i = holder.IntensityToIndex(imageIter.GetCenterPixel()); if ((imageIter.GetCenterPixel() != imageIter.GetCenterPixel()) || (maskIter.GetCenterPixel() < 1)) { ++imageIter; ++maskIter; continue; } for (unsigned int position = 0; position < iterSize; ++position) { if (position == center) { continue; } if ( ! region.IsInside(maskIter.GetIndex(position))) { completeNeighbourhood = false; continue; } bool isInBounds; auto jIntensity = imageIter.GetPixel(position, isInBounds); auto jMask = maskIter.GetPixel(position, isInBounds); if (jMask < 1 || (jIntensity != jIntensity) || ( ! isInBounds)) { completeNeighbourhood = false; continue; } int j = holder.IntensityToIndex(jIntensity); holder.m_NumberOfNeighbourVoxels += 1; if (std::abs(i - j) <= alpha) { holder.m_NumberOfDependenceNeighbourVoxels += 1; ++sameValues; } } holder.m_Matrix(i, sameValues) += 1; holder.m_NumberOfNeighbourhoods += 1; if (completeNeighbourhood) { holder.m_NumberOfCompleteNeighbourhoods += 1; } ++imageIter; ++maskIter; } } void LocalCalculateFeatures( mitk::NGLDMMatrixHolder &holder, mitk::NGLDMMatrixFeatures & results ) { auto sijMatrix = holder.m_Matrix; auto piMatrix = holder.m_Matrix; auto pjMatrix = holder.m_Matrix; // double Ng = holder.m_NumberOfBins; // int NgSize = holder.m_NumberOfBins; double Ns = sijMatrix.sum(); piMatrix.rowwise().normalize(); pjMatrix.colwise().normalize(); for (int i = 0; i < holder.m_NumberOfBins; ++i) { double sj = 0; for (int j = 0; j < holder.m_NumberOfDependences; ++j) { double iInt = i+1 ;// holder.IndexToMeanIntensity(i); double sij = sijMatrix(i, j); double k = j + 1; double pij = sij / Ns; results.LowDependenceEmphasis += sij / k / k; results.HighDependenceEmphasis += sij * k*k; if (iInt != 0) { results.LowGreyLevelCountEmphasis += sij / iInt / iInt; } results.HighGreyLevelCountEmphasis += sij * iInt*iInt; if (iInt != 0) { results.LowDependenceLowGreyLevelEmphasis += sij / k / k / iInt / iInt; } results.LowDependenceHighGreyLevelEmphasis += sij * iInt*iInt / k / k; if (iInt != 0) { results.HighDependenceLowGreyLevelEmphasis += sij *k * k / iInt / iInt; } results.HighDependenceHighGreyLevelEmphasis += sij * k*k*iInt*iInt; results.MeanGreyLevelCount += iInt * pij; results.MeanDependenceCount += k * pij; if (pij > 0) { results.DependenceCountEntropy -= pij * std::log(pij) / std::log(2); } results.DependenceCountEnergy += pij*pij; sj += sij; } results.GreyLevelNonUniformity += sj*sj; results.GreyLevelNonUniformityNormalised += sj*sj; } for (int j = 0; j < holder.m_NumberOfDependences; ++j) { double si = 0; for (int i = 0; i < holder.m_NumberOfBins; ++i) { double sij = sijMatrix(i, j); si += sij; } results.DependenceCountNonUniformity += si*si; results.DependenceCountNonUniformityNormalised += si*si; } for (int i = 0; i < holder.m_NumberOfBins; ++i) { for (int j = 0; j < holder.m_NumberOfDependences; ++j) { double iInt = i + 1;// holder.IndexToMeanIntensity(i); double sij = sijMatrix(i, j); double k = j + 1; double pij = sij / Ns; results.GreyLevelVariance += (iInt - results.MeanGreyLevelCount)* (iInt - results.MeanGreyLevelCount) * pij; results.DependenceCountVariance += (k - results.MeanDependenceCount)* (k - results.MeanDependenceCount) * pij; } } results.LowDependenceEmphasis /= Ns; results.HighDependenceEmphasis /= Ns; results.LowGreyLevelCountEmphasis /= Ns; results.HighGreyLevelCountEmphasis /= Ns; results.LowDependenceLowGreyLevelEmphasis /= Ns; results.LowDependenceHighGreyLevelEmphasis /= Ns; results.HighDependenceLowGreyLevelEmphasis /= Ns; results.HighDependenceHighGreyLevelEmphasis /= Ns; results.GreyLevelNonUniformity /= Ns; results.GreyLevelNonUniformityNormalised /= (Ns*Ns); results.DependenceCountNonUniformity /= Ns; results.DependenceCountNonUniformityNormalised /= (Ns*Ns); results.DependenceCountPercentage = 1; results.ExpectedNeighbourhoodSize = holder.m_NeighbourhoodSize; results.AverageNeighbourhoodSize = holder.m_NumberOfNeighbourVoxels / (1.0 * holder.m_NumberOfNeighbourhoods); results.AverageIncompleteNeighbourhoodSize = (holder.m_NumberOfNeighbourVoxels - holder.m_NumberOfCompleteNeighbourhoods* holder.m_NeighbourhoodSize) / (1.0 * (holder.m_NumberOfNeighbourhoods - holder.m_NumberOfCompleteNeighbourhoods)); results.PercentageOfCompleteNeighbourhoods = (1.0*holder.m_NumberOfCompleteNeighbourhoods) / (1.0 * holder.m_NumberOfNeighbourhoods); results.PercentageOfDependenceNeighbours = holder.m_NumberOfDependenceNeighbourVoxels / (1.0 * holder.m_NumberOfNeighbourVoxels); } template void CalculateCoocurenceFeatures(itk::Image* itkImage, mitk::Image::Pointer mask, mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType & featureList, mitk::GIFNeighbouringGreyLevelDependenceFeature::GIFNeighbouringGreyLevelDependenceFeatureConfiguration config) { typedef itk::Image MaskType; double rangeMin = config.MinimumIntensity; double rangeMax = config.MaximumIntensity; int numberOfBins = config.Bins; typename MaskType::Pointer maskImage = MaskType::New(); mitk::CastToItkImage(mask, maskImage); std::vector resultVector; int numberofDependency = 37; if (VImageDimension == 2) numberofDependency = 37; mitk::NGLDMMatrixHolder holderOverall(rangeMin, rangeMax, numberOfBins, numberofDependency); mitk::NGLDMMatrixFeatures overallFeature; CalculateNGLDMMatrix(itkImage, maskImage, config.alpha, config.range, config.direction, holderOverall); LocalCalculateFeatures(holderOverall, overallFeature); MatrixFeaturesTo(overallFeature, config.FeatureEncoding, featureList); } static void MatrixFeaturesTo(mitk::NGLDMMatrixFeatures features, std::string prefix, mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType &featureList) { featureList.push_back(std::make_pair(prefix + "Low Dependence Emphasis", features.LowDependenceEmphasis)); featureList.push_back(std::make_pair(prefix + "High Dependence Emphasis", features.HighDependenceEmphasis)); featureList.push_back(std::make_pair(prefix + "Low Grey Level Count Emphasis", features.LowGreyLevelCountEmphasis)); featureList.push_back(std::make_pair(prefix + "High Grey Level Count Emphasis", features.HighGreyLevelCountEmphasis)); featureList.push_back(std::make_pair(prefix + "Low Dependence Low Grey Level Emphasis", features.LowDependenceLowGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "Low Dependence High Grey Level Emphasis", features.LowDependenceHighGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "High Dependence Low Grey Level Emphasis", features.HighDependenceLowGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "High Dependence High Grey Level Emphasis", features.HighDependenceHighGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + "Grey Level Non-Uniformity", features.GreyLevelNonUniformity)); featureList.push_back(std::make_pair(prefix + "Grey Level Non-Uniformity Normalised", features.GreyLevelNonUniformityNormalised)); featureList.push_back(std::make_pair(prefix + "Dependence Count Non-Uniformity", features.DependenceCountNonUniformity)); featureList.push_back(std::make_pair(prefix + "Dependence Count Non-Uniformity Normalised", features.DependenceCountNonUniformityNormalised)); featureList.push_back(std::make_pair(prefix + "Dependence Count Percentage", features.DependenceCountPercentage)); featureList.push_back(std::make_pair(prefix + "Grey Level Mean", features.MeanGreyLevelCount)); featureList.push_back(std::make_pair(prefix + "Grey Level Variance", features.GreyLevelVariance)); featureList.push_back(std::make_pair(prefix + "Dependence Count Mean", features.MeanDependenceCount)); featureList.push_back(std::make_pair(prefix + "Dependence Count Variance", features.DependenceCountVariance)); featureList.push_back(std::make_pair(prefix + "Dependence Count Entropy", features.DependenceCountEntropy)); featureList.push_back(std::make_pair(prefix + "Dependence Count Energy", features.DependenceCountEnergy)); featureList.push_back(std::make_pair(prefix + "Expected Neighbourhood Size", features.ExpectedNeighbourhoodSize)); featureList.push_back(std::make_pair(prefix + "Average Neighbourhood Size", features.AverageNeighbourhoodSize)); featureList.push_back(std::make_pair(prefix + "Average Incomplete Neighbourhood Size", features.AverageIncompleteNeighbourhoodSize)); featureList.push_back(std::make_pair(prefix + "Percentage of complete Neighbourhoods", features.PercentageOfCompleteNeighbourhoods)); featureList.push_back(std::make_pair(prefix + "Percentage of Dependence Neighbour Voxels", features.PercentageOfDependenceNeighbours)); } mitk::GIFNeighbouringGreyLevelDependenceFeature::GIFNeighbouringGreyLevelDependenceFeature() : m_Range(1.0) { SetShortName("ngld"); SetLongName("neighbouring-grey-level-dependence"); SetFeatureClassName("Neighbouring Grey Level Dependence"); } mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType mitk::GIFNeighbouringGreyLevelDependenceFeature::CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) { FeatureListType featureList; InitializeQuantifier(image, mask); GIFNeighbouringGreyLevelDependenceFeatureConfiguration config; config.direction = GetDirection(); config.range = m_Range; config.alpha = 0; config.MinimumIntensity = GetQuantifier()->GetMinimum(); config.MaximumIntensity = GetQuantifier()->GetMaximum(); config.Bins = GetQuantifier()->GetBins(); config.FeatureEncoding = FeatureDescriptionPrefix(); AccessByItk_3(image, CalculateCoocurenceFeatures, mask, featureList,config); return featureList; } mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureNameListType mitk::GIFNeighbouringGreyLevelDependenceFeature::GetFeatureNames() { FeatureNameListType featureList; return featureList; } void mitk::GIFNeighbouringGreyLevelDependenceFeature::AddArguments(mitkCommandLineParser &parser) { std::string name = GetOptionPrefix(); parser.addArgument(GetLongName(), name, mitkCommandLineParser::Bool, "Calculate Neighbouring Grey Level Dependence Features", "Calculate Neighbouring grey level dependence based features", us::Any()); parser.addArgument(name + "::range", name + "::range", mitkCommandLineParser::String, "NGLD Range", "Define the range that is used (Semicolon-separated)", us::Any()); AddQuantifierArguments(parser); } void mitk::GIFNeighbouringGreyLevelDependenceFeature::CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &, const Image::Pointer &maskNoNAN, FeatureListType &featureList) { auto parsedArgs = GetParameter(); std::string name = GetOptionPrefix(); if (parsedArgs.count(GetLongName())) { std::vector ranges; if (parsedArgs.count(name + "::range")) { ranges = SplitDouble(parsedArgs[name + "::range"].ToString(), ';'); } else { ranges.push_back(1); } for (double range : ranges) { InitializeQuantifierFromParameters(feature, maskNoNAN); this->SetRange(range); MITK_INFO << "Start calculating NGLD"; auto localResults = this->CalculateFeatures(feature, maskNoNAN); featureList.insert(featureList.end(), localResults.begin(), localResults.end()); MITK_INFO << "Finished calculating NGLD"; } } } std::string mitk::GIFNeighbouringGreyLevelDependenceFeature::GetCurrentFeatureEncoding() { std::ostringstream ss; ss << m_Range; std::string strRange = ss.str(); return QuantifierParameterString() + "_Range-"+ss.str(); } diff --git a/Modules/Core/include/mitkSlicedGeometry3D.h b/Modules/Core/include/mitkSlicedGeometry3D.h index a376f8ba8c..d2502f516a 100644 --- a/Modules/Core/include/mitkSlicedGeometry3D.h +++ b/Modules/Core/include/mitkSlicedGeometry3D.h @@ -1,326 +1,330 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSLICEDGEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD #define MITKSLICEDGEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD #include "mitkBaseGeometry.h" #include "mitkPlaneGeometry.h" namespace mitk { class SliceNavigationController; class NavigationController; /** \brief Describes the geometry of a data object consisting of slices. * * A PlaneGeometry can be requested for each slice. In the case of * \em evenly-spaced, \em plane geometries (m_EvenlySpaced==true), * only the 2D-geometry of the first slice has to be set (to an instance of * PlaneGeometry). The 2D geometries of the other slices are calculated * by shifting the first slice in the direction m_DirectionVector by * m_Spacing.z * sliceNumber. The m_Spacing member (which is only * relevant in the case m_EvenlySpaced==true) descibes the size of a voxel * (in mm), i.e., m_Spacing.x is the voxel width in the x-direction of the * plane. It is derived from the reference geometry of this SlicedGeometry3D, * which usually would be the global geometry describing how datasets are to * be resliced. * * By default, slices are oriented in the direction of one of the main axes * (x, y, z). However, by means of rotation, it is possible to realign the * slices in any possible direction. In case of an inclined plane, the spacing * is derived as a product of the (regular) geometry spacing and the direction * vector of the plane. * * SlicedGeometry3D and the associated PlaneGeometries have to be initialized in * the method GenerateOutputInformation() of BaseProcess (or CopyInformation / * UpdateOutputInformation of BaseData, if possible, e.g., by analyzing pic * tags in Image) subclasses. See also * * \sa itk::ProcessObject::GenerateOutputInformation(), * \sa itk::DataObject::CopyInformation() and * \a itk::DataObject::UpdateOutputInformation(). * * Rule: everything is in mm (or ms for temporal information) if not * stated otherwise. * * \warning The hull (i.e., transform, bounding-box and * time-bounds) is only guaranteed to be up-to-date after calling * UpdateInformation(). * * \ingroup Geometry */ class MITKCORE_EXPORT SlicedGeometry3D : public mitk::BaseGeometry { public: mitkClassMacro(SlicedGeometry3D, BaseGeometry) /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * \brief Returns the PlaneGeometry of the slice (\a s). * * If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored * for the requested slice, and (c) the first slice (s=0) * is a PlaneGeometry instance, then we calculate the geometry of the * requested as the plane of the first slice shifted by m_Spacing[3]*s * in the direction of m_DirectionVector. * * \warning The PlaneGeometries are not necessarily up-to-date and not even * initialized. * * The PlaneGeometries have to be initialized in the method * GenerateOutputInformation() of BaseProcess (or CopyInformation / * UpdateOutputInformation of BaseData, if possible, e.g., by analyzing * pic tags in Image) subclasses. See also * * \sa itk::ProcessObject::GenerateOutputInformation(), * \sa itk::DataObject::CopyInformation() and * \sa itk::DataObject::UpdateOutputInformation(). */ virtual mitk::PlaneGeometry *GetPlaneGeometry(int s) const; /** * \deprecatedSince{2014_10} Please use GetPlaneGeometry */ DEPRECATED(const PlaneGeometry *GetGeometry2D(int s)) { return GetPlaneGeometry(s); } /** * \deprecatedSince{2014_10} Please use SetPlaneGeometry */ DEPRECATED(void SetGeometry2D(PlaneGeometry *geo, int s)) { SetPlaneGeometry(geo, s); } //##Documentation //## @brief When switching from an Image Geometry to a normal Geometry (and the other way around), you have to //change // the origin as well (See Geometry Documentation)! This function will change the "isImageGeometry" bool flag and // changes the origin respectively. void ChangeImageGeometryConsideringOriginOffset(const bool isAnImageGeometry) override; // virtual void SetTimeBounds( const mitk::TimeBounds& timebounds ); const mitk::BoundingBox *GetBoundingBox() const override; /** * \brief Get the number of slices */ itkGetConstMacro(Slices, unsigned int) /** * \brief Set PlaneGeometry of slice \a s. */ virtual bool SetPlaneGeometry(mitk::PlaneGeometry *geometry2D, int s); /** * \brief Check whether a slice exists */ virtual bool IsValidSlice(int s = 0) const; virtual const BaseGeometry* GetReferenceGeometry() const; virtual void SetReferenceGeometry(const BaseGeometry *referenceGeometry); bool HasReferenceGeometry() const; /** * \brief Set the SliceNavigationController corresponding to this sliced * geometry. * * The SNC needs to be informed when the number of slices in the geometry * changes, which can occur whenthe slices are re-oriented by rotation. */ virtual void SetSliceNavigationController(mitk::SliceNavigationController *snc); mitk::SliceNavigationController *GetSliceNavigationController(); /** * \brief Set/Get whether the SlicedGeometry3D is evenly-spaced * (m_EvenlySpaced) * * If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored for * the requested slice, and (c) the first slice (s=0) is a PlaneGeometry * instance, then we calculate the geometry of the requested as the plane * of the first slice shifted by m_Spacing.z * s in the direction of * m_DirectionVector. * * \sa GetPlaneGeometry */ itkGetConstMacro(EvenlySpaced, bool) virtual void SetEvenlySpaced(bool on = true); /** * \brief Set/Get the vector between slices for the evenly-spaced case * (m_EvenlySpaced==true). * * If the direction-vector is (0,0,0) (the default) and the first * 2D geometry is a PlaneGeometry, then the direction-vector will be * calculated from the plane normal. * * \sa m_DirectionVector */ virtual void SetDirectionVector(const mitk::Vector3D &directionVector); itkGetConstMacro(DirectionVector, const mitk::Vector3D &) itk::LightObject::Pointer InternalClone() const override; +#ifndef SWIG + static const std::string SLICES; const static std::string DIRECTION_VECTOR; const static std::string EVENLY_SPACED; +#endif // !SWIG + /** * \brief Tell this instance how many PlaneGeometries it shall manage. Bounding * box and the PlaneGeometries must be set additionally by calling the respective * methods! * * \warning Bounding box and the 2D-geometries must be set additionally: use * SetBounds(), SetGeometry(). */ virtual void InitializeSlicedGeometry(unsigned int slices); /** * \brief Completely initialize this instance as evenly-spaced with slices * parallel to the provided PlaneGeometry that is used as the first slice and * for spacing calculation. * * Initializes the bounding box according to the width/height of the * PlaneGeometry and \a slices. The spacing is calculated from the PlaneGeometry. */ virtual void InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, unsigned int slices); /** * \brief Completely initialize this instance as evenly-spaced with slices * parallel to the provided PlaneGeometry that is used as the first slice and * for spacing calculation (except z-spacing). * * Initializes the bounding box according to the width/height of the * PlaneGeometry and \a slices. The x-/y-spacing is calculated from the * PlaneGeometry. */ virtual void InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, mitk::ScalarType zSpacing, unsigned int slices); /** * \brief Completely initialize this instance as evenly-spaced plane slices * parallel to a side of the provided BaseGeometry and using its spacing * information. * * Initializes the bounding box according to the width/height of the * BaseGeometry and the number of slices according to * BaseGeometry::GetExtent(2). * * \param planeorientation side parallel to which the slices will be oriented * \param top if \a true, create plane at top, otherwise at bottom * (for PlaneOrientation Axial, for other plane locations respectively) * \param frontside defines the side of the plane (the definition of * front/back is somewhat arbitrary) * * \param rotate rotates the plane by 180 degree around its normal (the * definition of rotated vs not rotated is somewhat arbitrary) */ virtual void InitializePlanes(const mitk::BaseGeometry *geometry3D, mitk::PlaneGeometry::PlaneOrientation planeorientation, bool top = true, bool frontside = true, bool rotated = false); void SetImageGeometry(const bool isAnImageGeometry) override; void ExecuteOperation(Operation *operation) override; static double CalculateSpacing(const mitk::Vector3D &spacing, const mitk::Vector3D &d); protected: SlicedGeometry3D(); SlicedGeometry3D(const SlicedGeometry3D &other); ~SlicedGeometry3D() override; /** * Reinitialize plane stack after rotation. More precisely, the first plane * of the stack needs to spatially aligned, in two respects: * * 1. Re-alignment with respect to the dataset center; this is necessary * since the distance from the first plane to the center could otherwise * continuously decrease or increase. * 2. Re-alignment with respect to a given reference point; the reference * point is a location which the user wants to be exactly touched by one * plane of the plane stack. The first plane is minimally shifted to * ensure this touching. Usually, the reference point would be the * point around which the geometry is rotated. */ virtual void ReinitializePlanes(const Point3D ¢er, const Point3D &referencePoint); ScalarType GetLargestExtent(const BaseGeometry *geometry); void PrintSelf(std::ostream &os, itk::Indent indent) const override; /** Calculate "directed spacing", i.e. the spacing in directions * non-orthogonal to the coordinate axes. This is done via the * ellipsoid equation. */ double CalculateSpacing(const mitk::Vector3D &direction) const; /** The extent of the slice stack, i.e. the number of slices, depends on the * plane normal. For rotated geometries, the geometry's transform needs to * be accounted in this calculation. */ mitk::Vector3D AdjustNormal(const mitk::Vector3D &normal) const; /** * Container for the 2D-geometries contained within this SliceGeometry3D. */ mutable std::vector m_PlaneGeometries; /** * If (a) m_EvenlySpaced==true, (b) we don't have a PlaneGeometry stored * for the requested slice, and (c) the first slice (s=0) * is a PlaneGeometry instance, then we calculate the geometry of the * requested as the plane of the first slice shifted by m_Spacing.z*s * in the direction of m_DirectionVector. * * \sa GetPlaneGeometry */ bool m_EvenlySpaced; /** * Vector between slices for the evenly-spaced case (m_EvenlySpaced==true). * If the direction-vector is (0,0,0) (the default) and the first * 2D geometry is a PlaneGeometry, then the direction-vector will be * calculated from the plane normal. */ mutable mitk::Vector3D m_DirectionVector; /** Number of slices this SliceGeometry3D is descibing. */ unsigned int m_Slices; /** Underlying BaseGeometry for this SlicedGeometry */ const mitk::BaseGeometry *m_ReferenceGeometry; /** SNC correcsponding to this geometry; used to reflect changes in the * number of slices due to rotation. */ // mitk::NavigationController *m_NavigationController; mitk::SliceNavigationController *m_SliceNavigationController; //##Documentation //## @brief PreSetSpacing //## //## These virtual function allows a different beahiour in subclasses. //## Do implement them in every subclass of BaseGeometry. If not needed, use //## {Superclass::PreSetSpacing();}; void PreSetSpacing(const mitk::Vector3D &aSpacing) override; }; } // namespace mitk #endif /* MITKSLICEDGEOMETRY3D_H_HEADER_INCLUDED_C1EBD0AD */ diff --git a/SuperBuild.cmake b/SuperBuild.cmake index 3a78a6c7e2..6d3e34872d 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -1,453 +1,456 @@ include(mitkFunctionInstallExternalCMakeProject) #----------------------------------------------------------------------------- # Convenient macro allowing to download a file #----------------------------------------------------------------------------- if(NOT MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL) set(MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL http://mitk.org/download/thirdparty) endif() macro(downloadFile url dest) file(DOWNLOAD ${url} ${dest} STATUS status) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to download ${url} - ${error_msg}") endif() endmacro() #----------------------------------------------------------------------------- # MITK Prerequisites #----------------------------------------------------------------------------- if(UNIX AND NOT APPLE) include(mitkFunctionCheckPackageHeader) # Check for libxt-dev mitkFunctionCheckPackageHeader(StringDefs.h libxt-dev /usr/include/X11/) # Check for libtiff4-dev mitkFunctionCheckPackageHeader(tiff.h libtiff4-dev) # Check for libwrap0-dev mitkFunctionCheckPackageHeader(tcpd.h libwrap0-dev) endif() # We need a proper patch program. On Linux and MacOS, we assume # that "patch" is available. On Windows, we download patch.exe # if not patch program is found. find_program(PATCH_COMMAND patch) if((NOT PATCH_COMMAND OR NOT EXISTS ${PATCH_COMMAND}) AND WIN32) downloadFile(${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/patch.exe ${CMAKE_CURRENT_BINARY_DIR}/patch.exe) find_program(PATCH_COMMAND patch ${CMAKE_CURRENT_BINARY_DIR}) endif() if(NOT PATCH_COMMAND) message(FATAL_ERROR "No patch program found.") endif() #----------------------------------------------------------------------------- # ExternalProjects #----------------------------------------------------------------------------- get_property(external_projects GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS) if(MITK_CTEST_SCRIPT_MODE) # Write a file containing the list of enabled external project targets. # This file can be read by a ctest script to separately build projects. set(SUPERBUILD_TARGETS ) foreach(proj ${external_projects}) if(MITK_USE_${proj}) list(APPEND SUPERBUILD_TARGETS ${proj}) endif() endforeach() file(WRITE "${CMAKE_BINARY_DIR}/SuperBuildTargets.cmake" "set(SUPERBUILD_TARGETS ${SUPERBUILD_TARGETS})") endif() # A list of "nice" external projects, playing well together with CMake set(nice_external_projects ${external_projects}) list(REMOVE_ITEM nice_external_projects Boost Python) foreach(proj ${nice_external_projects}) if(MITK_USE_${proj}) set(EXTERNAL_${proj}_DIR "${${proj}_DIR}" CACHE PATH "Path to ${proj} build directory") mark_as_advanced(EXTERNAL_${proj}_DIR) if(EXTERNAL_${proj}_DIR) set(${proj}_DIR ${EXTERNAL_${proj}_DIR}) endif() endif() endforeach() set(EXTERNAL_BOOST_ROOT "${BOOST_ROOT}" CACHE PATH "Path to Boost directory") mark_as_advanced(EXTERNAL_BOOST_ROOT) if(EXTERNAL_BOOST_ROOT) set(BOOST_ROOT ${EXTERNAL_BOOST_ROOT}) endif() # Setup file for setting custom ctest vars configure_file( CMake/SuperbuildCTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) if(BUILD_TESTING) set(EXTERNAL_MITK_DATA_DIR "${MITK_DATA_DIR}" CACHE PATH "Path to the MITK data directory") mark_as_advanced(EXTERNAL_MITK_DATA_DIR) if(EXTERNAL_MITK_DATA_DIR) set(MITK_DATA_DIR ${EXTERNAL_MITK_DATA_DIR}) endif() endif() #----------------------------------------------------------------------------- # External project settings #----------------------------------------------------------------------------- include(ExternalProject) set(ep_prefix "${CMAKE_BINARY_DIR}/ep") set_property(DIRECTORY PROPERTY EP_PREFIX ${ep_prefix}) # Compute -G arg for configuring external projects with the same CMake generator: if(CMAKE_EXTRA_GENERATOR) set(gen "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") else() set(gen "${CMAKE_GENERATOR}") endif() # Use this value where semi-colons are needed in ep_add args: set(sep "^^") ## if(MSVC_VERSION) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP") endif() # This is a workaround for passing linker flags # actually down to the linker invocation set(_cmake_required_flags_orig ${CMAKE_REQUIRED_FLAGS}) set(CMAKE_REQUIRED_FLAGS "-Wl,-rpath") mitkFunctionCheckCompilerFlags(${CMAKE_REQUIRED_FLAGS} _has_rpath_flag) set(CMAKE_REQUIRED_FLAGS ${_cmake_required_flags_orig}) set(_install_rpath_linkflag ) if(_has_rpath_flag) if(APPLE) set(_install_rpath_linkflag "-Wl,-rpath,@loader_path/../lib") else() set(_install_rpath_linkflag "-Wl,-rpath='$ORIGIN/../lib'") endif() endif() set(_install_rpath) if(APPLE) set(_install_rpath "@loader_path/../lib") elseif(UNIX) # this work for libraries as well as executables set(_install_rpath "\$ORIGIN/../lib") endif() set(ep_common_args -DCMAKE_CXX_EXTENSIONS:STRING=${CMAKE_CXX_EXTENSIONS} -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED} -DCMAKE_MACOSX_RPATH:BOOL=TRUE "-DCMAKE_INSTALL_RPATH:STRING=${_install_rpath}" -DBUILD_TESTING:BOOL=OFF -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${MITK_CXX14_FLAG}" #debug flags -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} #release flags -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} #relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} #link flags -DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ) set(DCMTK_CMAKE_DEBUG_POSTFIX ) # python libraries wont work with it if(NOT MITK_USE_Python) list(APPEND ep_common_args -DCMAKE_DEBUG_POSTFIX:STRING=d) set(DCMTK_CMAKE_DEBUG_POSTFIX d) endif() set(ep_common_cache_args ) set(ep_common_cache_default_args "-DCMAKE_PREFIX_PATH:PATH=;${CMAKE_PREFIX_PATH}" "-DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH}" "-DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH}" ) # Pass the CMAKE_OSX variables to external projects if(APPLE) set(MAC_OSX_ARCHITECTURE_ARGS -DCMAKE_OSX_ARCHITECTURES:PATH=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET:PATH=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT} ) set(ep_common_args ${MAC_OSX_ARCHITECTURE_ARGS} ${ep_common_args} ) endif() set(mitk_superbuild_ep_args) set(mitk_depends ) # Include external projects include(CMakeExternals/MITKData.cmake) foreach(p ${external_projects}) if(EXISTS ${CMAKE_SOURCE_DIR}/CMakeExternals/${p}.cmake) include(CMakeExternals/${p}.cmake) else() foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) get_filename_component(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIR} ABSOLUTE) set(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMakeExternals) if(EXISTS ${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/${p}.cmake) include(${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/${p}.cmake) break() endif() endforeach() endif() list(APPEND mitk_superbuild_ep_args -DMITK_USE_${p}:BOOL=${MITK_USE_${p}} ) get_property(_package GLOBAL PROPERTY MITK_${p}_PACKAGE) if(_package) list(APPEND mitk_superbuild_ep_args -D${p}_DIR:PATH=${${p}_DIR}) endif() list(APPEND mitk_depends ${${p}_DEPENDS}) endforeach() +if (SWIG_EXECUTABLE) + list(APPEND mitk_superbuild_ep_args -DSWIG_EXECUTABLE=${SWIG_EXECUTABLE}) +endif() #----------------------------------------------------------------------------- # Set superbuild boolean args #----------------------------------------------------------------------------- set(mitk_cmake_boolean_args BUILD_SHARED_LIBS WITH_COVERAGE BUILD_TESTING MITK_BUILD_ALL_PLUGINS MITK_BUILD_ALL_APPS MITK_BUILD_EXAMPLES MITK_USE_Qt5 MITK_USE_SYSTEM_Boost MITK_USE_BLUEBERRY MITK_USE_OpenCL MITK_ENABLE_PIC_READER ) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(mitk_superbuild_boolean_args) foreach(mitk_cmake_arg ${mitk_cmake_boolean_args}) list(APPEND mitk_superbuild_boolean_args -D${mitk_cmake_arg}:BOOL=${${mitk_cmake_arg}}) endforeach() if(MITK_BUILD_ALL_PLUGINS) list(APPEND mitk_superbuild_boolean_args -DBLUEBERRY_BUILD_ALL_PLUGINS:BOOL=ON) endif() #----------------------------------------------------------------------------- # MITK Utilities #----------------------------------------------------------------------------- set(proj MITK-Utilities) ExternalProject_Add(${proj} DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${mitk_depends} ) #----------------------------------------------------------------------------- # Additional MITK CXX/C Flags #----------------------------------------------------------------------------- set(MITK_ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_RELEASE "" CACHE STRING "Additional Release C Flags for MITK") set(MITK_ADDITIONAL_C_FLAGS_DEBUG "" CACHE STRING "Additional Debug C Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_C_FLAGS MITK_ADDITIONAL_C_FLAGS_DEBUG MITK_ADDITIONAL_C_FLAGS_RELEASE) set(MITK_ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_RELEASE "" CACHE STRING "Additional Release CXX Flags for MITK") set(MITK_ADDITIONAL_CXX_FLAGS_DEBUG "" CACHE STRING "Additional Debug CXX Flags for MITK") mark_as_advanced(MITK_ADDITIONAL_CXX_FLAGS MITK_ADDITIONAL_CXX_FLAGS_DEBUG MITK_ADDITIONAL_CXX_FLAGS_RELEASE) set(MITK_ADDITIONAL_EXE_LINKER_FLAGS "" CACHE STRING "Additional exe linker flags for MITK") set(MITK_ADDITIONAL_SHARED_LINKER_FLAGS "" CACHE STRING "Additional shared linker flags for MITK") set(MITK_ADDITIONAL_MODULE_LINKER_FLAGS "" CACHE STRING "Additional module linker flags for MITK") mark_as_advanced(MITK_ADDITIONAL_EXE_LINKER_FLAGS MITK_ADDITIONAL_SHARED_LINKER_FLAGS MITK_ADDITIONAL_MODULE_LINKER_FLAGS) #----------------------------------------------------------------------------- # MITK Configure #----------------------------------------------------------------------------- if(MITK_INITIAL_CACHE_FILE) set(mitk_initial_cache_arg -C "${MITK_INITIAL_CACHE_FILE}") endif() set(mitk_optional_cache_args ) foreach(type RUNTIME ARCHIVE LIBRARY) if(DEFINED CTK_PLUGIN_${type}_OUTPUT_DIRECTORY) list(APPEND mitk_optional_cache_args -DCTK_PLUGIN_${type}_OUTPUT_DIRECTORY:PATH=${CTK_PLUGIN_${type}_OUTPUT_DIRECTORY}) endif() endforeach() # Optional python variables if(MITK_USE_Python) list(APPEND mitk_optional_cache_args -DMITK_USE_Python:BOOL=${MITK_USE_Python} -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DMITK_USE_SYSTEM_PYTHON:BOOL=${MITK_USE_SYSTEM_PYTHON} ) endif() if(Eigen_INCLUDE_DIR) list(APPEND mitk_optional_cache_args -DEigen_INCLUDE_DIR:PATH=${Eigen_INCLUDE_DIR} ) endif() set(proj MITK-Configure) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} DOWNLOAD_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_CACHE_ARGS # --------------- Build options ---------------- -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} "-DCMAKE_PREFIX_PATH:PATH=${ep_prefix};${CMAKE_PREFIX_PATH}" "-DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH}" "-DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH}" # --------------- Compile options ---------------- -DCMAKE_CXX_EXTENSIONS:STRING=${CMAKE_CXX_EXTENSIONS} -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED} -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} ${MITK_ADDITIONAL_C_FLAGS}" "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} ${MITK_ADDITIONAL_CXX_FLAGS}" # debug flags "-DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} ${MITK_ADDITIONAL_CXX_FLAGS_DEBUG}" "-DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} ${MITK_ADDITIONAL_C_FLAGS_DEBUG}" # release flags "-DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} ${MITK_ADDITIONAL_CXX_FLAGS_RELEASE}" "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} ${MITK_ADDITIONAL_C_FLAGS_RELEASE}" # relwithdebinfo -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} # link flags "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} ${MITK_ADDITIONAL_EXE_LINKER_FLAGS}" "-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS} ${MITK_ADDITIONAL_SHARED_LINKER_FLAGS}" "-DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_MODULE_LINKER_FLAGS} ${MITK_ADDITIONAL_MODULE_LINKER_FLAGS}" # Output directories -DMITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY} -DMITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY} -DMITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY:PATH=${MITK_CMAKE_ARCHIVE_OUTPUT_DIRECTORY} # ------------- Boolean build options -------------- ${mitk_superbuild_boolean_args} ${mitk_optional_cache_args} -DMITK_USE_SUPERBUILD:BOOL=OFF -DMITK_BUILD_CONFIGURATION:STRING=${MITK_BUILD_CONFIGURATION} -DCTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} # ----------------- Miscellaneous --------------- -DCMAKE_LIBRARY_PATH:PATH=${CMAKE_LIBRARY_PATH} -DCMAKE_INCLUDE_PATH:PATH=${CMAKE_INCLUDE_PATH} -DMITK_CTEST_SCRIPT_MODE:STRING=${MITK_CTEST_SCRIPT_MODE} -DMITK_SUPERBUILD_BINARY_DIR:PATH=${MITK_BINARY_DIR} -DMITK_MODULES_TO_BUILD:INTERNAL=${MITK_MODULES_TO_BUILD} -DMITK_WHITELIST:STRING=${MITK_WHITELIST} -DMITK_WHITELISTS_EXTERNAL_PATH:STRING=${MITK_WHITELISTS_EXTERNAL_PATH} -DMITK_WHITELISTS_INTERNAL_PATH:STRING=${MITK_WHITELISTS_INTERNAL_PATH} -DMITK_EXTENSION_DIRS:STRING=${MITK_EXTENSION_DIRS} -DMITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES} -DMITK_ACCESSBYITK_FLOATING_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES} -DMITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES} -DMITK_ACCESSBYITK_VECTOR_PIXEL_TYPES:STRING=${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} -DMITK_ACCESSBYITK_DIMENSIONS:STRING=${MITK_ACCESSBYITK_DIMENSIONS} # --------------- External project options --------------- -DMITK_DATA_DIR:PATH=${MITK_DATA_DIR} -DMITK_EXTERNAL_PROJECT_PREFIX:PATH=${ep_prefix} -DCppMicroServices_DIR:PATH=${CppMicroServices_DIR} -DDCMTK_CMAKE_DEBUG_POSTFIX:STRING=${DCMTK_CMAKE_DEBUG_POSTFIX} -DBOOST_ROOT:PATH=${BOOST_ROOT} -DBOOST_LIBRARYDIR:PATH=${BOOST_LIBRARYDIR} -DMITK_USE_Boost_LIBRARIES:STRING=${MITK_USE_Boost_LIBRARIES} CMAKE_ARGS ${mitk_initial_cache_arg} ${MAC_OSX_ARCHITECTURE_ARGS} ${mitk_superbuild_ep_args} SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} BINARY_DIR ${CMAKE_BINARY_DIR}/MITK-build BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS MITK-Utilities ) mitkFunctionInstallExternalCMakeProject(${proj}) #----------------------------------------------------------------------------- # MITK #----------------------------------------------------------------------------- if(CMAKE_GENERATOR MATCHES ".*Makefiles.*") set(mitk_build_cmd "$(MAKE)") else() set(mitk_build_cmd ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/MITK-build --config ${CMAKE_CFG_INTDIR}) endif() if(NOT DEFINED SUPERBUILD_EXCLUDE_MITKBUILD_TARGET OR NOT SUPERBUILD_EXCLUDE_MITKBUILD_TARGET) set(MITKBUILD_TARGET_ALL_OPTION "ALL") else() set(MITKBUILD_TARGET_ALL_OPTION "") endif() add_custom_target(MITK-build ${MITKBUILD_TARGET_ALL_OPTION} COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build DEPENDS MITK-Configure ) #----------------------------------------------------------------------------- # Custom target allowing to drive the build of the MITK project itself #----------------------------------------------------------------------------- add_custom_target(MITK COMMAND ${mitk_build_cmd} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/MITK-build ) diff --git a/Wrapper/swigutils.cmake b/Wrapper/swigutils.cmake deleted file mode 100644 index 516778aff8..0000000000 --- a/Wrapper/swigutils.cmake +++ /dev/null @@ -1,63 +0,0 @@ -macro(setup_swig) - if (NOT SWIG_DIR) - set(SWIG_DIR $ENV{SWIG_DIR} ) - endif() - if (NOT SWIG_EXECUTABLE) - set(SWIG_EXECUTABLE $ENV{SWIG_EXECUTABLE} ) - endif() - find_package(SWIG REQUIRED) - INCLUDE(${SWIG_USE_FILE}) - message(STATUS "SWIG_DIR = ${SWIG_DIR}" ) - message(STATUS "SWIG_EXECUTABLE = ${SWIG_EXECUTABLE}" ) -endmacro() - -macro(setup_python) - # CMake's python-detection is crazy broken, so we use python-config on *nix. - # Sadly on Windows python-config isn't available, so do our best with CMake. - # - # see https://cmake.org/Bug/view.php?id=14809 - # - if (WIN32) - find_package(PythonInterp) - find_package(PythonLibs) - - set(PYTHON_CFLAGS "-I${PYTHON_INCLUDE_PATH}") - set(PYTHON_LDFLAGS "${PYTHON_LIBRARIES}") - else() - if (ARCH STREQUAL "arm") - find_program(PYTHON_CONFIG_EXECUTABLE arm-linux-gnueabihf-python-config) - else() - find_program(PYTHON_CONFIG_EXECUTABLE python-config) - endif() - if (PYTHON_CONFIG_EXECUTABLE) - execute_process(COMMAND ${PYTHON_CONFIG_EXECUTABLE} --cflags OUTPUT_VARIABLE PYTHON_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND ${PYTHON_CONFIG_EXECUTABLE} --ldflags OUTPUT_VARIABLE PYTHON_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT PYTHON_EXECUTABLE) - execute_process(COMMAND ${PYTHON_CONFIG_EXECUTABLE} --exec-prefix OUTPUT_VARIABLE PYTHON_EXECUTABLE OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}/bin/python) - endif() - endif() - endif() - - if (PYTHON_EXECUTABLE) - # get the python version - execute_process(COMMAND ${PYTHON_EXECUTABLE} --version ERROR_VARIABLE PYTHON_VERSION) - # message("rv='${PYTHON_VERSION}'") - string(STRIP ${PYTHON_VERSION} PYTHON_VERSION) - string(REPLACE " " ";" PYTHON_VERSION ${PYTHON_VERSION}) - list(GET PYTHON_VERSION 1 PYTHON_VERSION) - - message(STATUS "PYTHON_EXECUTABLE= ${PYTHON_EXECUTABLE}") - message(STATUS "PYTHON_VERSION= ${PYTHON_VERSION}") - message(STATUS "PYTHON_CFLAGS= ${PYTHON_CFLAGS}") - message(STATUS "PYTHON_LDFLAGS= ${PYTHON_LDFLAGS}") - - set(PYTHON 1) - endif() -endmacro() - -# build-time file replacement -set(FILE_REPLACE_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/replace.cmake) -file(WRITE ${FILE_REPLACE_SCRIPT} "file(READ \${FROM} file_contents) \n") -file(APPEND ${FILE_REPLACE_SCRIPT} "string(REPLACE \${MATCH_STRING} \${REPLACE_STRING} file_contents \${file_contents}) \n") -file(APPEND ${FILE_REPLACE_SCRIPT} "file(WRITE \${TO} \${file_contents}) \n") diff --git a/Wrapping/CMakeLists.txt b/Wrapping/CMakeLists.txt new file mode 100644 index 0000000000..7d516b4e7d --- /dev/null +++ b/Wrapping/CMakeLists.txt @@ -0,0 +1,68 @@ + +find_package(SWIG REQUIRED) +include(mitkLanguageOptions) +include(UseSWIG) + +include(mitkSwigAddLibraryDependencies) +include(mitkSwigPrepareFiles) + +# Path to common files +set(MITK_WRAPPING_COMMON_DIR ${MITK_SOURCE_DIR}/Wrapping/Common) +# make a manual list of dependencies for the Swig.i files +list( APPEND SWIG_EXTRA_DEPS + "${MITK_WRAPPING_COMMON_DIR}/MITK_Common.i" + ) + +# A general packaging target, not built by default, to build packages for each +# language. This should depend on all language specific targets. + +add_custom_target( dist ${CMAKE_COMMAND} -E echo "Finished generating wrapped packages for distribution..." ) + +# +# lua SWIG configuration +# +#if ( WRAP_LUA ) +# add_subdirectory ( Lua ) +#endif() + +# +# python SWIG configuration +# +if ( WRAP_PYTHON ) + add_subdirectory ( Python ) +endif() + +# +# ruby SWIG configuration +# +#if ( WRAP_RUBY ) +# add_subdirectory ( Ruby ) +#endif() + +# +# JAVA SWIG configuration +# +#if ( WRAP_JAVA ) +# add_subdirectory( Java ) +#endif() + +# +# C# SWIG configuration +# +#if ( WRAP_CSHARP ) +# add_subdirectory ( CSharp ) +#endif() + +# +# TCL SWIG configuration +# +#if ( WRAP_TCL ) +# add_subdirectory ( Tcl ) +#endif() + +# +# R SWIG configuration +# +#if ( WRAP_R ) +# add_subdirectory( R ) +#endif() diff --git a/Wrapping/Common/mitk_swig_classes.i b/Wrapping/Common/mitk_swig_classes.i new file mode 100644 index 0000000000..8a5e384924 --- /dev/null +++ b/Wrapping/Common/mitk_swig_classes.i @@ -0,0 +1,81 @@ + +// +// Defining some Macros that make problems with SWIG as the +// corresponding definitions are not included by default. +// Luckely, these includes are not necessary for SWIG. +// +#define ITK_NOEXCEPT +#define ITKCommon_EXPORT +#define ITK_OVERRIDE +#define MITKCORE_EXPORT +#define MITKCLCORE_EXPORT +#define MITKCLUTILITIES_EXPORT +#define ITKCommon_EXPORT + +#define ITKCommon_EXPORT +#define ITK_FORWARD_EXPORT +#define ITK_OVERRIDE +#define ITK_NOEXCEPT + + +%include +%include +%include +%include +%include +%include + +#define DEPRECATED(func) func +#undef ITK_DISALLOW_COPY_AND_ASSIGN +#define ITK_DISALLOW_COPY_AND_ASSIGN(TypeName) + +%pythoncode %{ + convertion_list = {} +%} + +SWIG_ADD_MITK_CLASS(Object, itkObject.h, itk) +SWIG_ADD_MITK_CLASS(DataObject, itkDataObject.h, itk) + +SWIG_ADD_MITK_CLASS(TimeGeometry, mitkTimeGeometry.h, mitk) +SWIG_ADD_MITK_CLASS(ArbitraryTimeGeometry, mitkArbitraryTimeGeometry.h, mitk) +SWIG_ADD_MITK_CLASS(ProportionalTimeGeometry, mitkProportionalTimeGeometry.h, mitk) +SWIG_ADD_MITK_CLASS(BaseGeometry, mitkBaseGeometry.h, mitk) +SWIG_ADD_MITK_CLASS(Geometry3D, mitkGeometry3D.h, mitk) +SWIG_ADD_MITK_CLASS(SlicedGeometry3D, mitkSlicedGeometry3D.h, mitk) +SWIG_ADD_MITK_CLASS(PlaneGeometry , mitkPlaneGeometry.h, mitk) + +SWIG_ADD_NONOBJECT_NOVECTOR_CLASS(BoundingBox, mitkBaseGeometry.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(TimeBounds, mitkBaseGeometry.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(FixedArrayType, mitkBaseGeometry.h, mitk) + +SWIG_ADD_NONOBJECT_CLASS(Point2D, mitkPoint.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Point3D, mitkPoint.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Point4D, mitkPoint.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Point2I, mitkPoint.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Point3I, mitkPoint.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Point4I, mitkPoint.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(VnlVector, mitkVector.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Vector2D, mitkVector.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Vector3D, mitkVector.h, mitk) +SWIG_ADD_NONOBJECT_CLASS(Vector4D, mitkVector.h, mitk) + +SWIG_ADD_MITK_CLASS(BaseData, mitkBaseData.h, mitk) +SWIG_ADD_MITK_CLASS(SlicedData, mitkSlicedData.h, mitk) +SWIG_ADD_MITK_CLASS(Image, mitkImage.h, mitk) +SWIG_ADD_MITK_CLASS(PointSet, mitkPointSet.h, mitk) + +SWIG_ADD_MITK_CLASS(AbstractGlobalImageFeature, mitkAbstractGlobalImageFeature.h, mitk) +SWIG_ADD_MITK_CLASS(GIFImageDescriptionFeatures, mitkGIFImageDescriptionFeatures.h, mitk) +SWIG_ADD_MITK_CLASS(GIFFirstOrderStatistics, mitkGIFFirstOrderStatistics.h, mitk) +SWIG_ADD_MITK_CLASS(GIFFirstOrderHistogramStatistics, mitkGIFFirstOrderHistogramStatistics.h, mitk) +SWIG_ADD_MITK_CLASS(GIFVolumetricStatistics, mitkGIFVolumetricStatistics.h, mitk) +SWIG_ADD_MITK_CLASS(GIFVolumetricDensityStatistics, mitkGIFVolumetricDensityStatistics.h, mitk) +SWIG_ADD_MITK_CLASS(GIFCooccurenceMatrix2, mitkGIFCooccurenceMatrix2.h, mitk) +SWIG_ADD_MITK_CLASS(GIFNeighbouringGreyLevelDependenceFeature, mitkGIFNeighbouringGreyLevelDependenceFeatures.h, mitk) +SWIG_ADD_MITK_CLASS(GIFGreyLevelRunLength, mitkGIFGreyLevelRunLength.h, mitk) +SWIG_ADD_MITK_CLASS(GIFGreyLevelSizeZone, mitkGIFGreyLevelSizeZone.h, mitk) +SWIG_ADD_MITK_CLASS(GIFGreyLevelDistanceZone, mitkGIFGreyLevelDistanceZone.h, mitk) +SWIG_ADD_MITK_CLASS(GIFLocalIntensity, mitkGIFLocalIntensity.h, mitk) +SWIG_ADD_MITK_CLASS(GIFIntensityVolumeHistogramFeatures, mitkGIFIntensityVolumeHistogramFeatures.h, mitk) +SWIG_ADD_MITK_CLASS(GIFNeighbourhoodGreyToneDifferenceFeatures, mitkGIFNeighbourhoodGreyToneDifferenceFeatures.h, mitk) +SWIG_ADD_MITK_CLASS(GIFCurvatureStatistic, mitkGIFCurvatureStatistic.h, mitk) \ No newline at end of file diff --git a/Wrapping/Common/mitk_swig_common.i b/Wrapping/Common/mitk_swig_common.i new file mode 100644 index 0000000000..cdcbc58efa --- /dev/null +++ b/Wrapping/Common/mitk_swig_common.i @@ -0,0 +1,37 @@ + +// Ignore common warnings: +// 302 : Redefinition of Macro, usually not a problem +// 362 : Operator= is ignored. Can't help it. +// 503 : Can't wrap operator of type "*" unless renamed to a valid identifier, no problem as operator not needed. +// 509 : Overloaded function ignored. Usually not a problem, as overloaded functions shouldn't give different results. +// 511 : Can't use keyword arguments with overloaded functions +#pragma SWIG nowarn=302,362,503,509,511 + +// Splitted the information about the addition files into sub-files: + +%naturalvar; + +// Includes of STD-Files goes in here +%include +// Include c++ code in this file. It is basically a c++-header wrapped in the commands so it is included in the std-file +%include +// SWIG-Macro definition goes in here, for example SWIG_ADD_MITK_CLASS +%include +// information about classes that are going to be wrapped are in here: +%include + +// +// How to wrap a new class: +// ------------------------------------ +// (1. Add the c++ include file to mitk_swig_cpp_include.i +// If the class is in a new module, make sure that this module is added as dependency in cmake ) +// This step should no longer be necessary as the corresponding header is now included by +// the SWIG_ADD_MITK_CLASS macro. +// 2. Add the class definition in mitk_swig_classes.i +// If the definition of the class needs new macros, for example because it is not in the core +// and has a new Export-Macro, be sure to define this macro first. +// If the class inherit from mitk::BaseData use the SWIG_ADD_MITK_CLASS macro, as it defines +// some redundante code. +// + +std::vector mitk::GetImageSize(mitk::Image::Pointer image); \ No newline at end of file diff --git a/Wrapping/Common/mitk_swig_cpp_include.i b/Wrapping/Common/mitk_swig_cpp_include.i new file mode 100644 index 0000000000..198e92ece6 --- /dev/null +++ b/Wrapping/Common/mitk_swig_cpp_include.i @@ -0,0 +1,127 @@ +%{ + +#include +#include +#include +#include +#include +#include +#include +#include + +// SWIG Doesn't wrap namespaces. This leads to some problems, if the namespaces are not used. +using mitk::DataStorage; +using mitk::IFileReader; +using mitk::IFileWriter; +using mitk::ScalarType; +using mitk::Operation; +using mitk::GeometryTransformHolder; +using mitk::AffineTransform3D; +using mitk::BaseProperty; +using mitk::ImageDescriptor; +using mitk::PropertyList; +using mitk::ImageDataItem; +using mitk::PointSpecificationType; +using mitk::IntensityQuantifier; + +using itk::LightObject; +using itk::ModifiedTimeType; +using itk::TimeStamp; +using itk::EventObject; +using itk::MetaDataDictionary; +using itk::SmartPointerForwardReference; +using itk::RealTimeStamp; + + +std::vector GetImageSize(mitk::Image::Pointer image) +{ + std::vector< unsigned int > size; + unsigned int dimension = image->GetDimension(); + for (int i = 0; i < dimension; ++i) + { + size.push_back(image->GetDimension(i)); + } + return size; +} + +std::vector GetImageSize(mitk::Image* image) +{ + std::vector< unsigned int > size; + unsigned int dimension = image->GetDimension(); + for (int i = 0; i < dimension; ++i) + { + size.push_back(image->GetDimension(i)); + } + return size; +} + +struct TypeDefinitions +{ + static const int ComponentTypeUInt8 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeInt8 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeUInt16 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeInt16 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeUInt32 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeInt32 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeFloat = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeDouble = mitk::MapPixelType::value>::IOComponentType; +}; + +mitk::PixelType MakePixelTypeFromTypeID(int componentTypeID, int numberOfComponents) +{ + switch (componentTypeID) + { + case TypeDefinitions::ComponentTypeUInt8 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeInt8 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeUInt16 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeInt16 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeUInt32 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeInt32 : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeFloat : + return mitk::MakePixelType(numberOfComponents); + case TypeDefinitions::ComponentTypeDouble : + return mitk::MakePixelType(numberOfComponents); + default: + return mitk::MakePixelType(numberOfComponents); + } +} + +mitk::Image::Pointer MakeImage(mitk::PixelType pixelType, std::vector shape) +{ + mitk::Image::Pointer image = mitk::Image::New(); + image->Initialize(pixelType, shape.size(), shape.data()); + return image; +} + +template +typename T::Pointer ConvertTo(itk::Object::Pointer base) +{ + typename T::Pointer erg = dynamic_cast(base.GetPointer()); + return erg; +} + +%} + +std::vector GetImageSize(mitk::Image::Pointer image); +std::vector GetImageSize(mitk::Image* image); +mitk::PixelType MakePixelTypeFromTypeID(int componentTypeID, int numberOfComponents); +mitk::Image::Pointer MakeImage(mitk::PixelType pixelType, std::vector shape); + +%constant int ComponentTypeUInt8 = TypeDefinitions::ComponentTypeUInt8; +%constant int ComponentTypeInt8 = TypeDefinitions::ComponentTypeInt8; +%constant int ComponentTypeUInt16 = TypeDefinitions::ComponentTypeUInt16; +%constant int ComponentTypeInt16 = TypeDefinitions::ComponentTypeInt16; +%constant int ComponentTypeUInt32 = TypeDefinitions::ComponentTypeUInt32; +%constant int ComponentTypeInt32 = TypeDefinitions::ComponentTypeInt32; +%constant int ComponentTypeFloat = TypeDefinitions::ComponentTypeFloat; +%constant int ComponentTypeDouble = TypeDefinitions::ComponentTypeDouble; + +template +typename T::Pointer ConvertTo(itk::Object::Pointer base); + diff --git a/Wrapping/Common/mitk_swig_macros.i b/Wrapping/Common/mitk_swig_macros.i new file mode 100644 index 0000000000..9ab07200c4 --- /dev/null +++ b/Wrapping/Common/mitk_swig_macros.i @@ -0,0 +1,196 @@ +// +// This file contains macros for swig. +// + +// +// SWIG_ADD_MITK_CLASS is a helper macro in order to do +// all important stuff before an mitk::Class is included. +// Requires the name of the class as it is in c++ as classname +// and the include file, in which the class is defined. +// It is assumed that the class is somehow inherited from +// mitk::BaseData, and supports smartpointers. +// +%define SWIG_ADD_MITK_CLASS(classname, classinclude, nspace) + // Include the include file in the generated cpp file + %{ + #include < classinclude > + typedef nspace ## :: ## classname classname ## ; + using nspace ## :: ## classname ; + %} + + // Include the given header, where the class definition is found + %include + using nspace ##:: ## classname ; + + + // Declaring that this class is a smart-pointer class, in order to handle + // online upcasting where necessary (for example python) + %feature("smartptr", noblock=1) nspace ##:: ## classname { itk::SmartPointer } + + + // Typedef is necessary to overcome ambigiouties resulting in the fact that SWIG + // ignores namespaces. This can lead to some problems with templates. + typedef nspace ## :: ## classname classname ## ; + + // Initianziation of std. vectors containing pointers to these classes. This allows to use + // vectors of these types as target language arrays. + %template(Vector ## classname ## Pointer) std::vector< nspace ## :: ## classname ## ::Pointer >; + %template(Vector ## classname) std::vector< nspace ## :: ## classname ## ::Self *>; + + // Defining the Smartpointer, allows easy access in target language + %template(classname ## Pointer) itk::SmartPointer; + + // Define a conversion method to convert from and to types + %template(ConvertTo ## classname) ConvertTo< nspace ##:: ## classname ## >; + + + // This extend is necessary to have the automatic cast methods available +%extend itk::SmartPointer< nspace ## :: ## classname ## ::Self> { + %pythoncode %{ + def _GetListOfValidItems(self): + return [str(k) for k in self.GetClassHierarchy() if k in convertion_list.keys() ] + %} + %pythoncode %{ + def __getattr__(self, item): + if type(item)==str: + if (len(item) > 9) and ('ConvertTo' in item): + searchString=item[9:] + if searchString in self._GetListOfValidItems(): + def func_t(): + return convertion_list[searchString](self) + return func_t + %} + %pythoncode %{ + def __dir__(self): + return super().__dir__() + ['ConvertTo'+k for k in self._GetListOfValidItems()] + %} +} + +%extend std::vector< nspace ## :: ## classname *>::value_type { + %pythoncode %{ + def _GetListOfValidItems(self): + return [str(k) for k in self.GetClassHierarchy() if k in convertion_list.keys() ] + %} + %pythoncode %{ + def __getattr__(self, item): + if type(item)==str: + if (len(item) > 9) and ('ConvertTo' in item): + searchString=item[9:] + if searchString in self._GetListOfValidItems(): + def func_t(): + return convertion_list[searchString](self) + return func_t + %} + %pythoncode %{ + def __dir__(self): + return super().__dir__() + ['ConvertTo'+k for k in self._GetListOfValidItems()] + %} +} + +%pythoncode %{ + convertion_list['classname'] = ConvertTo ## classname +%} + +%enddef + + +// +// SWIG_ADD_NONOBJECT_CLASS is a helper macro in order to do +// all important stuff before an mitk::Class is included. +// Requires the name of the class as it is in c++ as classname +// and the include file, in which the class is defined. +// It is assumed that the class is somehow inherited from +// mitk::BaseData, and supports smartpointers. +// +%define SWIG_ADD_NONOBJECT_CLASS(classname, classinclude, nspace) + // Include the include file in the generated cpp file + %{ + #include < classinclude > + typedef nspace ## :: ## classname classname ## ; + using nspace ## :: ## classname ; + %} + + // Include the given header, where the class definition is found + %include + using nspace ##:: ## classname ; + + // Typedef is necessary to overcome ambigiouties resulting in the fact that SWIG + // ignores namespaces. This can lead to some problems with templates. + typedef nspace ## :: ## classname classname ## ; + + class nspace ## :: ## classname ## ; + + // Initianziation of std. vectors containing pointers to these classes. This allows to use + // vectors of these types as target language arrays. + %template(Vector ## classname ## Pointer) std::vector< nspace ## :: ## classname * >; + %template(Vector ## classname) std::vector< nspace ## :: ## classname >; + +%enddef + + + +// +// SWIG_ADD_NONOBJECT_TEMPLATECLASS is a helper macro in order to do +// all important stuff before an mitk::Class is included. +// Requires the name of the class as it is in c++ as classname +// and the include file, in which the class is defined. +// It is assumed that the class is somehow inherited from +// mitk::BaseData, and supports smartpointers. +// +%define SWIG_ADD_NONOBJECT_TEMPLATECLASS(classname, classinclude, nspace, tmplstring) + // Include the include file in the generated cpp file + %{ + #include < classinclude > + typedef nspace ## :: ## classname classname ## ; + using nspace ## :: ## classname ; + %} + + // Include the given header, where the class definition is found + %include + using nspace ##:: ## classname ; + + // Typedef is necessary to overcome ambigiouties resulting in the fact that SWIG + // ignores namespaces. This can lead to some problems with templates. + typedef nspace ## :: ## classname classname ## ; + + %template( classname ) nspace ## :: ## tmplstring ## ; + + // Initianziation of std. vectors containing pointers to these classes. This allows to use + // vectors of these types as target language arrays. + %template(Vector ## classname ## Pointer) std::vector< nspace ## :: ## classname * >; + %template(Vector ## classname) std::vector< nspace ## :: ## classname >; + +%enddef + + + + +// +// SWIG_ADD_NONOBJECT_CLASS is a helper macro in order to do +// all important stuff before an mitk::Class is included. +// Requires the name of the class as it is in c++ as classname +// and the include file, in which the class is defined. +// It is assumed that the class is somehow inherited from +// mitk::BaseData, and supports smartpointers. +// +%define SWIG_ADD_NONOBJECT_NOVECTOR_CLASS(classname, classinclude, nspace) + // Include the include file in the generated cpp file + %{ + #include < classinclude > + typedef nspace ## :: ## classname classname ## ; + using nspace ## :: ## classname ; + %} + + // Include the given header, where the class definition is found + %include + using nspace ##:: ## classname ; + + // Typedef is necessary to overcome ambigiouties resulting in the fact that SWIG + // ignores namespaces. This can lead to some problems with templates. + typedef nspace ## :: ## classname classname ## ; + + // Initianziation of std. vectors containing pointers to these classes. This allows to use + // vectors of these types as target language arrays. + %template(Vector ## classname ## Pointer) std::vector< nspace ## :: ## classname * >; + +%enddef diff --git a/Wrapping/Common/mitk_swig_std.i b/Wrapping/Common/mitk_swig_std.i new file mode 100644 index 0000000000..818c16a3df --- /dev/null +++ b/Wrapping/Common/mitk_swig_std.i @@ -0,0 +1,40 @@ + +// +// Includes for STD-library support +// +%include +%include +%include +#if SWIGPYTHON || SWIGRUBY +%include +#endif +// Use C99 int support +%include + +// +// Template definition for the most common vector types +// +namespace std { + %template(VectorBool) vector; + %template(VectorUInt8) vector; + %template(VectorInt8) vector; + %template(VectorUInt16) vector; + %template(VectorInt16) vector; + %template(VectorUInt32) vector; + %template(VectorInt32) vector; + %template(VectorUInt64) vector; + %template(VectorInt64) vector; + %template(VectorFloat) vector; + %template(VectorDouble) vector; + %template(VectorUIntList) vector< vector >; + %template(VectorString) vector< std::string >; + + %template(MapDoubleDouble) map; + %template(MapStringDouble) map; + + %template(PairDoubleDouble) pair; + %template(PairStringDouble) pair; + + %template(VectorMapStringDouble) vector< map< std::string, double> >; + %template(VectorPairStringDouble) vector< pair< std::string, double> >; +} \ No newline at end of file diff --git a/Wrapping/Python/CMakeLists.txt b/Wrapping/Python/CMakeLists.txt new file mode 100644 index 0000000000..99c6160c66 --- /dev/null +++ b/Wrapping/Python/CMakeLists.txt @@ -0,0 +1,77 @@ +# Version 2.8.1 is the minium requirement for this script. +# this is lower than the general minimum requirement. +#cmake_minimum_required ( VERSION 2.8.1 FATAL_ERROR ) + +include(mitkTargetLinkLibrariesWithDynamicLookup) + +project( MITK_Python ) + +set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "" FORCE) +set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "" FORCE) + +mitk_check_dynamic_lookup(MODULE + SHARED + MITK_UNDEFINED_SYMBOLS_ALLOWED + ) + +# +# Find the necessary libraries etc.. +# + +if ( MITK_UNDEFINED_SYMBOLS_ALLOWED ) + set( _QUIET_LIBRARY "QUIET" ) +else() + set( _QUIET_LIBRARY "REQUIRED" ) +endif() + +find_package ( PythonInterp REQUIRED ) +find_package ( PythonLibs ${_QUIET_LIBRARY} ) +include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ) +# +# Options +# +option ( MITK_PYTHON_THREADS "Enable threaded python usage by unlocking the GIL." ON ) +mark_as_advanced( MITK_PYTHON_THREADS ) +option ( MITK_PYTHON_EGG "Add building of python eggs to the dist target." OFF ) +mark_as_advanced( MITK_PYTHON_EGG ) +option ( MITK_PYTHON_WHEEL "Add building of python wheels to the dist target." ON ) +mark_as_advanced( MITK_PYTHON_WHEEL ) + +# Prepare the SWIG-File, i.e. especially add necessary include folders +mitkSwigPrepareFiles(MITK.i "MitkCore;MitkCLCore;MitkCLUtilities") + +# Add additional SWIG Parameters +# These parameters depend on the target language +set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_GLOBAL_FLAGS} -features autodoc=1 -keyword ) +if( MITK_PYTHON_THREADS ) + set(CMAKE_SWIG_FLAGS ${CMAKE_SWIG_FLAGS} -threads) +endif() +set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}) + +# Create the actual SWIG project +swig_add_module(pyMITK python MITK.i ) + +mitkSwigAddLibraryDependencies(pyMITK "MitkCore;MitkCLCore;MitkCLUtilities") +mitk_target_link_libraries_with_dynamic_lookup(${SWIG_MODULE_pyMITK_REAL_NAME} ${PYTHON_LIBRARIES}) + + +if(DEFINED SKBUILD) + message(WARNING "SKBuild exists") + # Currently this installation + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/pyMITK.py + ${CMAKE_CURRENT_SOURCE_DIR}/Packaging/__init__.py + # ${MITK_DOC_FILES} + DESTINATION pyMITK + COMPONENT Runtime + ) + + install(TARGETS ${SWIG_MODULE_pyMITK_REAL_NAME} + RUNTIME DESTINATION pyMITK + LIBRARY DESTINATION pyMITK + COMPONENT Runtime + ) +else() + message(WARNING "SKBuild missing") + include(LegacyPackaging.cmake) +endif() diff --git a/Wrapping/Python/LegacyPackaging.cmake b/Wrapping/Python/LegacyPackaging.cmake new file mode 100644 index 0000000000..41ff58f18e --- /dev/null +++ b/Wrapping/Python/LegacyPackaging.cmake @@ -0,0 +1,113 @@ +if ( MITK_DOC_FILES ) + # create a python list for the import documents to include in + # packaging + + # specially handle the first element + list( GET MITK_DOC_FILES 0 d ) + file(TO_NATIVE_PATH "${d}" d ) + set( MITK_DOC_FILES_AS_LIST "[r'${d}'") + set( _doc_list "${MITK_DOC_FILES}" ) + list( REMOVE_AT _doc_list 0 ) + + foreach( d ${_doc_list} ) + file(TO_NATIVE_PATH "${d}" d ) + set( MITK_DOC_FILES_AS_LIST "${MITK_DOC_FILES_AS_LIST},r'${d}'") + endforeach() + set( MITK_DOC_FILES_AS_LIST "${MITK_DOC_FILES_AS_LIST}]") + +endif() + +# Step 1: +# Do initial configuration of setup.py with variable a available +# at configuration time. +set(MITK_BINARY_MODULE "@MITK_BINARY_MODULE@") +set(MITK_RUNTIME_PATH "@MITK_RUNTIME_PATH@") +set(PYTHON_LIB_DEPENDENCIES "@PYTHON_LIB_DEPENDENCIES@") +set(TMP_MITK_BINARY_MODULE "@MITK_BINARY_MODULE@" ) +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Packaging/setup.py.in" + "${CMAKE_CURRENT_BINARY_DIR}/Packaging/setup.py.in" ) +set(MITK_BINARY_MODULE) + +# Step 2: +# Do file configuration during compilation with generator expressions +mitkFunctionGetLibrarySearchPaths(MITK_RUNTIME_PATH release) + +add_custom_command(TARGET ${SWIG_MODULE_pyMITK_REAL_NAME} + POST_BUILD + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMAND ${CMAKE_COMMAND} + "-DMITK_BINARY_MODULE=$" + "-DMITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY=${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + "-\"DMITK_RUNTIME_PATH=${MITK_RUNTIME_PATH}\"" + "-DCONFIGUREBUILDTIME_filename=${CMAKE_CURRENT_BINARY_DIR}/Packaging/setup.py.in" + "-DCONFIGUREBUILDTIME_out_filename=${CMAKE_CURRENT_BINARY_DIR}/Packaging/setup.py" + -P "${MITK_SOURCE_DIR}/CMake/mitkSWIGConfigurePythonfileBuildtime.cmake" + COMMENT "Generating setup.py..." + ) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/Packaging/__init__.py" + "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" + COPYONLY ) + +# Hopefully being able to turn this option on at some point in future. +option(MITK_PYTHON_USE_VIRTUALENV "Create a Python Virtual Environment for testing." OFF) +mark_as_advanced(MITK_PYTHON_USE_VIRTUALENV) + +set(VIRTUAL_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}) +if (MITK_PYTHON_USE_VIRTUALENV) + + # Executable to setup a new Python virtual environment + find_package( PythonVirtualEnv REQUIRED ) + + sitk_enforce_forbid_downloads( MITK_PYTHON_USE_VIRTUALENV ) + + if (MITK_PYTHON_WHEEL AND PYTHON_VIRTUALENV_VERSION_STRING VERSION_LESS "13") + message(SEND_ERROR "In sufficient version of virutalenv for \ + building wheels. Require virtualenv>=13.0.") + endif() + + # + # Setup Python Virtual Environment for testing and packaging + # + set( PythonVirtualenvHome "${${CMAKE_PROJECT_NAME}_BINARY_DIR}/Testing/Installation/PythonVirtualenv" ) + + # virtualenv places the python executable in different + # locations. Also note than on windows installations where python is + # installed only for a single user the may be a missing dll issue. + if( WIN32 ) + set( VIRTUAL_PYTHON_EXECUTABLE + "${PythonVirtualenvHome}/Scripts/python") + else( ) + set( VIRTUAL_PYTHON_EXECUTABLE "${PythonVirtualenvHome}/bin/python" ) + endif() + set(MITK_PYTHON_TEST_EXECUTABLE "${VIRTUAL_PYTHON_EXECUTABLE}" + CACHE INTERNAL "Python executable for testing." FORCE ) + + # configure a scripts which creates the virtualenv and installs numpy + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/PythonVirtualEnvInstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/PythonVirtualEnvInstall.cmake" + @ONLY ) + + set( PythonVirtualEnv_ALL "" ) + if ( BUILD_TESTING ) + set( PythonVirtualEnv_ALL "ALL" ) + endif() + + add_custom_target( PythonVirtualEnv ${PythonVirtualEnv_ALL} + DEPENDS "${VIRTUAL_PYTHON_EXECUTABLE}" + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/PythonVirtualEnvInstall.cmake.in ) + + add_custom_command( OUTPUT "${VIRTUAL_PYTHON_EXECUTABLE}" + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/PythonVirtualEnvInstall.cmake" + DEPENDS + "${SWIG_MODULE_pyMITK_REAL_NAME}" + "${CMAKE_CURRENT_BINARY_DIR}/PythonVirtualEnvInstall.cmake" + COMMENT "Creating python virtual enviroment..." + ) +endif() + +# Packaging for distribution +add_subdirectory(dist) diff --git a/Wrapping/Python/MITK.i b/Wrapping/Python/MITK.i new file mode 100644 index 0000000000..cbdd3c857c --- /dev/null +++ b/Wrapping/Python/MITK.i @@ -0,0 +1,171 @@ +%module pyMITK + +%include + +%{ +#include "mitkNumpyArrayConversion.cxx" +%} + +// Numpy array conversion support +%native(_GetMemoryViewFromImage) PyObject *mitk_GetMemoryViewFromImage( PyObject *self, PyObject *args ); +%native(_SetImageFromArray) PyObject *mitk_SetImageFromArray( PyObject *(self), PyObject *args ); + + +%pythoncode %{ + +HAVE_NUMPY = True +try: + import numpy +except ImportError: + HAVE_NUMPY = False + + +def _get_numpy_dtype( mitkImage ): + """Given a MITK image, returns the numpy.dtype which describes the data""" + + if not HAVE_NUMPY: + raise ImportError('Numpy not available.') + + # this is a mapping from MITK's pixel id to numpy's dtype + _mitk_np = {ComponentTypeUInt8:numpy.uint8, + ComponentTypeUInt16:numpy.uint16, + ComponentTypeUInt32:numpy.uint32, + ComponentTypeInt8:numpy.int8, + ComponentTypeInt16:numpy.int16, + ComponentTypeInt32:numpy.int32, + ComponentTypeFloat:numpy.float32, + ComponentTypeDouble:numpy.float64, + } + + return _mitk_np[ mitkImage.GetPixelType().GetComponentType() ] + + + +def _get_mitk_pixelid(numpy_array_type): + """Returns a MITK PixelID given a numpy array.""" + + if not HAVE_NUMPY: + raise ImportError('Numpy not available.') + + # This is a Mapping from numpy array types to sitks pixel types. + _np_mitk = {numpy.character:ComponentTypeUInt8, + numpy.uint8:ComponentTypeUInt8, + numpy.uint16:ComponentTypeUInt16, + numpy.uint32:ComponentTypeUInt32, + numpy.int8:ComponentTypeInt8, + numpy.int16:ComponentTypeInt16, + numpy.int32:ComponentTypeInt32, + numpy.float32:ComponentTypeFloat, + numpy.float64:ComponentTypeDouble, + } + + try: + return _np_mitk[numpy_array_type.dtype] + except KeyError: + for key in _np_mitk: + if numpy.issubdtype(numpy_array_type.dtype, key): + return _np_mitk[key] + raise TypeError('dtype: {0} is not supported.'.format(numpy_array_type.dtype)) + +def _get_sitk_vector_pixelid(numpy_array_type): + """Returns a MITK vecotr PixelID given a numpy array.""" + + if not HAVE_NUMPY: + raise ImportError('Numpy not available.') + + # This is a Mapping from numpy array types to sitks pixel types. + _np_sitk = {numpy.character:sitkVectorUInt8, + numpy.uint8:sitkVectorUInt8, + numpy.uint16:sitkVectorUInt16, + numpy.uint32:sitkVectorUInt32, + numpy.uint64:sitkVectorUInt64, + numpy.int8:sitkVectorInt8, + numpy.int16:sitkVectorInt16, + numpy.int32:sitkVectorInt32, + numpy.int64:sitkVectorInt64, + numpy.float32:sitkVectorFloat32, + numpy.float64:sitkVectorFloat64, + } + + try: + return _np_sitk[numpy_array_type.dtype] + except KeyError: + for key in _np_sitk: + if numpy.issubdtype(numpy_array_type.dtype, key): + return _np_sitk[key] + raise TypeError('dtype: {0} is not supported.'.format(numpy_array_type.dtype)) + + +# MITK <-> Numpy Array conversion support. +#http://www.nickdarnell.com/swig-casting-revisited/ +def GetArrayViewFromImage(image): + """Get a NumPy ndarray view of a MITK Image. + + Returns a Numpy ndarray object as a "view" of the MITK's Image buffer. This reduces pixel buffer copies, but requires that the MITK image object is kept around while the buffer is being used. + + """ + + if not HAVE_NUMPY: + raise ImportError('NumPy not available.') + + dtype = _get_numpy_dtype( image ) + + shape = GetImageSize(image); + if image.GetPixelType().GetNumberOfComponents() > 1: + shape = ( image.GetPixelType().GetNumberOfComponents(), ) + shape + + imageMemoryView = _pyMITK._GetMemoryViewFromImage(image) + arrayView = numpy.asarray(imageMemoryView).view(dtype = dtype) + arrayView.shape = shape[::-1] + + return arrayView + +def GetArrayFromImage(image): + """Get a NumPy ndarray from a MITK Image. + + This is a deep copy of the image buffer and is completely safe and without potential side effects. + """ + + # TODO: If the image is already not unique then a second copy may be made before the numpy copy is done. + arrayView = GetArrayViewFromImage(image) + + # perform deep copy of the image buffer + return numpy.array(arrayView, copy=True) + +def GetImageFromArray( arr, isVector=False): + """Get a MITK Image from a numpy array. If isVector is True, then a 3D array will be treated as a 2D vector image, otherwise it will be treated as a 3D image""" + + if not HAVE_NUMPY: + raise ImportError('Numpy not available.') + + z = numpy.asarray( arr ) + + assert z.ndim in ( 2, 3, 4 ), \ + "Only arrays of 2, 3 or 4 dimensions are supported." + + id = _get_mitk_pixelid( z ) + #img = Image_New() + + if ( z.ndim == 3 and isVector ) or (z.ndim == 4): + pixelType=MakePixelTypeFromTypeID(id, z.shape[-1]) + newShape=VectorUInt32(z.shape[-2::-1]) + img = MakeImage(pixelType, newShape) + #img.Initialize(pixelType, z.ndim - 1, z.shape[-2::-1]) + elif z.ndim in ( 2, 3 ): + pixelType=MakePixelTypeFromTypeID(id, 1) + newShape=VectorUInt32(z.shape[::-1]) + img = MakeImage(pixelType, newShape) + #img.Initialize(pixelType, z.ndim, z.shape[::-1]) + + _pyMITK._SetImageFromArray( z.tostring(), img ) + + return img + +#convertion_list = {'Image':ConvertToImage, +# 'SlicedData':ConvertToSlicedData, +# 'BaseData':ConvertToBaseData} + +%} + + + diff --git a/Wrapping/Python/PackageUtility/Dockerfile-Python b/Wrapping/Python/PackageUtility/Dockerfile-Python new file mode 100644 index 0000000000..0de8418b1e --- /dev/null +++ b/Wrapping/Python/PackageUtility/Dockerfile-Python @@ -0,0 +1,13 @@ +FROM python +MAINTAINER Insight Software Consortium + +ENV http_proxy http://www-int2.dkfz-heidelberg.de:3128/ +ENV https_proxy https://www-int2.dkfz-heidelberg.de:3128/ + + +RUN apt-get update && \ + yes | apt-get install libgl1-mesa-glx + +# User is expected to mount directory to "/work" +ENTRYPOINT ["bash", "-c", "groupadd -o -g $_GROUPID $_USER && useradd -m -o -g $_GROUPID $_USER -u $_USERID && su $_USER /work/io/imagefiles/cmd.sh" ] + diff --git a/Wrapping/Python/PackageUtility/Dockerfile-x86_64 b/Wrapping/Python/PackageUtility/Dockerfile-x86_64 new file mode 100644 index 0000000000..79739e4515 --- /dev/null +++ b/Wrapping/Python/PackageUtility/Dockerfile-x86_64 @@ -0,0 +1,36 @@ +FROM quay.io/pypa/manylinux1_x86_64 +MAINTAINER Insight Software Consortium + +ENV http_proxy http://www-int2.dkfz-heidelberg.de:3128/ +ENV https_proxy https://www-int2.dkfz-heidelberg.de:3128/ + +ADD https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz \ + https://www.openssl.org/source/openssl-1.0.2h.tar.gz \ + /tmp/ + +ADD http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz \ + https://gmplib.org/download/gmp/gmp-6.0.0a.tar.bz2 \ + http://www.mpfr.org/mpfr-3.1.3/mpfr-3.1.3.tar.bz2 \ + https://ftp.gnu.org/gnu/mpc/mpc-1.0.2.tar.gz \ + http://bugseng.com/products/ppl/download/ftp/releases/1.1/ppl-1.1.tar.bz2 \ + http://www.bastoul.net/cloog/pages/download/cloog-0.18.1.tar.gz \ + http://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.bz2 \ + http://ftp.gnu.org/gnu/binutils/binutils-2.24.tar.bz2 \ + http://download.osgeo.org/libtiff/tiff-4.0.9.tar.gz \ + /tmp/archives/ + +RUN yum -y install nano libXt-devel tcp_wrappers + +WORKDIR /tmp/ +COPY ./imagefiles/install.sh ./ +COPY ./imagefiles/install-gcc.sh ./ +COPY ./imagefiles/install-libtiff.sh ./ + +RUN bash -v install-gcc.sh /usr/local && \ + bash -v install-libtiff.sh && \ + bash -v install.sh && \ + rm -rf /tmp/* + +# User is expected to mount directory to "/work" +ENTRYPOINT ["bash", "-c", "groupadd -o -g $_GROUPID $_USER && useradd -m -o -g $_GROUPID $_USER -u $_USERID && su $_USER /work/io/imagefiles/cmd.sh" ] + diff --git a/Wrapping/Python/PackageUtility/Dockerfile-x86_64_2 b/Wrapping/Python/PackageUtility/Dockerfile-x86_64_2 new file mode 100644 index 0000000000..8a0620b67b --- /dev/null +++ b/Wrapping/Python/PackageUtility/Dockerfile-x86_64_2 @@ -0,0 +1,12 @@ +FROM mitk_manylinux_x86_64 +MAINTAINER MITK.org + + +ENV http_proxy http://www-int2.dkfz-heidelberg.de:3128/ +ENV https_proxy https://www-int2.dkfz-heidelberg.de:3128/ + +WORKDIR /tmp/ + +# User is expected to mount directory to "/work" +ENTRYPOINT ["bash", "-c", "groupadd -o -g $_GROUPID $_USER && useradd -m -o -g $_GROUPID $_USER -u $_USERID && su $_USER /work/io/imagefiles/cmd.sh" ] + diff --git a/Wrapping/Python/PackageUtility/imagefiles/cmd.sh b/Wrapping/Python/PackageUtility/imagefiles/cmd.sh new file mode 100755 index 0000000000..d876ad6cfc --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/cmd.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +set -x + +export SRC_DIR="/tmp/mitk" +export BLD_DIR="/tmp/bin" +export OUT_DIR="/var/io" + +MITK_GIT_TAG=T24046-SwigBasedPythonWrapping + +PYTHON_VERSIONS=${PYTHON_VERSIONS:-$(ls /opt/python | sed -e 's/cp2[0-6][^ ]\+ \?//g')} + +NPROC=$(grep -c processor /proc/cpuinfo) +export MAKEFLAGS="-j ${NPROC}" + + +function build_mitk { + + echo "MITK_GIT_TAG: ${MITK_GIT_TAG}" + + git clone https://phabricator.mitk.org/source/mitk.git ${SRC_DIR} && + (cd ${SRC_DIR} && git checkout ${MITK_GIT_TAG} ) && + rm -rf ${BLD_DIR} && + mkdir -p ${BLD_DIR} && cd ${BLD_DIR} && + cmake \ + -DBUILD_TESTING:BOOL=OFF \ + -DMITK_USE_SWIG:BOOL=ON \ + -DMITK_USE_Qt5:BOOL=OFF \ + -DMITK_USE_CTK:BOOL=OFF \ + -DMITK_USE_BLUEBERRY:BOOL=OFF \ + -DCMAKE_C_COMPILER:FILEPATH=/usr/local/bin/gcc \ + -DCMAKE_CXX_COMPILER:FILEPATH=/usr/local/bin/g++ \ + -DMITK_WHITELIST:STRING=Wrapping \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + ${SRC_DIR} && + make -j8 +} + +function build_mitk_python { + + PYTHON_EXECUTABLE=/opt/python/${PYTHON}/bin/python + PYTHON_INCLUDE_DIR="$( find -L /opt/python/${PYTHON}/include/ -name Python.h -exec dirname {} \; )" + + echo "" + echo "PYTHON_EXECUTABLE:${PYTHON_EXECUTABLE}" + echo "PYTHON_INCLUDE_DIR:${PYTHON_INCLUDE_DIR}" + echo "PYTHON_LIBRARY:${PYTHON_LIBRARY}" + + cd ${BLD_DIR}/MITK-build && + cmake \ + -DWRAP_PYTHON:BOOL=ON \ + -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} \ + -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} \ + . + make dist -B +} + +build_mitk || exit 1 + + +for PYTHON in ${PYTHON_VERSIONS}; do + build_mitk_python && + auditwheel repair $(find ${BLD_DIR}/MITK-build/Wrapping/Python/dist -name pyMITK*.whl) -w ${OUT_DIR}/wheelhouse/ + rm $(find ${BLD_DIR}/MITK-build/Wrapping/Python/dist/ -name pyMITK*.whl) +done + diff --git a/Wrapping/Python/PackageUtility/imagefiles/imagefiles/cmd.sh b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/cmd.sh new file mode 100755 index 0000000000..d876ad6cfc --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/cmd.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +set -x + +export SRC_DIR="/tmp/mitk" +export BLD_DIR="/tmp/bin" +export OUT_DIR="/var/io" + +MITK_GIT_TAG=T24046-SwigBasedPythonWrapping + +PYTHON_VERSIONS=${PYTHON_VERSIONS:-$(ls /opt/python | sed -e 's/cp2[0-6][^ ]\+ \?//g')} + +NPROC=$(grep -c processor /proc/cpuinfo) +export MAKEFLAGS="-j ${NPROC}" + + +function build_mitk { + + echo "MITK_GIT_TAG: ${MITK_GIT_TAG}" + + git clone https://phabricator.mitk.org/source/mitk.git ${SRC_DIR} && + (cd ${SRC_DIR} && git checkout ${MITK_GIT_TAG} ) && + rm -rf ${BLD_DIR} && + mkdir -p ${BLD_DIR} && cd ${BLD_DIR} && + cmake \ + -DBUILD_TESTING:BOOL=OFF \ + -DMITK_USE_SWIG:BOOL=ON \ + -DMITK_USE_Qt5:BOOL=OFF \ + -DMITK_USE_CTK:BOOL=OFF \ + -DMITK_USE_BLUEBERRY:BOOL=OFF \ + -DCMAKE_C_COMPILER:FILEPATH=/usr/local/bin/gcc \ + -DCMAKE_CXX_COMPILER:FILEPATH=/usr/local/bin/g++ \ + -DMITK_WHITELIST:STRING=Wrapping \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + ${SRC_DIR} && + make -j8 +} + +function build_mitk_python { + + PYTHON_EXECUTABLE=/opt/python/${PYTHON}/bin/python + PYTHON_INCLUDE_DIR="$( find -L /opt/python/${PYTHON}/include/ -name Python.h -exec dirname {} \; )" + + echo "" + echo "PYTHON_EXECUTABLE:${PYTHON_EXECUTABLE}" + echo "PYTHON_INCLUDE_DIR:${PYTHON_INCLUDE_DIR}" + echo "PYTHON_LIBRARY:${PYTHON_LIBRARY}" + + cd ${BLD_DIR}/MITK-build && + cmake \ + -DWRAP_PYTHON:BOOL=ON \ + -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} \ + -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} \ + . + make dist -B +} + +build_mitk || exit 1 + + +for PYTHON in ${PYTHON_VERSIONS}; do + build_mitk_python && + auditwheel repair $(find ${BLD_DIR}/MITK-build/Wrapping/Python/dist -name pyMITK*.whl) -w ${OUT_DIR}/wheelhouse/ + rm $(find ${BLD_DIR}/MITK-build/Wrapping/Python/dist/ -name pyMITK*.whl) +done + diff --git a/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install-gcc.sh b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install-gcc.sh new file mode 100755 index 0000000000..b36458f281 --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install-gcc.sh @@ -0,0 +1,680 @@ +#!/bin/bash +# +# Date: 2015-09-29 +# +# This downloads, builds and installs the gcc-4.9.3 compiler and boost +# 1.58. It handles the dependent packages like gmp-6.0.0a, mpfr-3.1.3, +# mpc-1.0.2, ppl-1.1, cloog-0.18.0 and binutils-2.24. +# +# To install gcc-4.9.3 in ~/tmp/gcc-4.9.3/rtf/bin you would run this +# script as follows: +# +# % # Install in ~/tmp/gcc-4.9.3/rtf/bin +# % bld.sh ~/tmp/gcc-4.9.3 2>&1 | tee bld.log +# +# If you do not specify a directory, then it will install in the +# current directory which means that following command will also +# install in ~/tmp/gcc-4.9.3/rtf/bin: +# +# % # Install in ~/tmp/gcc-4.9.3/rtf/bin +# % mkdir -p ~/tmp/gcc-4.9.3 +# % cd ~/tmp/gcc-4.9.3 +# % bld.sh 2>&1 | tee bld.log +# +# This script creates 4 subdirectories: +# +# Directory Description +# ========= ================================================== +# archives This is where the package archives are downloaded. +# src This is where the package source is located. +# bld This is where the packages are built from source. +# rtf This is where the packages are installed. +# +# When the build is complete you can safely remove the archives, bld +# and src directory trees to save disk space. +# +# Copyright (C) 2014 Joe Linoff +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# ================================================================ +# Trim a string, remove internal spaces, convert to lower case. +# ================================================================ +function get-platform-trim { + local s=$(echo "$1" | tr -d '[ \t]' | tr 'A-Z' 'a-z') + echo $s +} + +# ================================================================ +# Get the platform root name. +# ================================================================ +function get-platform-root +{ + if which uname >/dev/null 2>&1 ; then + # Greg Moeller reported that the original code didn't + # work because the -o option is not available on solaris. + # I modified the script to correctly identify that + # case and recover by using the -s option. + if uname -o >/dev/null 2>&1 ; then + # Linux distro + uname -o | tr 'A-Z' 'a-z' + elif uname -s >/dev/null 2>&1 ; then + # Solaris variant + uname -s | tr 'A-Z' 'a-z' + else + echo "unkown" + fi + else + echo "unkown" + fi +} + +# ================================================================ +# Get the platform identifier. +# +# The format of the output is: +# --- +# ^ ^ ^ ^ +# | | | +----- architecture: x86_64, i86pc, etc. +# | | +----------- version: 5.5, 6.4, 10.9, etc. +# | +------------------ distribution: centos, rhel, nexenta, darwin +# +------------------------- platform: linux, sunos, macos +# +# ================================================================ +function get-platform +{ + local plat=$(get-platform-root) + case "$plat" in + "gnu/linux") + d=$(get-platform-trim "$(lsb_release -i)" | awk -F: '{print $2;}') + r=$(get-platform-trim "$(lsb_release -r)" | awk -F: '{print $2;}') + m=$(get-platform-trim "$(uname -m)") + if [[ "$d" == "redhatenterprise"* ]] ; then + # Need a little help for Red Hat because + # they don't make the minor version obvious. + d="rhel_${d:16}" # keep the tail (e.g., es or client) + x=$(get-platform-trim "$(lsb_release -c)" | \ + awk -F: '{print $2;}' | \ + sed -e 's/[^0-9]//g') + r="$r.$x" + fi + echo "linux-$d-$r-$m" + ;; + "cygwin") + x=$(get-platform-trim "$(uname)") + echo "linux-$x" + ;; + "sunos") + d=$(get-platform-trim "$(uname -v)") + r=$(get-platform-trim "$(uname -r)") + m=$(get-platform-trim "$(uname -m)") + echo "sunos-$d-$r-$m" + ;; + "darwin") + d=$(get-platform-trim "$(uname -s)") + r=$(get-platform-trim "$(uname -r)") + m=$(get-platform-trim "$(uname -m)") + echo "macos-$d-$r-$m" + ;; + "unknown") + echo "unk-unk-unk-unk" + ;; + *) + echo "$plat-unk-unk-unk" + ;; + esac +} + +# ================================================================ +# Command header +# Usage : docmd_hdr $ar $* +# Example: docmd_hdr $ar +# ================================================================ +function docmd_hdr { + local ar=$1 + shift + local cmd=($*) + echo + echo " # ================================================================" + if [[ "$ar" != "" ]] ; then + echo " # Archive: $ar" + fi + echo " # PWD: "$(pwd) + echo " # CMD: "${cmd[@]} + echo " # ================================================================" +} + +# ================================================================ +# Execute command with decorations and status testing. +# Usage : docmd $ar +# Example: docmd $ar ls -l +# ================================================================ +function docmd { + docmd_hdr $* + shift + local cmd=($*) + ${cmd[@]} + local st=$? + echo "STATUS = $st" + if (( $st != 0 )) ; then + exit $st; + fi +} + +# ================================================================ +# Report an error and exit. +# Usage : doerr [ .. ] +# Example: doerr "line 1 msg" +# Example: doerr "line 1 msg" "line 2 msg" +# ================================================================ +function doerr { + local prefix="ERROR: " + for ln in "$@" ; do + echo "${prefix}${ln}" + prefix=" " + done + exit 1 +} + +# ================================================================ +# Extract archive information. +# Usage : ard=( $(extract-ar-info $ar) ) +# Example: ard=( $(extract-ar-info $ar) ) +# fn=${ard[1]} +# ext=${ard[2]} +# d=${ard[3]} +# ================================================================ +function extract-ar-info { + local ar=$1 + local fn=$(basename $ar) + local ext=$(echo $fn | awk -F. '{print $NF}') + local d=${fn%.*tar.$ext} + echo $ar + echo $fn + echo $ext + echo $d +} + +# ================================================================ +# Print a banner for a new section. +# Usage : banner STEP $ar +# Example: banner "DOWNLOAD" $ar +# Example: banner "BUILD" $ar +# ================================================================ +function banner { + local step=$1 + local ard=( $(extract-ar-info $2) ) + local ar=${ard[0]} + local fn=${ard[1]} + local ext=${ard[2]} + local d=${ard[3]} + echo + echo '# ================================================================' + echo "# Step : $step" + echo "# Archive: $ar" + echo "# File : $fn" + echo "# Ext : $ext" + echo "# Dir : $d" + echo '# ================================================================' +} + +# ================================================================ +# Make a set of directories +# Usage : mkdirs [ .. ] +# Example: mkdirs foo bar spam spam/foo/bar +# ================================================================ +function mkdirs { + local ds=($*) + #echo "mkdirs" + for d in ${ds[@]} ; do + #echo " testing $d" + if [ ! -d $d ] ; then + #echo " creating $d" + mkdir -p $d + fi + done +} + +# ================================================================ +# Check the current platform to see if it is in the tested list, +# if it isn't, then issue a warning. +# It doesn't work on CentOS 5.x. +# It doesn't work on Mac OS X 10.9 (Maverick) but is close. +# ================================================================ +function check-platform +{ + local plat=$(get-platform) + local tested_plats=( + 'linux-centos-6.4-x86_64') + local plat_found=0 + + echo "PLATFORM: $plat" + for tested_plat in ${tested_plats[@]} ; do + if [[ "$plat" == "$tested_plat" ]] ; then + plat_found=1 + break + fi + done + if (( $plat_found == 0 )) ; then + echo "WARNING: This platform ($plat) has not been tested." + fi +} + +# ================================================================ +# my-readlink +# Some platforms (like darwin) do not support "readlink -f". +# This function checks to see if readlink -f is available, +# if it isn't then it uses a more POSIX compliant approach. +# ================================================================ +function my-readlink +{ + # First make sure that the command works. + readlink -f "$1" 1>/dev/null 2>/dev/null + local st=$? + if (( $st )) ; then + # If readlink didn't work then this may be a platform + # like Mac OS X. + local abspath="$(cd $(dirname .); pwd)" + else + local abspath=$(readlink -f "$1" 2>/dev/null) + fi + echo "$abspath" +} + +# ================================================================ +# DATA +# ================================================================ +# List of archives +# The order is important. +ARS=( + http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz + https://gmplib.org/download/gmp/gmp-6.0.0a.tar.bz2 + http://www.mpfr.org/mpfr-current/mpfr-3.1.3.tar.bz2 + http://www.multiprecision.org/mpc/download/mpc-1.0.2.tar.gz + http://bugseng.com/products/ppl/download/ftp/releases/1.1/ppl-1.1.tar.bz2 + http://www.bastoul.net/cloog/pages/download/cloog-0.18.1.tar.gz + http://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.bz2 + http://ftp.gnu.org/gnu/binutils/binutils-2.24.tar.bz2 + #http://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.bz2 + # + # Why glibc is disabled (for now). + # + # glibc does not work on CentOS because the versions of the shared + # libraries we are building are not compatiable with installed + # shared libraries. + # + # This is the run-time error: ELF file OS ABI invalid that I see + # when I try to run binaries compiled with the local glibc-2.15. + # + # Note that the oldest supported ABI for glibc-2.15 is 2.2. The + # CentOS 5.5 ABI is 0. + # http://ftp.gnu.org/gnu/glibc/glibc-2.15.tar.bz2 +) + +# ================================================================ +# MAIN +# ================================================================ +umask 0 + +check-platform + +# Read the command line argument, if it exists. +ROOTDIR=$(my-readlink .) +if (( $# == 1 )) ; then + ROOTDIR=$(my-readlink $1) +elif (( $# > 1 )) ; then + doerr "too many command line arguments ($#), only zero or one is allowed" "foo" +fi + +# Setup the directories. +ARDIR="/tmp/archives" +RTFDIR="$ROOTDIR" +SRCDIR="/tmp/src" +BLDDIR="/tmp/bld" +TSTDIR="/tmp/LOCAL-TEST" + +export PATH="${RTFDIR}/bin:${PATH}" +export LD_LIBRARY_PATH="${RTFDIR}/lib:${RTFDIR}/lib64:${LD_LIBRARY_PATH}" + +echo +echo "# ================================================================" +echo '# Version : gcc-4.9.3 2015-08-15' +echo "# RootDir : $ROOTDIR" +echo "# ArchiveDir : $ARDIR" +echo "# RtfDir : $RTFDIR" +echo "# SrcDir : $SRCDIR" +echo "# BldDir : $BLDDIR" +echo "# TstDir : $TSTDIR" +echo "# Gcc : "$(which gcc) +echo "# GccVersion : "$(gcc --version | head -1) +echo "# Hostname : "$(hostname) +echo "# O/S : "$(uname -s -r -v -m) +echo "# Date : "$(date) +echo "# Platform : "$(get-platform) +echo "# ================================================================" + +mkdirs $ARDIR $RTFDIR $SRCDIR $BLDDIR + +# ================================================================ +# Download +# ================================================================ +#for ar in ${ARS[@]} ; do +# banner 'DOWNLOAD' $ar +# ard=( $(extract-ar-info $ar) ) +# fn=${ard[1]} +# ext=${ard[2]} +# d=${ard[3]} +# if [ -f "${ARDIR}/$fn" ] ; then +# echo "skipping $fn" +# else +# # get +# docmd $ar wget $ar -O "${ARDIR}/$fn" +# fi +#done + +# ================================================================ +# Extract +# ================================================================ +for ar in ${ARS[@]} ; do + banner 'EXTRACT' $ar + ard=( $(extract-ar-info $ar) ) + fn=${ard[1]} + ext=${ard[2]} + d=${ard[3]} + sd="$SRCDIR/$d" + if [ -d $sd ] ; then + echo "skipping $fn" + else + # unpack + pushd $SRCDIR + case "$ext" in + "bz2") + docmd $ar tar jxf ${ARDIR}/$fn + ;; + "gz") + docmd $ar tar zxf ${ARDIR}/$fn + ;; + "tar") + docmd $ar tar xf ${ARDIR}/$fn + ;; + *) + doerr "unrecognized extension: $ext" "Can't continue." + ;; + esac + popd + if [ ! -d $sd ] ; then + # Some archives (like gcc-g++) overlay. We create a dummy + # directory to avoid extracting them every time. + mkdir -p $sd + fi + fi + + # special hack for gmp-6.0.0a + if [[ $d == "gmp-6.0.0a" ]] ; then + if [ ! -f $sd/configure ] ; then + sdn="$SRCDIR/gmp-6.0.0" + echo "fixing $sdn --> $sd" + docmd $sd rm -rf $sd + docmd $sd ln -s $sdn $sd + fi + fi +done + +# ================================================================ +# Build +# ================================================================ +for ar in ${ARS[@]} ; do + banner 'BUILD' $ar + ard=( $(extract-ar-info $ar) ) + fn=${ard[1]} + ext=${ard[2]} + d=${ard[3]} + sd="$SRCDIR/$d" + bd="$BLDDIR/$d" + if [ -d $bd ] ; then + echo "skipping $sd" + else + # Build + regex='^gcc-g\+\+.*' + if [[ $fn =~ $regex ]] ; then + # Don't build/configure the gcc-g++ package explicitly because + # it is part of the regular gcc package. + echo "skipping $sd" + # Dummy + continue + fi + + # Set the CONF_ARGS + plat=$(get-platform) + run_conf=1 + run_boost_bootstrap=0 + case "$d" in + binutils-*) + # Binutils will not compile with strict error + # checking on so I disabled -Werror by setting + # --disable-werror. + CONF_ARGS=( + --disable-cloog-version-check + --disable-ppl-version-check + --disable-werror + --enable-cloog-backend=isl + --enable-lto + --enable-libssp + --enable-gold + --prefix=${RTFDIR} + --with-cloog=${RTFDIR} + --with-gmp=${RTFDIR} + --with-mlgmp=${RTFDIR} + --with-mpc=${RTFDIR} + --with-mpfr=${RTFDIR} + --with-ppl=${RTFDIR} + CC=${RTFDIR}/bin/gcc + CXX=${RTFDIR}/bin/g++ + ) + ;; + + boost_*) + # The boost configuration scheme requires + # that the build occur in the source directory. + run_conf=0 + run_boost_bootstrap=1 + CONF_ARGS=( + --prefix=${RTFDIR} + --with-python=python2.7 + ) + ;; + + cloog-*) + GMPDIR=$(ls -1d ${BLDDIR}/gmp-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp-builddir=${GMPDIR} + --with-gmp=build + ) + ;; + + gcc-*) + # We are using a newer version of CLooG (0.18.0). + # I have also made stack protection available + # (similar to DEP in windows). + CONF_ARGS=( + --disable-cloog-version-check + --disable-ppl-version-check + --enable-cloog-backend=isl + --enable-gold + --enable-languages='c,c++' + --enable-lto + --enable-libssp + --prefix=${RTFDIR} + --with-cloog=${RTFDIR} + --with-gmp=${RTFDIR} + --with-mlgmp=${RTFDIR} + --with-mpc=${RTFDIR} + --with-mpfr=${RTFDIR} + --with-ppl=${RTFDIR} + ) + + macplats=("macos-darwin-13.0.0-x86_64" "macos-darwin-13.1.0-x86_64") + for macplat in ${macplats[@]} ; do + if [[ "$plat" == "$macplat" ]] ; then + # Special handling for Mac OS X 10.9. + # Fix the bad reference to CFBase.h in + # src/gcc-4.9.3/libsanitizer/asan/asan_malloc_mac.cc + src="$sd/libsanitizer/asan/asan_malloc_mac.cc" + if [ -f $src ] ; then + if [ ! -f $src.orig ] ; then + cp $src $src.orig + cat $src.orig |\ + sed -e 's@#include @//#include @' >$src + fi + fi + fi + done + ;; + + glibc-*) + CONF_ARGS=( + --enable-static-nss=no + --prefix=${RTFDIR} + --with-binutils=${RTFDIR} + --with-elf + CC=${RTFDIR}/bin/gcc + CXX=${RTFDIR}/bin/g++ + ) + ;; + + gmp-*) + CONF_ARGS=( + --enable-cxx + --prefix=${RTFDIR} + ) + if [[ "$plat" == "linux-cygwin_nt-6.1-wow64" ]] ; then + CONF_ARGS+=('--enable-static') + CONF_ARGS+=('--disable-shared') + fi + ;; + + libiconv-*) + CONF_ARGS=( + --prefix=${RTFDIR} + ) + ;; + + mpc-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp=${RTFDIR} + --with-mpfr=${RTFDIR} + ) + if [[ "$plat" == "linux-cygwin_nt-6.1-wow64" ]] ; then + CONF_ARGS+=('--enable-static') + CONF_ARGS+=('--disable-shared') + fi + ;; + + mpfr-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp=${RTFDIR} + ) + ;; + + ppl-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp=${RTFDIR} + ) + if [[ "$plat" == "linux-cygwin_nt-6.1-wow64" ]] ; then + # Cygwin does not implement long double so I cheated. + CONF_ARGS+=('--enable-static') + CONF_ARGS+=('--disable-shared') + fi + + # We need a special fix for the pax archive prompt. + # Change the configure code. + if [ ! -f "$sd/configure.orig" ] ; then + # Fix the configure code so that it does not use 'pax -r'. + # The problem with 'pax -r' is that it expects a "." input + # from stdin which breaks the flow. + cp $sd/configure{,.orig} + sed -e "s/am__untar='pax -r'/am__untar='tar -xf' #am__untar='pax -r'/" \ + $sd/configure.orig >$sd/configure + fi + + # We need to make a special fix here + src="$sd/src/mp_std_bits.defs.hh" + if [ -f $src ] ; then + if [ ! -f $src.orig ] ; then + if ! grep -q '__GNU_MP_VERSION' $src ; then + cp $src $src.orig + cat $src.orig | \ + awk \ +'{ \ + if($1=="namespace" && $2 == "std") { \ + printf("// Automatically patched by bld.sh for gcc-4.9.3.\n"); \ + printf("#define tininess_before tinyness_before\n"); \ + printf("#if __GNU_MP_VERSION < 5 || (__GNU_MP_VERSION == 5 && __GNU_MP_VERSION_MINOR < 1)\n"); + } \ + print $0; \ + if($1 == "}" && $2=="//" && $3=="namespace") { \ + printf("#endif // #if __GNU_MP_VERSION < 5 || (__GNU_MP_VERSION == 5 && __GNU_MP_VERSION_MINOR < 1)\n"); + } \ +}' >$src + fi + fi + fi + ;; + + *) + doerr "unrecognized package: $d" + ;; + esac + + mkdir -p $bd + pushd $bd + if (( $run_conf )) ; then + docmd $ar $sd/configure --help + docmd $ar $sd/configure ${CONF_ARGS[@]} + docmd $ar make + docmd $ar make install + fi + if (( $run_boost_bootstrap )) ; then + pushd $sd + docmd $ar which g++ + docmd $ar gcc --version + docmd $ar $sd/bootstrap.sh --help + docmd $ar $sd/bootstrap.sh ${CONF_ARGS[@]} + docmd $ar ./b2 --help + docmd $ar ./b2 --clean + docmd $ar ./b2 --reconfigure + docmd $ar ./b2 -a -d+2 --build-dir $bd + docmd $ar ./b2 -d+2 --build-dir $bd install + docmd $ar ./b2 install + popd + fi + + # Redo the tests if anything changed. + if [ -d $TSTDIR ] ; then + rm -rf $TSTDIR + fi + popd + fi +done diff --git a/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install-libtiff.sh b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install-libtiff.sh new file mode 100755 index 0000000000..efd0520a98 --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install-libtiff.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd /tmp/archive +tar -xzf tiff-4.0.9.tar.gz -C /tmp/ +cd /tmp/tiff-4.0.9 +./configure CC=/usr/local/bin/gcc CXX=/usr/local/bin/g++ +make +make install diff --git a/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install.sh b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install.sh new file mode 100755 index 0000000000..f01d53b9db --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/imagefiles/install.sh @@ -0,0 +1,70 @@ +NPROC=$(grep -c processor /proc/cpuinfo) + +export MAKEFLAGS="-j ${NPROC}" + +OPENSSL_ROOT=openssl-1.0.2h +OPENSSL_HASH=1d4007e53aad94a5b2002fe045ee7bb0b3d98f1a47f8b2bc851dcd1c74332919 +CMAKE_ROOT=cmake-3.7.2 + +function check_var { + if [ -z "$1" ]; then + echo "required variable not defined" + exit 1 + fi +} + +function do_openssl_build { + + ./config no-ssl2 no-shared -fPIC --prefix=/usr/local/ssl && + MAKEFLAGS="" make && + MAKEFLAGS="" make install +} + +function check_sha256sum { + local fname=$1 + check_var ${fname} + local sha256=$2 + check_var ${sha256} + + echo "${sha256} ${fname}" > ${fname}.sha256 + sha256sum -c ${fname}.sha256 + rm -f ${fname}.sha256 +} + + +function build_openssl { + local openssl_fname=$1 + check_var ${openssl_fname} + local openssl_sha256=$2 + check_var ${openssl_sha256} && + check_sha256sum ${openssl_fname}.tar.gz ${openssl_sha256} && + tar -xzf ${openssl_fname}.tar.gz && + (cd ${openssl_fname} && do_openssl_build) && + rm -rf ${openssl_fname} ${openssl_fname}.tar.gz +} + +build_openssl $OPENSSL_ROOT $OPENSSL_HASH || exit 1 + +tar xvzf ${CMAKE_ROOT}.tar.gz && +mkdir /tmp/cmake-build && +(cd /tmp/cmake-build && + ../${CMAKE_ROOT}/bootstrap --parallel=${NPROC} -- \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DCMAKE_USE_OPENSSL:BOOL=ON \ + -DOPENSSL_ROOT_DIR:PATH=/usr/local/ssl \ + -DCMAKE_USE_SYSTEM_CURL:BOOL=OFF && + make && + make install) || +exit 1 + +rm -rf /usr/local/ssl + +sed -i -e 's/3.4.8"/3.4.8","3.4.9"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.10"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.11"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.12"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.13"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.14"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.15"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.16"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.17"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json diff --git a/Wrapping/Python/PackageUtility/imagefiles/install-gcc.sh b/Wrapping/Python/PackageUtility/imagefiles/install-gcc.sh new file mode 100755 index 0000000000..b36458f281 --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/install-gcc.sh @@ -0,0 +1,680 @@ +#!/bin/bash +# +# Date: 2015-09-29 +# +# This downloads, builds and installs the gcc-4.9.3 compiler and boost +# 1.58. It handles the dependent packages like gmp-6.0.0a, mpfr-3.1.3, +# mpc-1.0.2, ppl-1.1, cloog-0.18.0 and binutils-2.24. +# +# To install gcc-4.9.3 in ~/tmp/gcc-4.9.3/rtf/bin you would run this +# script as follows: +# +# % # Install in ~/tmp/gcc-4.9.3/rtf/bin +# % bld.sh ~/tmp/gcc-4.9.3 2>&1 | tee bld.log +# +# If you do not specify a directory, then it will install in the +# current directory which means that following command will also +# install in ~/tmp/gcc-4.9.3/rtf/bin: +# +# % # Install in ~/tmp/gcc-4.9.3/rtf/bin +# % mkdir -p ~/tmp/gcc-4.9.3 +# % cd ~/tmp/gcc-4.9.3 +# % bld.sh 2>&1 | tee bld.log +# +# This script creates 4 subdirectories: +# +# Directory Description +# ========= ================================================== +# archives This is where the package archives are downloaded. +# src This is where the package source is located. +# bld This is where the packages are built from source. +# rtf This is where the packages are installed. +# +# When the build is complete you can safely remove the archives, bld +# and src directory trees to save disk space. +# +# Copyright (C) 2014 Joe Linoff +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# ================================================================ +# Trim a string, remove internal spaces, convert to lower case. +# ================================================================ +function get-platform-trim { + local s=$(echo "$1" | tr -d '[ \t]' | tr 'A-Z' 'a-z') + echo $s +} + +# ================================================================ +# Get the platform root name. +# ================================================================ +function get-platform-root +{ + if which uname >/dev/null 2>&1 ; then + # Greg Moeller reported that the original code didn't + # work because the -o option is not available on solaris. + # I modified the script to correctly identify that + # case and recover by using the -s option. + if uname -o >/dev/null 2>&1 ; then + # Linux distro + uname -o | tr 'A-Z' 'a-z' + elif uname -s >/dev/null 2>&1 ; then + # Solaris variant + uname -s | tr 'A-Z' 'a-z' + else + echo "unkown" + fi + else + echo "unkown" + fi +} + +# ================================================================ +# Get the platform identifier. +# +# The format of the output is: +# --- +# ^ ^ ^ ^ +# | | | +----- architecture: x86_64, i86pc, etc. +# | | +----------- version: 5.5, 6.4, 10.9, etc. +# | +------------------ distribution: centos, rhel, nexenta, darwin +# +------------------------- platform: linux, sunos, macos +# +# ================================================================ +function get-platform +{ + local plat=$(get-platform-root) + case "$plat" in + "gnu/linux") + d=$(get-platform-trim "$(lsb_release -i)" | awk -F: '{print $2;}') + r=$(get-platform-trim "$(lsb_release -r)" | awk -F: '{print $2;}') + m=$(get-platform-trim "$(uname -m)") + if [[ "$d" == "redhatenterprise"* ]] ; then + # Need a little help for Red Hat because + # they don't make the minor version obvious. + d="rhel_${d:16}" # keep the tail (e.g., es or client) + x=$(get-platform-trim "$(lsb_release -c)" | \ + awk -F: '{print $2;}' | \ + sed -e 's/[^0-9]//g') + r="$r.$x" + fi + echo "linux-$d-$r-$m" + ;; + "cygwin") + x=$(get-platform-trim "$(uname)") + echo "linux-$x" + ;; + "sunos") + d=$(get-platform-trim "$(uname -v)") + r=$(get-platform-trim "$(uname -r)") + m=$(get-platform-trim "$(uname -m)") + echo "sunos-$d-$r-$m" + ;; + "darwin") + d=$(get-platform-trim "$(uname -s)") + r=$(get-platform-trim "$(uname -r)") + m=$(get-platform-trim "$(uname -m)") + echo "macos-$d-$r-$m" + ;; + "unknown") + echo "unk-unk-unk-unk" + ;; + *) + echo "$plat-unk-unk-unk" + ;; + esac +} + +# ================================================================ +# Command header +# Usage : docmd_hdr $ar $* +# Example: docmd_hdr $ar +# ================================================================ +function docmd_hdr { + local ar=$1 + shift + local cmd=($*) + echo + echo " # ================================================================" + if [[ "$ar" != "" ]] ; then + echo " # Archive: $ar" + fi + echo " # PWD: "$(pwd) + echo " # CMD: "${cmd[@]} + echo " # ================================================================" +} + +# ================================================================ +# Execute command with decorations and status testing. +# Usage : docmd $ar +# Example: docmd $ar ls -l +# ================================================================ +function docmd { + docmd_hdr $* + shift + local cmd=($*) + ${cmd[@]} + local st=$? + echo "STATUS = $st" + if (( $st != 0 )) ; then + exit $st; + fi +} + +# ================================================================ +# Report an error and exit. +# Usage : doerr [ .. ] +# Example: doerr "line 1 msg" +# Example: doerr "line 1 msg" "line 2 msg" +# ================================================================ +function doerr { + local prefix="ERROR: " + for ln in "$@" ; do + echo "${prefix}${ln}" + prefix=" " + done + exit 1 +} + +# ================================================================ +# Extract archive information. +# Usage : ard=( $(extract-ar-info $ar) ) +# Example: ard=( $(extract-ar-info $ar) ) +# fn=${ard[1]} +# ext=${ard[2]} +# d=${ard[3]} +# ================================================================ +function extract-ar-info { + local ar=$1 + local fn=$(basename $ar) + local ext=$(echo $fn | awk -F. '{print $NF}') + local d=${fn%.*tar.$ext} + echo $ar + echo $fn + echo $ext + echo $d +} + +# ================================================================ +# Print a banner for a new section. +# Usage : banner STEP $ar +# Example: banner "DOWNLOAD" $ar +# Example: banner "BUILD" $ar +# ================================================================ +function banner { + local step=$1 + local ard=( $(extract-ar-info $2) ) + local ar=${ard[0]} + local fn=${ard[1]} + local ext=${ard[2]} + local d=${ard[3]} + echo + echo '# ================================================================' + echo "# Step : $step" + echo "# Archive: $ar" + echo "# File : $fn" + echo "# Ext : $ext" + echo "# Dir : $d" + echo '# ================================================================' +} + +# ================================================================ +# Make a set of directories +# Usage : mkdirs [ .. ] +# Example: mkdirs foo bar spam spam/foo/bar +# ================================================================ +function mkdirs { + local ds=($*) + #echo "mkdirs" + for d in ${ds[@]} ; do + #echo " testing $d" + if [ ! -d $d ] ; then + #echo " creating $d" + mkdir -p $d + fi + done +} + +# ================================================================ +# Check the current platform to see if it is in the tested list, +# if it isn't, then issue a warning. +# It doesn't work on CentOS 5.x. +# It doesn't work on Mac OS X 10.9 (Maverick) but is close. +# ================================================================ +function check-platform +{ + local plat=$(get-platform) + local tested_plats=( + 'linux-centos-6.4-x86_64') + local plat_found=0 + + echo "PLATFORM: $plat" + for tested_plat in ${tested_plats[@]} ; do + if [[ "$plat" == "$tested_plat" ]] ; then + plat_found=1 + break + fi + done + if (( $plat_found == 0 )) ; then + echo "WARNING: This platform ($plat) has not been tested." + fi +} + +# ================================================================ +# my-readlink +# Some platforms (like darwin) do not support "readlink -f". +# This function checks to see if readlink -f is available, +# if it isn't then it uses a more POSIX compliant approach. +# ================================================================ +function my-readlink +{ + # First make sure that the command works. + readlink -f "$1" 1>/dev/null 2>/dev/null + local st=$? + if (( $st )) ; then + # If readlink didn't work then this may be a platform + # like Mac OS X. + local abspath="$(cd $(dirname .); pwd)" + else + local abspath=$(readlink -f "$1" 2>/dev/null) + fi + echo "$abspath" +} + +# ================================================================ +# DATA +# ================================================================ +# List of archives +# The order is important. +ARS=( + http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz + https://gmplib.org/download/gmp/gmp-6.0.0a.tar.bz2 + http://www.mpfr.org/mpfr-current/mpfr-3.1.3.tar.bz2 + http://www.multiprecision.org/mpc/download/mpc-1.0.2.tar.gz + http://bugseng.com/products/ppl/download/ftp/releases/1.1/ppl-1.1.tar.bz2 + http://www.bastoul.net/cloog/pages/download/cloog-0.18.1.tar.gz + http://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.bz2 + http://ftp.gnu.org/gnu/binutils/binutils-2.24.tar.bz2 + #http://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.bz2 + # + # Why glibc is disabled (for now). + # + # glibc does not work on CentOS because the versions of the shared + # libraries we are building are not compatiable with installed + # shared libraries. + # + # This is the run-time error: ELF file OS ABI invalid that I see + # when I try to run binaries compiled with the local glibc-2.15. + # + # Note that the oldest supported ABI for glibc-2.15 is 2.2. The + # CentOS 5.5 ABI is 0. + # http://ftp.gnu.org/gnu/glibc/glibc-2.15.tar.bz2 +) + +# ================================================================ +# MAIN +# ================================================================ +umask 0 + +check-platform + +# Read the command line argument, if it exists. +ROOTDIR=$(my-readlink .) +if (( $# == 1 )) ; then + ROOTDIR=$(my-readlink $1) +elif (( $# > 1 )) ; then + doerr "too many command line arguments ($#), only zero or one is allowed" "foo" +fi + +# Setup the directories. +ARDIR="/tmp/archives" +RTFDIR="$ROOTDIR" +SRCDIR="/tmp/src" +BLDDIR="/tmp/bld" +TSTDIR="/tmp/LOCAL-TEST" + +export PATH="${RTFDIR}/bin:${PATH}" +export LD_LIBRARY_PATH="${RTFDIR}/lib:${RTFDIR}/lib64:${LD_LIBRARY_PATH}" + +echo +echo "# ================================================================" +echo '# Version : gcc-4.9.3 2015-08-15' +echo "# RootDir : $ROOTDIR" +echo "# ArchiveDir : $ARDIR" +echo "# RtfDir : $RTFDIR" +echo "# SrcDir : $SRCDIR" +echo "# BldDir : $BLDDIR" +echo "# TstDir : $TSTDIR" +echo "# Gcc : "$(which gcc) +echo "# GccVersion : "$(gcc --version | head -1) +echo "# Hostname : "$(hostname) +echo "# O/S : "$(uname -s -r -v -m) +echo "# Date : "$(date) +echo "# Platform : "$(get-platform) +echo "# ================================================================" + +mkdirs $ARDIR $RTFDIR $SRCDIR $BLDDIR + +# ================================================================ +# Download +# ================================================================ +#for ar in ${ARS[@]} ; do +# banner 'DOWNLOAD' $ar +# ard=( $(extract-ar-info $ar) ) +# fn=${ard[1]} +# ext=${ard[2]} +# d=${ard[3]} +# if [ -f "${ARDIR}/$fn" ] ; then +# echo "skipping $fn" +# else +# # get +# docmd $ar wget $ar -O "${ARDIR}/$fn" +# fi +#done + +# ================================================================ +# Extract +# ================================================================ +for ar in ${ARS[@]} ; do + banner 'EXTRACT' $ar + ard=( $(extract-ar-info $ar) ) + fn=${ard[1]} + ext=${ard[2]} + d=${ard[3]} + sd="$SRCDIR/$d" + if [ -d $sd ] ; then + echo "skipping $fn" + else + # unpack + pushd $SRCDIR + case "$ext" in + "bz2") + docmd $ar tar jxf ${ARDIR}/$fn + ;; + "gz") + docmd $ar tar zxf ${ARDIR}/$fn + ;; + "tar") + docmd $ar tar xf ${ARDIR}/$fn + ;; + *) + doerr "unrecognized extension: $ext" "Can't continue." + ;; + esac + popd + if [ ! -d $sd ] ; then + # Some archives (like gcc-g++) overlay. We create a dummy + # directory to avoid extracting them every time. + mkdir -p $sd + fi + fi + + # special hack for gmp-6.0.0a + if [[ $d == "gmp-6.0.0a" ]] ; then + if [ ! -f $sd/configure ] ; then + sdn="$SRCDIR/gmp-6.0.0" + echo "fixing $sdn --> $sd" + docmd $sd rm -rf $sd + docmd $sd ln -s $sdn $sd + fi + fi +done + +# ================================================================ +# Build +# ================================================================ +for ar in ${ARS[@]} ; do + banner 'BUILD' $ar + ard=( $(extract-ar-info $ar) ) + fn=${ard[1]} + ext=${ard[2]} + d=${ard[3]} + sd="$SRCDIR/$d" + bd="$BLDDIR/$d" + if [ -d $bd ] ; then + echo "skipping $sd" + else + # Build + regex='^gcc-g\+\+.*' + if [[ $fn =~ $regex ]] ; then + # Don't build/configure the gcc-g++ package explicitly because + # it is part of the regular gcc package. + echo "skipping $sd" + # Dummy + continue + fi + + # Set the CONF_ARGS + plat=$(get-platform) + run_conf=1 + run_boost_bootstrap=0 + case "$d" in + binutils-*) + # Binutils will not compile with strict error + # checking on so I disabled -Werror by setting + # --disable-werror. + CONF_ARGS=( + --disable-cloog-version-check + --disable-ppl-version-check + --disable-werror + --enable-cloog-backend=isl + --enable-lto + --enable-libssp + --enable-gold + --prefix=${RTFDIR} + --with-cloog=${RTFDIR} + --with-gmp=${RTFDIR} + --with-mlgmp=${RTFDIR} + --with-mpc=${RTFDIR} + --with-mpfr=${RTFDIR} + --with-ppl=${RTFDIR} + CC=${RTFDIR}/bin/gcc + CXX=${RTFDIR}/bin/g++ + ) + ;; + + boost_*) + # The boost configuration scheme requires + # that the build occur in the source directory. + run_conf=0 + run_boost_bootstrap=1 + CONF_ARGS=( + --prefix=${RTFDIR} + --with-python=python2.7 + ) + ;; + + cloog-*) + GMPDIR=$(ls -1d ${BLDDIR}/gmp-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp-builddir=${GMPDIR} + --with-gmp=build + ) + ;; + + gcc-*) + # We are using a newer version of CLooG (0.18.0). + # I have also made stack protection available + # (similar to DEP in windows). + CONF_ARGS=( + --disable-cloog-version-check + --disable-ppl-version-check + --enable-cloog-backend=isl + --enable-gold + --enable-languages='c,c++' + --enable-lto + --enable-libssp + --prefix=${RTFDIR} + --with-cloog=${RTFDIR} + --with-gmp=${RTFDIR} + --with-mlgmp=${RTFDIR} + --with-mpc=${RTFDIR} + --with-mpfr=${RTFDIR} + --with-ppl=${RTFDIR} + ) + + macplats=("macos-darwin-13.0.0-x86_64" "macos-darwin-13.1.0-x86_64") + for macplat in ${macplats[@]} ; do + if [[ "$plat" == "$macplat" ]] ; then + # Special handling for Mac OS X 10.9. + # Fix the bad reference to CFBase.h in + # src/gcc-4.9.3/libsanitizer/asan/asan_malloc_mac.cc + src="$sd/libsanitizer/asan/asan_malloc_mac.cc" + if [ -f $src ] ; then + if [ ! -f $src.orig ] ; then + cp $src $src.orig + cat $src.orig |\ + sed -e 's@#include @//#include @' >$src + fi + fi + fi + done + ;; + + glibc-*) + CONF_ARGS=( + --enable-static-nss=no + --prefix=${RTFDIR} + --with-binutils=${RTFDIR} + --with-elf + CC=${RTFDIR}/bin/gcc + CXX=${RTFDIR}/bin/g++ + ) + ;; + + gmp-*) + CONF_ARGS=( + --enable-cxx + --prefix=${RTFDIR} + ) + if [[ "$plat" == "linux-cygwin_nt-6.1-wow64" ]] ; then + CONF_ARGS+=('--enable-static') + CONF_ARGS+=('--disable-shared') + fi + ;; + + libiconv-*) + CONF_ARGS=( + --prefix=${RTFDIR} + ) + ;; + + mpc-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp=${RTFDIR} + --with-mpfr=${RTFDIR} + ) + if [[ "$plat" == "linux-cygwin_nt-6.1-wow64" ]] ; then + CONF_ARGS+=('--enable-static') + CONF_ARGS+=('--disable-shared') + fi + ;; + + mpfr-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp=${RTFDIR} + ) + ;; + + ppl-*) + CONF_ARGS=( + --prefix=${RTFDIR} + --with-gmp=${RTFDIR} + ) + if [[ "$plat" == "linux-cygwin_nt-6.1-wow64" ]] ; then + # Cygwin does not implement long double so I cheated. + CONF_ARGS+=('--enable-static') + CONF_ARGS+=('--disable-shared') + fi + + # We need a special fix for the pax archive prompt. + # Change the configure code. + if [ ! -f "$sd/configure.orig" ] ; then + # Fix the configure code so that it does not use 'pax -r'. + # The problem with 'pax -r' is that it expects a "." input + # from stdin which breaks the flow. + cp $sd/configure{,.orig} + sed -e "s/am__untar='pax -r'/am__untar='tar -xf' #am__untar='pax -r'/" \ + $sd/configure.orig >$sd/configure + fi + + # We need to make a special fix here + src="$sd/src/mp_std_bits.defs.hh" + if [ -f $src ] ; then + if [ ! -f $src.orig ] ; then + if ! grep -q '__GNU_MP_VERSION' $src ; then + cp $src $src.orig + cat $src.orig | \ + awk \ +'{ \ + if($1=="namespace" && $2 == "std") { \ + printf("// Automatically patched by bld.sh for gcc-4.9.3.\n"); \ + printf("#define tininess_before tinyness_before\n"); \ + printf("#if __GNU_MP_VERSION < 5 || (__GNU_MP_VERSION == 5 && __GNU_MP_VERSION_MINOR < 1)\n"); + } \ + print $0; \ + if($1 == "}" && $2=="//" && $3=="namespace") { \ + printf("#endif // #if __GNU_MP_VERSION < 5 || (__GNU_MP_VERSION == 5 && __GNU_MP_VERSION_MINOR < 1)\n"); + } \ +}' >$src + fi + fi + fi + ;; + + *) + doerr "unrecognized package: $d" + ;; + esac + + mkdir -p $bd + pushd $bd + if (( $run_conf )) ; then + docmd $ar $sd/configure --help + docmd $ar $sd/configure ${CONF_ARGS[@]} + docmd $ar make + docmd $ar make install + fi + if (( $run_boost_bootstrap )) ; then + pushd $sd + docmd $ar which g++ + docmd $ar gcc --version + docmd $ar $sd/bootstrap.sh --help + docmd $ar $sd/bootstrap.sh ${CONF_ARGS[@]} + docmd $ar ./b2 --help + docmd $ar ./b2 --clean + docmd $ar ./b2 --reconfigure + docmd $ar ./b2 -a -d+2 --build-dir $bd + docmd $ar ./b2 -d+2 --build-dir $bd install + docmd $ar ./b2 install + popd + fi + + # Redo the tests if anything changed. + if [ -d $TSTDIR ] ; then + rm -rf $TSTDIR + fi + popd + fi +done diff --git a/Wrapping/Python/PackageUtility/imagefiles/install-libtiff.sh b/Wrapping/Python/PackageUtility/imagefiles/install-libtiff.sh new file mode 100755 index 0000000000..efd0520a98 --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/install-libtiff.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd /tmp/archive +tar -xzf tiff-4.0.9.tar.gz -C /tmp/ +cd /tmp/tiff-4.0.9 +./configure CC=/usr/local/bin/gcc CXX=/usr/local/bin/g++ +make +make install diff --git a/Wrapping/Python/PackageUtility/imagefiles/install.sh b/Wrapping/Python/PackageUtility/imagefiles/install.sh new file mode 100755 index 0000000000..f01d53b9db --- /dev/null +++ b/Wrapping/Python/PackageUtility/imagefiles/install.sh @@ -0,0 +1,70 @@ +NPROC=$(grep -c processor /proc/cpuinfo) + +export MAKEFLAGS="-j ${NPROC}" + +OPENSSL_ROOT=openssl-1.0.2h +OPENSSL_HASH=1d4007e53aad94a5b2002fe045ee7bb0b3d98f1a47f8b2bc851dcd1c74332919 +CMAKE_ROOT=cmake-3.7.2 + +function check_var { + if [ -z "$1" ]; then + echo "required variable not defined" + exit 1 + fi +} + +function do_openssl_build { + + ./config no-ssl2 no-shared -fPIC --prefix=/usr/local/ssl && + MAKEFLAGS="" make && + MAKEFLAGS="" make install +} + +function check_sha256sum { + local fname=$1 + check_var ${fname} + local sha256=$2 + check_var ${sha256} + + echo "${sha256} ${fname}" > ${fname}.sha256 + sha256sum -c ${fname}.sha256 + rm -f ${fname}.sha256 +} + + +function build_openssl { + local openssl_fname=$1 + check_var ${openssl_fname} + local openssl_sha256=$2 + check_var ${openssl_sha256} && + check_sha256sum ${openssl_fname}.tar.gz ${openssl_sha256} && + tar -xzf ${openssl_fname}.tar.gz && + (cd ${openssl_fname} && do_openssl_build) && + rm -rf ${openssl_fname} ${openssl_fname}.tar.gz +} + +build_openssl $OPENSSL_ROOT $OPENSSL_HASH || exit 1 + +tar xvzf ${CMAKE_ROOT}.tar.gz && +mkdir /tmp/cmake-build && +(cd /tmp/cmake-build && + ../${CMAKE_ROOT}/bootstrap --parallel=${NPROC} -- \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DCMAKE_USE_OPENSSL:BOOL=ON \ + -DOPENSSL_ROOT_DIR:PATH=/usr/local/ssl \ + -DCMAKE_USE_SYSTEM_CURL:BOOL=OFF && + make && + make install) || +exit 1 + +rm -rf /usr/local/ssl + +sed -i -e 's/3.4.8"/3.4.8","3.4.9"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.10"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.11"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.12"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.13"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.14"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.15"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.16"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json +sed -i -e 's/3.4.8"/3.4.8","3.4.17"/g' /opt/_internal/cpython-3.6.4/lib/python3.6/site-packages/auditwheel/policy/policy.json diff --git a/Wrapping/Python/PackageUtility/run.sh b/Wrapping/Python/PackageUtility/run.sh new file mode 100755 index 0000000000..81c8549417 --- /dev/null +++ b/Wrapping/Python/PackageUtility/run.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +if [ -n "$ExternalData_OBJECT_STORES" -a -d "$ExternalData_OBJECT_STORES" ] ; then + extra_args="-v ${ExternalData_OBJECT_STORES}:/var/io/.ExternalData -e ExternalData_OBJECT_STORES=/var/io/.ExternalData" +fi + +if [ ! -z "${MITK_GIT_TAG}" ] ; then + extra_args="${extra_args} -e MITK_GIT_TAG=${MITK_GIT_TAG}" +fi + +# example versions: "cp27-cp27m cp27-cp27mu cp36-cp36m" +if [ ! -z "${PYTHON_VERSIONS}" ] ; then + extra_args="${extra_args} -e PYTHON_VERSIONS=${PYTHON_VERSIONS}" +fi + +for ARCH in x86_64; do + # Docker container is build for a specific target plattfrom. + docker build --pull=true --rm=true -t mitk_manylinux_${ARCH} -f Dockerfile-${ARCH} . + + # Docker file is ran in order to generate the python wheels in it. + docker run --storage-opt size=150G --rm -e _USER=$(id -un) -e _USERID=$(id -u) -e_GROUPID=$(id -g) $extra_args -v $(pwd):/work/io -t pymitk_manylinux_${ARCH} + + # use this command to get an interactive prompt to debug behavior + #docker run --rm -i -t --entrypoint=/bin/bash -u=root $extra_args -v $(pwd):/var/io mitk_manylinux_${ARCH} +done + diff --git a/Wrapping/Python/Packaging/__init__.py b/Wrapping/Python/Packaging/__init__.py new file mode 100644 index 0000000000..13380c5106 --- /dev/null +++ b/Wrapping/Python/Packaging/__init__.py @@ -0,0 +1 @@ +from .pyMITK import * diff --git a/Wrapping/Python/Packaging/setup.py.in b/Wrapping/Python/Packaging/setup.py.in new file mode 100644 index 0000000000..b4c8215a58 --- /dev/null +++ b/Wrapping/Python/Packaging/setup.py.in @@ -0,0 +1,133 @@ +import sys +import os +import glob +import itertools as it + +def multiple_file_types(path, *patterns): + return it.chain.from_iterable(glob.iglob(os.path.join(path,pattern)) for pattern in patterns) + +try: + from setuptools import setup, Extension + from setuptools.command.build_ext import build_ext as _build_ext +except ImportError: + from distutils.core import setup, Extension + from distutils.command.build_ext import build_ext as _build_ext + +import re + +doc_files = "" +dependency_paths = "@MITK_RUNTIME_PATH@" +dependency_files = "@PYTHON_LIB_DEPENDENCIES@" +binary_module_file = "@TMP_MITK_BINARY_MODULE@" + +def get_pep386version(): + """This method examines the MITK's CMake version variables to make a pep 386 compliant version string when building a version indented for distribution.""" + sitkMAJOR = "@MITK_VERSION_MAJOR@" + sitkMINOR = "@MITK_VERSION_MINOR@" + sitkPATCH = "@MITK_VERSION_PATCH@" + sitkTWEAK = "@MITK_VERSION_TWEAK@" + sitkRC = "@MITK_VERSION_RC@" + sitkPOST = "@MITK_VERSION_POST@" + sitkDEV = "@MITK_VERSION_DEV@" + sitkHASH = "@MITK_VERSION_HASH@" + + + version = sitkMAJOR+"."+sitkMINOR + + if sitkPATCH: + version += "."+sitkPATCH + if sitkTWEAK: + version += "."+sitkTWEAK + + if sitkRC: + version += sitkRC + + if sitkPOST: + version += ".post"+sitkPOST + elif sitkDEV: + version += ".dev"+sitkDEV + + # Local Version Identifier + if sitkHASH and not "@MITK_BUILD_DISTRIBUTE@" in ['1', 'ON']: + version += "+g"+sitkHASH + + return version + +class build_ext(_build_ext): + """ Override standard command class to build an extension, to + simply copy an existing compiled library into the packaging + directory structure. + """ + + def build_extension(self, ext): + """ + """ + from distutils.errors import DistutilsSetupError + + sources = ext.sources + if sources is None or not len(sources) == 1: + raise DistutilsSetupError( "Expected only one compiled library." ) + + expected_ext_filename = os.path.split(self.get_ext_filename(ext.name))[1] + + ext_file = self.get_ext_fullpath(ext.name) + + abs_sources = list( map(os.path.abspath, sources) ) + + module_name=ext.name.split(".")[0] + placeholder = self.get_ext_filename("placeholder") + + for current_path in dependency_paths.split(";"): + for library_file in multiple_file_types(current_path, "*.pyd","*.so"): + if binary_module_file in library_file: + self.copy_file(library_file, ext_file) + continue + # Do not copy .so - files manually. They will be later added by auditwheel + for library_file in multiple_file_types(current_path, "*.dll"): + if "Qt" in library_file: + continue + library_basename=os.path.basename(library_file) + if library_basename not in dependency_files: + continue + library_target= self.get_ext_fullpath(module_name+".placeholder") + self.copy_file(library_file,library_target.replace(placeholder,library_basename)) + + #self.copy_file(abs_sources[0], ext_file) + + +setup( + name = 'pyMITK', + version = get_pep386version(), + author = 'Medical Image Computing, DKFZ Heidelberg', + author_email = 'm.goetz@dkfz-heidelberg.de', + ext_modules=[Extension('pyMITK._pyMITK', [r'@MITK_BINARY_MODULE@'])], + packages= ['pyMITK'], + package_dir = {'pyMITK':r'@MITK_PYTHON_PACKAGE_DIR@'}, + download_url = r'https://www.itk.org/MITKDoxygen/html/PyDownloadPage.html', + platforms = [], + description = r'MITK is a simplified interface to the Insight Toolkit (ITK) for image registration and segmentation', + long_description = 'MITK provides an abstraction layer to ITK that enables developers \ + and users to access the powerful features of the InsightToolkit in an easy \ + to use manner for biomedical image analysis.', + classifiers=[ + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: C++", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Education", + "Intended Audience :: Healthcare Industry", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Medical Science Apps.", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Software Development :: Libraries", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Operating System :: Unix", + "Operating System :: MacOS" + ], + license='Apache', + keywords = 'MITK ITK InsightToolkit segmentation registration', + url = r'http://mitk.org/', + cmdclass={'build_ext':build_ext} + ) diff --git a/Wrapping/Python/Packaging/setupegg.py b/Wrapping/Python/Packaging/setupegg.py new file mode 100644 index 0000000000..f110f9563c --- /dev/null +++ b/Wrapping/Python/Packaging/setupegg.py @@ -0,0 +1,17 @@ +""" +A setup.py script to use setuptools, which gives wheel and egg goodness, etc. +""" +try: + from setuptools import setup +except ImportError: + # MITK no longer provides ez_setup, but a copy may be around + # so we give it a try. It's intended that setuptools be install in + # a constructed virtualenv during the make process. + from ez_setup import use_setuptools + use_setuptools() +import os + +from setuptools import setup + +fn = os.path.dirname(os.path.realpath(__file__)) + '/setup.py' +exec(open(fn).read()) diff --git a/Wrapping/Python/dist/CMakeLists.txt b/Wrapping/Python/dist/CMakeLists.txt new file mode 100644 index 0000000000..504c94c5fa --- /dev/null +++ b/Wrapping/Python/dist/CMakeLists.txt @@ -0,0 +1,40 @@ +# +# Packaging +# +if( MITK_PYTHON_EGG OR MITK_PYTHON_WHEEL ) + if( NOT MITK_PYTHON_USE_VIRTUALENV ) + message( STATUS "Not using MITK's virtualenv for distribution!\n +Using unknown versions of pip, setuptools and/or wheel packages/" ) + endif() + + set(bdist_setup "${MITK_Python_BINARY_DIR}/Packaging/setup.py") + set(bdist_commands "") + + if( MITK_PYTHON_EGG ) + set(bdist_commands "bdist_egg") + endif() + + if( MITK_PYTHON_WHEEL ) + set(bdist_commands ${bdist_commands} "bdist_wheel") + endif() + + set( MITK_PYTHON_PLAT_NAME "" CACHE STRING + "Optional value passed to setup.py with the '--plat-name' argument") + + if( NOT "${MITK_PYTHON_PLAT_NAME}" STREQUAL "" ) + set(bdist_commands ${bdist_commands} "--plat-name" "${MITK_PYTHON_PLAT_NAME}") + endif() + + add_custom_target( dist.Python + ${VIRTUAL_PYTHON_EXECUTABLE} ${bdist_setup} ${bdist_commands} + WORKING_DIRECTORY ${MITK_Python_BINARY_DIR} + DEPENDS ${SWIG_MODULE_pyMITK_REAL_NAME} + COMMENT "Creating Python binary distribution" ) + + if( MITK_PYTHON_USE_VIRTUALENV ) + add_dependencies( dist.Python PythonVirtualEnv) + endif() + add_dependencies( dist dist.Python ) +elseif() + message( STATUS "Not creating dist.Python target since MITK_FORBID_DOWNLOADS is enabled" ) +endif() diff --git a/Wrapping/Python/mitkNumpyArrayConversion.cxx b/Wrapping/Python/mitkNumpyArrayConversion.cxx new file mode 100644 index 0000000000..305045f93d --- /dev/null +++ b/Wrapping/Python/mitkNumpyArrayConversion.cxx @@ -0,0 +1,234 @@ +/*========================================================================= +* +* 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 +* +* http://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. +* +*=========================================================================*/ + +#include +#include + +#include +#include + +#include "mitkImage.h" + + +// Python is written in C +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** An internal function that returns a memoryview object to the + * MITK Image's buffer (shallow). The correct copy and writing + * policies need to be done by the end-user method. + */ +static PyObject * +mitk_GetMemoryViewFromImage( PyObject *SWIGUNUSEDPARM(self), PyObject *args ) +{ + const void * mitkBufferPtr; + Py_ssize_t len; + std::vector< unsigned int > size; + size_t pixelSize = 1; + + unsigned int dimension; + + /* Cast over to a sitk Image. */ + PyObject * pyImage; + void * voidImage; + mitk::Image * mitkImage; + int res = 0; + + PyObject * memoryView = NULL; + Py_buffer pyBuffer; + memset(&pyBuffer, 0, sizeof(Py_buffer)); + + + if( !PyArg_ParseTuple( args, "O", &pyImage ) ) + { + SWIG_fail; // SWIG_fail is a macro that says goto: fail (return NULL) + } + res = SWIG_ConvertPtr( pyImage, &voidImage, SWIGTYPE_p_mitk__Image, 0 ); + if (!SWIG_IsOK(res)) + { + mitk::Image::Pointer tmpImage; + res = SWIG_ConvertPtr(pyImage, &voidImage, SWIGTYPE_p_itk__SmartPointerT_mitk__Image_t, 0); + if (!SWIG_IsOK(res)) + { + SWIG_exception_fail(SWIG_ArgError(res), "in method 'GetByteArrayFromImage', argument needs to be of type 'sitk::Image *'"); + } + tmpImage = *(reinterpret_cast(voidImage)); + voidImage = reinterpret_cast(tmpImage.GetPointer()); + } + mitkImage = reinterpret_cast< mitk::Image * >( voidImage ); + + mitkBufferPtr = mitkImage->GetData(); + pixelSize = mitkImage->GetPixelType().GetBitsPerComponent() / 8; + + dimension = mitkImage->GetDimension(); + for (int i = 0; i < dimension; ++i) + { + size.push_back(mitkImage->GetDimension(i)); + } + + // if the image is a vector just treat is as another dimension + if ( mitkImage->GetPixelType().GetNumberOfComponents() > 1 ) + { + size.push_back( mitkImage->GetPixelType().GetNumberOfComponents() ); + } + + len = std::accumulate( size.begin(), size.end(), unsigned int(1), std::multiplies() ); + len *= pixelSize; + + if (PyBuffer_FillInfo(&pyBuffer, NULL, (void*)mitkBufferPtr, len, true, PyBUF_CONTIG_RO)!=0) + { + SWIG_fail; + } + memoryView = PyMemoryView_FromBuffer(&pyBuffer); + + PyBuffer_Release(&pyBuffer); + return memoryView; + +fail: + Py_XDECREF( memoryView ); + return NULL; +} + +/** An internal function that performs a deep copy of the image buffer + * into a python byte array. The byte array can later be converted + * into a numpy array with the frombuffer method. + */ +static PyObject* +mitk_SetImageFromArray( PyObject *SWIGUNUSEDPARM(self), PyObject *args ) +{ + PyObject * pyImage = NULL; + + const void *buffer; + Py_ssize_t buffer_len; + Py_buffer pyBuffer; + memset(&pyBuffer, 0, sizeof(Py_buffer)); + + mitk::Image * mitkImage = NULL; + void * mitkBufferPtr = NULL; + size_t pixelSize = 1; + + unsigned int dimension = 0; + std::vector< unsigned int > size; + size_t len = 1; + + // We wish to support both the new PEP3118 buffer interface and the + // older. So we first try to parse the arguments with the new buffer + // protocol, then the old. + if (!PyArg_ParseTuple( args, "s*O", &pyBuffer, &pyImage ) ) + { + PyErr_Clear(); + +#ifdef PY_SSIZE_T_CLEAN + typedef Py_ssize_t bufSizeType; +#else + typedef int bufSizeType; +#endif + + bufSizeType _len; + // This function takes 2 arguments from python, the first is an + // python object which support the old "ReadBuffer" interface + if( !PyArg_ParseTuple( args, "s#O", &buffer, &_len, &pyImage ) ) + { + return NULL; + } + buffer_len = _len; + } + else + { + if ( PyBuffer_IsContiguous( &pyBuffer, 'C' ) != 1 ) + { + PyBuffer_Release( &pyBuffer ); + PyErr_SetString( PyExc_TypeError, "A C Contiguous buffer object is required." ); + return NULL; + } + buffer_len = pyBuffer.len; + buffer = pyBuffer.buf; + } + + /* Cast over to a sitk Image. */ + { + void * voidImage; + int res = 0; + res = SWIG_ConvertPtr( pyImage, &voidImage, SWIGTYPE_p_mitk__Image, 0 ); + if (!SWIG_IsOK(res)) + { + mitk::Image::Pointer tmpImage; + res = SWIG_ConvertPtr(pyImage, &voidImage, SWIGTYPE_p_itk__SmartPointerT_mitk__Image_t, 0); + if (!SWIG_IsOK(res)) + { + SWIG_exception_fail(SWIG_ArgError(res), "in method 'GetByteArrayFromImage', argument needs to be of type 'sitk::Image *'"); + } + tmpImage = *(reinterpret_cast(voidImage)); + voidImage = reinterpret_cast(tmpImage.GetPointer()); + } + mitkImage = reinterpret_cast< mitk::Image * >(voidImage); + } + + try + { + mitkBufferPtr = mitkImage->GetData(); + pixelSize= mitkImage->GetPixelType().GetBitsPerComponent() / 8; + } + catch( const std::exception &e ) + { + std::string msg = "Exception thrown in MITK new Image: "; + msg += e.what(); + PyErr_SetString( PyExc_RuntimeError, msg.c_str() ); + goto fail; + } + + dimension = mitkImage->GetDimension(); + for (int i = 0; i < dimension; ++i) + { + size.push_back(mitkImage->GetDimension(i)); + } + + // if the image is a vector just treat is as another dimension + if (mitkImage->GetPixelType().GetNumberOfComponents() > 1) + { + size.push_back(mitkImage->GetPixelType().GetNumberOfComponents()); + } + + len = std::accumulate(size.begin(), size.end(), unsigned int(1), std::multiplies()); + len *= pixelSize; + + if ( buffer_len != len ) + { + PyErr_SetString( PyExc_RuntimeError, "Size mismatch of image and Buffer." ); + goto fail; + } + + memcpy( (void *)mitkBufferPtr, buffer, len ); + + + PyBuffer_Release( &pyBuffer ); + Py_RETURN_NONE; + +fail: + PyBuffer_Release( &pyBuffer ); + return NULL; +} + + + +#ifdef __cplusplus +} // end extern "C" +#endif